1

I have encountered problem with updating data in AngularJS directive.

The directive loads list of orders when initialized, and then watches the variable orderMade. If this variable is changed, it should reload the list of orders.

.directive('listRingorders', ['ringsService',function(ringsService){
  return {
    restrict: 'AE',
    templateUrl : 'pages/list-ringorders.tpl.html',
    scope : { 
        orderMade : '='
    },                                                                      
    controllerAs : 'RingOrderListCtrl',
    bindToController: true,
    controller : function (){

    // variables
    var self = this;

    // load data
    ringsService.fetchRingOrders()
        .then(function(data){
          self.ringorders = data;
        }, function(data){
          alert("Error");
      });

      //log orders
      this.test = function(){
        console.log(self.ringorders);
      }

    },
    link: function (scope, element, attrs) {
            scope.$parent.$watch(attrs.orderMade, function() {
                ringsService.fetchRingOrders()
                  .then(function(data){
                        scope.ringorders = data;
                   }, function(data){
                        alert("Error");
                });
            });
        }
  }
}]);

And here is html template (simplyfied)

<div ng-repeat="ringOrder in RingOrderListCtrl.ringorders">
  <h3>Order number: {{ringOrder.ID}}</h3>
</div>

I can correctly capture changing value orderMade and reload data, but when I update the scope.ringorders variable, the list does not update (HTML page shows the same data). Also when I log self.ringorders in controller's test() function, it contains old data.

My question is: how to update directive's scope data from link function?

UPDATE

I have figured out the solution - I was accessing the scope of controller function in directive instead of accesing teh scope of directive itself.

Here is correct template (just replace RingOrderListCtrl.ringorders with ringorders)

<div ng-repeat="ringOrder in ringorders">
  <h3>Order number: {{ringOrder.ID}}</h3>
</div>
5
  • Have you tried to add scope.$apply() in your then method after you added ringorders to scope? Commented Oct 8, 2015 at 19:09
  • Calling scope.$apply causes Error: [$rootScope:inprog] $digest already in progress Commented Oct 8, 2015 at 19:17
  • OK, then the digest is already in progress. Sometimes it helps with asynch data. Where have you added your test method call? Can you please add the code of your ringService maybe that helps to see the issue? Commented Oct 8, 2015 at 19:24
  • thanks, I have just found the solution - turned out I was accesing wrong scope - see updated question Commented Oct 8, 2015 at 19:29
  • Well, about two minutes too late :/ glad you figured it out. Commented Oct 8, 2015 at 19:31

1 Answer 1

2

Your problem is that you're binding data to two different places (the controller, via controllerAs and onto scope). In your directive's link function, you can access the directive's controller by passing in a fourth argument:

link: function listRingOrdersLink(scope, element, attributes, ctrl) {
    scope.$watch(function() {
        /**
         * bindToController puts this info 
         * on the controller object
         */
        return ctrl.orderMade;
     }, function(newValue, oldValue) {
        ringService.fetchRingOrders()
            .then(function(data) {
                /** put the new data on the controller */
                ctrl.ringorders = data;
            }, function(data) { alert(data); });
     });
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.