Watch controller model value from inside directive

有些话、适合烂在心里 提交于 2019-12-17 23:40:54

问题


I am trying to have angular watch the $viewValue of a controller from inside a directive.

fiddle: http://jsfiddle.net/dkrotts/TfTr5/5/

function foo($scope, $timeout) {
    $scope.bar = "Lorem ipsum";

    $timeout(function() {
        $scope.bar = "Dolor sit amet";
    }, 2000);
}

myApp.directive('myDirective', function() {
    return {
        restrict: 'A',
        require: '?ngModel',
        link: function (scope, element, attrs, controller) {
            scope.$watch(controller.$viewValue, function() {
                console.log("Changed to " + controller.$viewValue);
            });
        }
    } 
});

As is, the $watch function is not catching the model change done after 2 seconds from inside the controller. What am I missing?


回答1:


$watch accepts the "name" of the property to watch in the scope, you're asking it to watch the value. Change it to watch attrs.ngModel which returns "bar", now you're watching scope.bar. You can get the value the same way you were or use scope[attrs.ngModel] which is like saying scope["bar"] which again, is the same as scope.bar.

scope.$watch(attrs.ngModel, function(newValue) {
    console.log("Changed to " + newValue);
});

To clarify user271996's comment: scope.$eval is used because you may pass object notation into the ng-model attribute. i.e. ng-model="someObj.someProperty" which won't work because scope["someObj.someProperty"] is not valid. scope.$eval is used to evaluate that string into an actual object so that scope["someObj.someProperty"] becomes scope.someObj.someProperty.




回答2:


Wanted to add: in 1.2.x, with isolated scope, the above wont work. http://jsfiddle.net/TfTr5/23/

A workaround I came up with was using the fact that $watch also accepts a function, so you can access your controller using that.

scope.$watch(
    function(){return controller.$viewValue},
    function(newVal, oldVal){
        //code
    }
)

Working fiddle: http://jsfiddle.net/TfTr5/24/

If anyone has an alternative, I would gladly welcome it!




回答3:


If you want to bind a value inside isolated scope,there are 2 ways to do it.The first way you can use even you don't have isolated scope.Here are the ways:

1) use $attrs.any_attribute and bind it (set in watch)

2) use 2 ways binding ('=') method and set it into listener

if you want more with examples here is a great article

http://www.w3docs.com/snippets/angularjs/bind-variable-inside-angularjs-directive-isolated-scope.html




回答4:


If you want debounce on a model value, it is worth mentioning the debounce setting in ng-model-option:

<input type="text" ng-model-options="{ debounce: 1000 }" ng-model="search"/>

For example: this watch is trigger 1000 ms after change and reset at new changes.

scope.$watch(attrs.ngModel, function(newValue) { });

https://docs.angularjs.org/api/ng/directive/ngModelOptions



来源:https://stackoverflow.com/questions/14567908/watch-controller-model-value-from-inside-directive

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!