[英]How to watch a model from a directive in the context of its source scope AngularJS
我需要从指令中观察模型。
angular.module('app', [])
.directive('myDirective', [function() {
return {
restrict: 'A',
scope: {
modelToWatch: '@'
},
link: function(scope, element, attrs) {
scope.$watch(scope.modelToWatch, function(val) {
// do something...
});
}
};
]})
.controller('MyController', ['$scope', function($scope) {
$scope.obj = {
foo: 'val'
};
}]);
<div ng-controller="MyController">
<div my-directive model-to-watch="obj.foo"></div>
</div>
以上工作正常。
但是,当模型的实际所有者与指令之间存在中间作用域时,我会遇到问题。
我使用另一个控制器来演示以下情况:
.controller('AnotherController', ['$scope', function($scope) {}])
<div ng-controller="MyController">
<div ng-controller="AnotherController">
<div my-directive model-to-watch="obj.foo"></div>
</div>
</div>
在上述情况下,我可以使用下面的代码查找$ parent树以找到拥有我要监视的属性的范围:
...
link: function(scope, element, attrs) {
var contextScope = scope;
// find for the scope which owns the property that we want to watch
while (contextScope != null && contextScope.hasOwnProperty(attrs.modelToWatch)) {
contextScope = contextScope.$parent;
}
// use the scope found to watch the model
if (contextScope != null) {
contextScope.$watch(scope.modelToWatch, function(val) {
// do something...
});
}
}
但是,另一个问题是,如果modelToWatch是一个复杂的表达式(例如:“ tableParams.filter()。shop_id”),则无法依赖hasOwnProperty。
有没有一种简单的方法可以在其所有者范围内查看模型? 还是有可能甚至从原型孩子那里观看模特儿?
或者我可以将范围作为参数传递,因此至少不必寻找它...
restrict: 'A',
scope: {
modelToWatch: '@',
sourceScope: '=', // don't know how to do this..
}
注意:我需要使用隔离范围
正如@pixelbit所建议的那样,我尝试使用$ eval查找正确的范围
link: function(scope, element, attrs) {
var contextScope = scope;
// find for the scope which owns the property that we want to watch
while (contextScope != null && contextScope.$eval(attrs.modelToWatch) != undefined) {
contextScope = contextScope.$parent;
}
...
}
在大多数情况下都适用,除了modelToWatch表达式实际上计算为undefined时。在当前范围中不存在modelToWatch(意味着它不是所有者)还是modelToWatch表达式恰好计算为undefined时存在歧义。
不需要隔离的作用域-您可以继承作用域。 同样,为了处理复杂的表达式,您可以使用scope。$ eval评估模型并找到适当的范围。 评估模型后,请从受监视的函数返回它:
angular.module('app', [])
.directive('myDirective', [function() {
return {
restrict: 'A',
scope: false,
link: function(scope, element, attrs) {
scope.$watch(function() {
return scope.$eval(attrs.modelToWatch);
}, function(val) {
// do something...
});
}
};
]})
如果必须使用隔离范围,请观察一个函数并返回模型:
angular.module('app', [])
.directive('myDirective', [function() {
return {
restrict: 'A',
scope: {
modelToWatch: '='
},
link: function(scope, element, attrs) {
scope.$watch(function() {
return scope.modelToWatch;
}, function(val) {
// do something...
});
}
};
]})
您可以在指令内部直接声明一个控制器:
angular.module('app', [])
.directive('myDirective', [function() {
return {
restrict: 'A',
scope: {
modelToWatch: '='
},
link: function(scope, element, attrs) {
scope.$watch(scope.modelToWatch, function(val) {
// do something...
});
},
controller: 'MyController'
};
]})
.controller('MyController', ['$scope', function($scope) {
$scope.obj = {
foo: 'val'
};
}]);
<div my-directive model-to-watch="obj.foo"></div>
这样,当您调用指令时,将首先实例化控制器,然后将执行链接,并共享相同的作用域。
您可以观看一个函数:
scope.$watch(function() {
return scope.modelToWatch;
}, function(val) {
// do something
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.