37

我正在尝试访问控制器函数中指令的属性。但是,当我访问它时,它是未定义的。我注意到,如果我做一个简单的计时器,它就可以工作。有没有办法仅在指令及其范围准备好并设置为可以使用之后才执行代码?

我做了一个小提琴。确保您的控制台已打开。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);
        }
    };
});
4

6 回答 6

27

有效的是,如果你设置

scope.text = $attrs.text;

在链接和控制器功能内部。这只会在最初起作用,因为没有 2way 数据绑定。不过,您可以使用$attrs.observe

见小提琴:http: //jsfiddle.net/JohannesJo/nm3FL/2/

于 2013-03-01T05:50:46.103 回答
25

在隔离作用域中,不能在链接函数中访问使用“@”定义的局部作用域属性。正如@remigio 已经提到的那样,这种本地范围属性就undefined在此时。$attrs.$observe() 或 $scope.$watch() 必须用于异步获取(插值)值。

如果您在属性中传递一个常量值(即,不需要插值,即属性的值不包含任何 {{}}),则不需要“@”或 $observer 或 $watch。您可以使用 $attrs。正如@hugo 建议的那样, attribute_name一次,或者如果您传递一个数字或布尔值并且想要获得正确的类型,您可以使用一次 $scope.$eval($attrs.attribute_name )

如果您使用 '=' 将本地范围属性数据绑定到父范围属性,则该属性的值将在链接函数中可用(不需要 $observe 或 $watch 或 $eval)。

于 2013-03-01T22:17:43.173 回答
9

从 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 确保在实例化控制器时,隔离范围绑定的初始值在此可用,并且将来的更改也自动可用。

于 2015-11-29T06:57:18.440 回答
7

而不是使用$scope获取指令属性值,我个人更喜欢使用$attrs函数controller,或者只是函数attrs的第三个参数linkcontroller在没有超时的情况下通过以下代码从 a 获取属性值时我没有问题:

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
    }]
    };
});
于 2016-06-14T07:52:37.150 回答
1

在 $digest 循环之前调用链接函数,此时范围变量未定义。查看本章其他章节以了解链接功能如何运作。您仅使用链接功能来定义指令的监视和/或行为,而不是操纵模型,这是在控制器中完成的。

于 2013-03-01T07:35:43.200 回答
0

如果您从指令访问此值以使用指令插入到您的视图中,您可以使用 $compile api 访问此属性并执行类似的操作

var string = "<div> " + scope.text + "</div>";
$compile(string)(scope, function(cloned, scope){
       element.append(cloned);
});
于 2015-04-28T21:32:58.067 回答