我试图在控制器函数中访问指令的属性。但是,当我访问它时,它是未定义的。我注意到如果我做一个简单的计时器就行了。有没有办法只在指令执行后才能执行代码,并且它的范围已准备好并设置为使用?
我做了一个小提琴。确保您的控制台已打开。 http://jsfiddle.net/paulocoelho/uKA2L/1/
以下是我在小提琴中使用的代码:
<div ng-app="testApp" >
<testcomponent text="hello!"></testcomponent>
</div>
var module = angular.module('testApp', [])
.directive('testcomponent', function () {
return {
restrict: 'E',
template: '<div><p>{{text}} This will run fine! </p></div>',
scope: {
text: '@text'
},
controller: function ($scope, $element) {
console.log($scope.text); // this will return undefined
setTimeout(function () {
console.log($scope.text); // this will return the actual value...
}, 1000);
},
link: function ($scope, $element, $attrs) {
console.log($scope.text);
setTimeout(function () {
console.log($scope.text);
}, 1000);
}
};
});
答案 0 :(得分:27)
答案 1 :(得分:25)
在隔离范围中,无法在链接函数中访问使用“@”定义的局部范围属性。正如@remigio已经提到的那样,此时此类本地范围属性为undefined
。 $ attrs。$ observe()或$ scope。$ watch()必须用于异步获取(插值)值。
如果要在属性中传递一个常量值(即,不需要插值,即属性的值不包含任何{{}} s),则不需要'@'或$ observer或$看。您可以使用$ attrs。 attribute_name 一次,如@hugo建议的那样,或者如果您要传递数字或布尔值并且想要获得正确的类型,则可以使用$ scope。$ eval($ attrs 。 attribute_name )一次。
如果使用'='将本地范围属性数据绑定到父范围属性,则该属性的值将在链接函数中可用(无需$ observe或$ watch或$ eval)。
答案 2 :(得分:8)
自Angular 1.3起,您可以使用bindToController
。这是我如何使用它的示例。在这里,我将属性添加到范围,然后使用bindToController
在控制器中使用它:
var module = angular.module('testApp', [])
.directive('testcomponent', function () {
return {
restrict: 'E',
template: '<div><p>{{text}} This will run fine! </p></div>',
scope: {
text: '@text'
},
controller: function () {
console.log(this.text);
},
controllerAs: 'vm',
bindToController: true
};
});
Angular 1.3为指令定义引入了一个新属性 对象名为bindToController,它完全按照它所说的去做。什么时候 在具有使用controllerAs的隔离范围的指令中设置为true, 组件的属性绑定到控制器而不是 范围。这意味着,当控制器出现时,Angular会确保这一点 实例化后,隔离范围绑定的初始值为 可用于此,未来的更改也会自动进行 可用。
答案 3 :(得分:6)
相反,使用$scope
来获取指令属性值,我个人更喜欢$attrs
用于controller
函数,或仅attrs
用于link
的第3个参数功能。通过以下代码在没有超时的情况下从controller
获取属性值时,我没有问题:
var module = angular.module('testApp', [])
.directive('testcomponent', function () {
return {
restrict: 'E',
template: '<div><p>{{text}} This will run fine! </p></div>',
scope: {
text: '@text'
},
controller: ['$scope','$attrs', function ($scope, $attrs) {
console.log($attrs.text); // just call to the $attrs instead $scope and i got the actual value
$scope.text = $attrs.text; //assign attribute to the scope
}]
};
});
答案 4 :(得分:1)
在$ digest循环之前调用link函数,此时范围变量未定义。查看this chapter和this other以了解链接功能的运作方式。您只使用链接函数来定义指令的监视和/或行为,而不是操纵模型,这在控制器中完成。
答案 5 :(得分:0)
如果从指令访问此值以使用指令插入视图,则可以使用$ compile api访问此属性并执行类似此操作
var string = "<div> " + scope.text + "</div>";
$compile(string)(scope, function(cloned, scope){
element.append(cloned);
});