Mr Kohn Doew
Mr Kohn Doew

Reputation: 277

Angular accordion doesn't update UI when data source has been changed

I start learning Angular and faced with some strange behaviour.

I want to add a new header to accordion dynamically but I accordion doesn't reflect it on UI till I explicitly click on some of his items. By some reason he doesn't react on items changes before it starts load itserlf aggain durnig DOM rendering.

var mainApp = angular.module('ui.bootstrap.demo', ['ui.bootstrap', 'ngResource']);
mainApp.factory('teamSharedObj',['$rootScope', function($rootScope) {
    return {
        teams: [],
        peopleInTeam: [],
        addNewTeam: function(item) {
            console.log("add new team: " + item);
            this.teams.push(item);
            $rootScope.$broadcast('team.new');
        },
        addTeamMembers: function(team, teamMembers) {
            for (var i = 0; i < teamMembers.length; i++) {
                var temp;
                // put in team as key-value pair
                temp[team] = teamMembers[i]
                console.log("add new team member: " + temp);
                peopleInTeam.push(temp);
            }
            if (teamMembers.length != 0) {
                $rootScope.$broadcast('teamMember.new');
            }
        }
    }
}]);

mainApp.directive("addNewTeam", ['teamSharedObj', 'teamSharedObj', function (teamSharedObj) {
    return {
        restrict: 'A',
        link: function( scope, element, attrs ) {
            element.bind('click', function() {
                console.log(scope.teamName)
                teamSharedObj.addNewTeam(scope.teamName)
            });
        }
    }
}])

mainApp.controller('teamListCtrl', ['$scope', 'teamSharedObj', function($scope, teamSharedObj) {
    $scope.$on('team.new', function(event) {
            console.log('new team ' + event);
            $scope.items = teamSharedObj.teams;
        }
    );
    $scope.oneAtATime = true;
    $scope.items = ['new', 'another one'];//teamSharedObj.teams;
}]);


<!DOCTYPE html>
<html>
<head lang="en">
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.js"></script>
    <script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular-resource.js"></script>
    <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.2.js"></script>
    <script src="js/test.team.js"></script>

    <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">



</head>
<body ng-app="ui.bootstrap.demo">

    <div id="teamBlock">
        <input type="text" ng-model="teamName" >
        <input add-new-team type="submit" value="Add new team" >
        <!--<button add-book-button>Add data</button>-->
    </div>

    <div>
        {{teamName}}
    </div>

    <div ng-controller="teamListCtrl">
        <accordion close-others="oneAtATime" >
            <accordion-group heading="{{d}}" ng-repeat="d in items">
                This content is straight in the template.

            </accordion-group>
        </accordion>

        <div ng-repeat="item in items">{{item}}</div>
    </div>



</body>
</html>

Can you suggest me please a right way to notifu component about changes in its datasource?

Upvotes: 2

Views: 1570

Answers (1)

tasseKATT
tasseKATT

Reputation: 38490

bind is jqLite/jQuery method and does not automatically trigger the digest loop for you. This means no dirty checking will take place and the UI will not be updated to reflect the model changes.

To trigger it manually wrap the code in a call to $apply:

element.bind('click', function() {
  scope.$apply(function () {
    teamSharedObj.addNewTeam(scope.teamName);
  });
});

And since teamSharedObj contains a reference to the array the controller can reference it directly. Then you do not need to use $broadcast:

addNewTeam: function(item) {
  this.teams.push(item);
},

And:

mainApp.controller('teamListCtrl', ['$scope', 'teamSharedObj',
  function($scope, teamSharedObj) {

    $scope.oneAtATime = true;
    $scope.items = teamSharedObj.teams;
  }
]);

Demo: http://plnkr.co/edit/ZzZN7wlT10MD0rneYUBM?p=preview

Upvotes: 2

Related Questions