0

I am trying to make two controllers comunicate via a service in Angularjs. The service 'playerFocus' works fine at the model level, but the view gets not updated. I refer in particular to the variable show inside the ModalDialogController, that turns correctly to true but remains false in the view. Here is the complete js:

(function(){

var players = [
    {
        id: 1,
        name: 'Charles Foley',
        photo: 'images/gem-01.gif'
    },
    {
        id: 2,
        name: 'Pippo',
        photo: 'images/gem-02.gif'
    },
    {
        id: 3,
        name: 'Roberto',
        photo: 'images/gem-03.gif'
    }
];

var app = angular.module('soccer-match', []);

app.service('playerFocus', function(){
    var subscriber = undefined;

    this.sendMessage = function(mex){
        subscriber(mex);
    };

    this.onMessage = function(callback){
        subscriber = callback;
    };
});

app.controller('PlayersListController', ['$scope', 'playerFocus', function($scope, playerFocus){
    $scope.players = players;

    $scope.playerDialog = function(p){
        playerFocus.sendMessage(p);         
    };
}]);

app.controller('ModalDialogController', ['$scope', 'playerFocus', function($scope, playerFocus){

    $scope.player = undefined;
    $scope.show = false;

    $scope.focusPlayer = function(p) {
        for(i in players){
            if(players[i].id == p){ // PROBLEM HERE
                $scope.$apply( function(){
                    $scope.player = players[i];
                    $scope.show = true;
                });
            }
        }
    };


    playerFocus.onMessage($scope.focusPlayer); // PROBLEM HERE
}]);

And the html template:

            <!-- players list -->
        <div id="players-list" ng-controller="PlayersListController">
            <div ng-repeat="player in players">

                <!-- player -->
                <div class="player">    
                    <img class="player-thumb" ng-src="{{player.photo}}"}}>
                    <div class="player-info">
                        <p>{{player.name}}</p>
                        <button ng-click="playerDialog(player.id)" type="button" class="btn btn-default player-info-btn">Info</button>
                    </div>
                </div>

            </div>

            <!-- add player -->
            <div class="player">    
                <img class="player-thumb" src="images/default.png"}}>
                <div class="player-info">
                    <p>- ??? -</p>
                    <button type="button" class="btn btn-success player-info-btn">Nuovo Giocatore</button>
                </div>
            </div>

        </div>

    </div>

    <!-- player modal dialog -->
    <div ng-controller="ModalDialogController">
        <div class="modal-dialog" ng-show="{{show}}">
            {{player}}{{show}}
        </div>
    </div>

I searched for a solution the whole day, one being to use $apply to force the sync of model and view after the service callback, but I get this error. I am really confused on this and Angular docs are way too complicated for my level of understanding.

Community
  • 1
  • 1
Pieroit
  • 1
  • 2
  • I suggest that you post your HTML. If your view isn't updating, its likely you have a binding issue. – Michael Kang Jun 19 '14 at 09:30
  • HTML added, thank you. I think it is not a binding problem, because in the console I can see ng-show=true, the view just gets not updated... xD – Pieroit Jun 19 '14 at 09:41
  • It *is* a binding issue. Your views are bound to different scope variables on multiple controllers: {{ player }} and {{ show }}. Since they are different scope variables, there is no binding between them, so you should not expect them to update their views in synch. – Michael Kang Jun 19 '14 at 09:47
  • Sorry to bother you @pixelbits but I can't follow. If there is a binding problem why in the console > elements I can see the right data? – Pieroit Jun 19 '14 at 09:55
  • Its the binding of the model to the views that's broken. Your ModalDialogController and your PlayersListController are on sister scopes. If you set a scope variable on one controllers' scope, it won't update the other and vice versa because they are separate scopes. Scopes *can* inherit each other's scope variables, in which case, they could possibly bind to the same scope variable - but in this case they are sister scopes. – Michael Kang Jun 19 '14 at 10:02
  • Ok I understand that the two scopes are siblings, and that's why I created the playerFocus service. The service does in fact let the two controllers share a message, and the variable in the scope gets changed! p.s.: I appreciate really much your intervention – Pieroit Jun 19 '14 at 10:34
  • I see, my apologies for not understanding. One thing to know about view bindings ({{player}} {{show}}) that might help you is that they must be bound to the same variable on the same scope in order for them to get updated and stay in synch. Scope inheritance comes into play here - if the variable is not found in current scope, it will look for the variable in parent scope, etc. So it is possible that they do inherit the same variable on the same scope. I can't see from your HTML that the views are bound to the same scope, but maybe I can't see all of your HTML. – Michael Kang Jun 19 '14 at 10:41
  • Oh... just noticed something. Get rid of the curlies in your ng-show. It should be: ng-show="show" – Michael Kang Jun 19 '14 at 10:43
  • Models are placed on the scope, and bindings are setup between the model and the view. If you want to share scope variables, you should not devise a service to do it (I'm not even sure how you could do it). Instead, take advantage of scope inheritance and the fact that scope variables may be inherited. I suggest binding your views to a parent controller's scope (parent of ControllerA and ControllerB). Also, be aware that when you do $scope.var = value; it does not look up 'var' using scope inheritance rules. It just creates a new var on $scope. This could lead to binding issues too. – Michael Kang Jun 19 '14 at 10:50
  • I am going to switch strategy and try with the parent controller. Thank you for your time :) – Pieroit Jun 19 '14 at 10:56
  • Hey really the problem were the curly braces! You were right. – Pieroit Jun 19 '14 at 11:18

1 Answers1

0

I think you can refactor it to use service as two-way databinding (no $apply), It looks all to complicated in your code

http://plnkr.co/edit/pt2xwlYqvY3r840tHJ92?p=info

maurycy
  • 8,455
  • 1
  • 27
  • 44