Search code examples
javascriptangularjsscopecomponentscreatejs

AngualrJS: Why isn't Component scope binding?


I have come across an issue and created a JSFiddle to demonstrate

var myApp = angular.module("myApp", []);
myApp.component("bar", {
    transclude: true,
    template: '<div ng-transclude></div>',
    controller: function ($scope, $element, $attrs) {
                        $scope.msg = "Hello";
            setTimeout(function(){
                $scope.msg = "Goodbye";
                alert($scope.msg);
            }, 3000)
    }
});

HTML:

<body ng-app="myApp">
    <bar>
        {{ $parent.msg }}
    </bar>
</body>

As you can see I have a scope variable (msg) that I am updating after I do some work (setTimeout in this case). There seems to be only one-way binding in the HTML, because "Goodbye" is never rendered to the view when the component's scope is updated.

Am I correct to be using $parent? Have I got my scope all wrong? Am I handling transclusion properly?

Edit

I should say that setTimeout is only a example, in my real world case I am trying to add components for http://www.createjs.com/ Instead of setTimeout I was actually adding a 'complete' event listener to a PreLoadJS LoadQueue http://www.createjs.com/docs/preloadjs/classes/LoadQueue.html


Solution

  • the reason is you are doing this inside setTimeout which is not in angular context. Any time you update scope outside of angular context you need to notify angular to run a digest to update view

    Angular provides a service $timeout that takes care of this for you.

    Try:

    controller: function ($scope, $element, $attrs, $timeout) {
            $scope.msg = "Hello";
            $timeout(function(){
                $scope.msg = "Goodbye";
                alert($scope.msg);
            }, 3000)
    }
    

    DEMO