最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - From my directive, how can I manually trigger a digest cycle on my parent scope? - Stack Overflow

programmeradmin1浏览0评论

I have a directive that I would like to force render when a change is made to an underlying model programmatically. $scope.$apply is idiomatic. But I am unable to get the directive to render without clicking repeatedly on the UI (which presumably manually forces the digest).

Can someone help me identify how to manually trigger the digest?

Even this.scope.$root.$apply() has no effect.

Grabbing hold of a parent DOM node and getting the associated scope, then calling $apply on that from the console, does work however.

When using this DOM node approach in the code it does not work however. Why might this be?

I have a directive that I would like to force render when a change is made to an underlying model programmatically. $scope.$apply is idiomatic. But I am unable to get the directive to render without clicking repeatedly on the UI (which presumably manually forces the digest).

Can someone help me identify how to manually trigger the digest?

Even this.scope.$root.$apply() has no effect.

Grabbing hold of a parent DOM node and getting the associated scope, then calling $apply on that from the console, does work however.

When using this DOM node approach in the code it does not work however. Why might this be?

Share edited Aug 4, 2015 at 22:04 C1pher 1,9726 gold badges34 silver badges52 bronze badges asked Aug 4, 2015 at 15:26 Ben AstonBen Aston 55.8k69 gold badges220 silver badges349 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 4

Two things to note:

  1. Scopes inherit from each other prototypically and form a tree. Scopes have a reference to $parent which can be used to traverse.
  2. A digest cycle is something that happens on a scope object. Ie. $scope.$digest(). This runs a digest on the scope, and then recursively does the same for all of the child scopes. $scope.$apply() is like doing $rootScope.$digest(). Since it starts at the root, it calls a digest on every other scope. So $apply might be excessive.

To answer your question, scope.$parent.$digest() will trigger a digest on scope's parent.


But it seems that the triggering of the digest isn't actually your problem. $apply will trigger digests on all scopes, so if that isn't working for you, I don't think your problem is simply that you need a digest to be triggered.

Perhaps you don't need the whole directive to re-render, but just need a part of it to update? If so, consider data binding to some shared service like this.

HTML

<div ng-app='app'>
  <one></one>
  <two></two>
</div>

JS

angular
  .module('app', [])
  .directive('one', function() {
    return {
      restrict: 'E',
      scope: {},
      template: "<input ng-model='shared.val'> {{ shared.val }}",
      controller: function($scope, Shared) {
        $scope.shared = Shared;
      }
    };
  })
  .directive('two', function() {
    return {
      restrict: 'E',
      scope: {},
      template: '<p> {{ shared.val }}</p>',
      controller: function($scope, Shared) {
        $scope.shared = Shared;
      }
    };
  })
  .factory('Shared', function() {
    return {
      val: ''
    };
  });

It somewhat depends. It sounds like $parent is what you want to call. scope.$root simply holds a reference to $rootScope (not your parent element scope). Short answer - try the following...

scope.$parent.$apply()

Longer answer - the above assumes your child directive scope inherits from your parent via scope: true. See SO answer How to access parent scope from within a custom directive with own scope in AngularJS? for more detail on the topic and other possible approaches to access the parent scope. Once you get a handle on your parent scope, just call $apply() on it.

I've made an example which modifies the parent scope on a jQuery .click() event. Consider the following and observe the parent behavior...

app.directive('parent', function() {
    return {
        link: function(scope, elem, attrs) {
             scope.value = 'parent'            
        }
    }
});

app.directive('child', function() {
    return {
        scope: true,
        link: function(scope, elem, attrs) {

            scope.value = 'child'

            elem.click(function() {
                scope.$parent.value = 'modded!!' // -- previously 'parent' 
                scope.$parent.$apply();
            })
        }
    }
});

JSFiddle Link - working example

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论