AngularJS指令属性来自控制器的访问

时间:2013-03-01 05:26:40

标签: javascript events controller angularjs angularjs-directive

我试图在控制器函数中访问指令的属性。但是,当我访问它时,它是未定义的。我注意到如果我做一个简单的计时器就行了。有没有办法只在指令执行后才能执行代码,并且它的范围已准备好并设置为使用?

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

6 个答案:

答案 0 :(得分:27)

如果你设置了

,那么有效
scope.text = $attrs.text;

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

请参阅小提琴:http://jsfiddle.net/JohannesJo/nm3FL/2/

答案 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 chapterthis other以了解链接功能的运作方式。您只使用链接函数来定义指令的监视和/或行为,而不是操纵模型,这在控制器中完成。

答案 5 :(得分:0)

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

var string = "<div> " + scope.text + "</div>";
$compile(string)(scope, function(cloned, scope){
       element.append(cloned);
});