简体   繁体   中英

Using a $apply inside a $watch

I have a non-isolate scope directive. I don't want to isolate it because it needs to be on elements with other directives. Yet I need to watch an item on scope. So I tried this:

scope.$watch(function() {
     return scope.$apply(attrs.myAttribute);
}, function(val) {
     return val ? doSomething():doSomethingElse();
});

This does not work because angular throws a digest cycle already in progress error. So my question is, how can I dynamically watch an item on scope with a non-isolate directive.

Thanks,

Not entirely sure what your difficulties are watching the item if it is on scope already. Could you elaborate a bit on this? Regardless, here are two solutions which should cover almost all cases. To watch attribute changes, observe the following...

scope.$watch(function() {
    return elem.attr('my-attribute');
}, function(n, o) {
    if(n) 
        console.log(n);
});

JSFiddle Link - watch attribute demo


But, I suspect you are having difficulty getting the item on scope. If so, here is a way to assign it via $observe then watch it from there without an isolate...

attrs.$observe('myAttribute', function(value) {
    scope.myValue = value;
});

scope.$watch('myValue', function(n, o) {
    if(n) 
        console.log(n);
});

JSFiddle Link - watch attribute demo via $observe

You don't want to call $apply inside of a $watch callback because scope.$watch internally calls $apply for you, which is why you are getting the "digest cycle already in progress error" error.

Instead you can simply do:

scope.$watch(attrs.myAttribute, function(val){
  return val ? doSomething() : doSomethingElse();
};

The expression set to myAttribute will get evaluated against the scope of the element on which your directive sits since, like you mentioned, it is not isolated. And when the return value changes, the callback function will get invoked.

For example, if your HTML looked something like this

<div myNoNewScopeDirective myAttribute="doThis(value)"></div>

doThis(value) will get evaluated against the scope associated with the div element and its return value will be watched by your myNoNewScopeDirective . As a result, any change to such value will trigger the callback you provided and when val is truthy, doSomething will get invoked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM