【问题标题】:How to use an isolated scope property properly?如何正确使用隔离范围属性?
【发布时间】:2015-08-24 08:58:31
【问题描述】:

如何正确使用隔离范围属性?

我有一个指令,它从页面控制器调用,并传递了一个属性item,例如<my-directive item="myItem"></my-directive>,包含一个id

下面的代码将不起作用,因为似乎 $scope.item 在控制器中未定义.. 就像我使用它太快了一样。当我想使用它时,我如何确定它确实被设置了?

app.directive('myDirective', [function() {
return {
    restrict: 'E',
    templateUrl: 'template.html',
    scope: {
        item: "="
    },
    controller: ['$scope', 'ExtendedItemFactory', function($scope, ExtendedItemFactory) {
        this.extendedInfo = ExtendedItemFactory.get({ id: $scope.item.id });
    }],
    controllerAs: 'MyDirectiveCtrl'
};
}]);

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-watch controlleras


    【解决方案1】:

    您可以在指令中使用$watch 来观察值的变化并触发您想要的代码。

    代码

    app.directive('myDirective', [function() {
        return {
            restrict: 'E',
            templateUrl: 'template.html',
            scope: {
                item: "="
            },
            controller: ['$scope', 'ExtendedItemFactory', function($scope, ExtendedItemFactory) {
                this.extendedInfo = ExtendedItemFactory.get({
                    id: $scope.item.id
                });
                $scope.$watch('item', function(newVal, oldVal) {
                    if (newVal && newVal != oldVal)
                        this.extendedInfo = ExtendedItemFactory.get({
                            id: $scope.item.id
                        });
                }, true).bind(this);
            }],
            controllerAs: 'MyDirectiveCtrl'
        };
    }]);
    

    【讨论】:

    • 不得不说,奇怪的是,Angular 没有为此提供更简单的原生解决方案。
    • @Andreas 是的,它可以在没有.bind(this) 的情况下工作,因为我们直接访问孤立的范围变量..如果我们想使用链接到指令控制器的范围变量,那么只有我们会使用.bind(this) ..如果它对你有帮助,那就投票吧..那..
    【解决方案2】:

    您可以创建按需检索它的 getter 函数,而不是在指令加载时初始化 extendedInfo

    this.getExtendedInfo = function(){
        return ExtendedItemFactory.get({ id: $scope.item.id });
    }
    

    或者,您可以在 item 准备好之前阻止您的指令加载

    <div ng-if="ctrl.item">
        <my-directive item="ctrl.item"></my-directive>
    </div>
    

    【讨论】:

    • 我必须在加载时直接加载信息,所以你的第一个建议不起作用。您的第二个建议是一种有趣的方法,但是将逻辑放在指令本身之外感觉不对...
    【解决方案3】:

    您正在使用 controllerAs,因此您不需要在此实例中注入 $scope。

    我会将您的指令定义更改为以下内容,注意使用 bindToController,这将确保您的隔离范围值已填充并在您的控制器上可用:

    app.directive('myDirective', [function() {
        return {
            restrict: 'E',
            templateUrl: 'template.html',
            scope: {
                item: "="
            },
            controller: ['ExtendedItemFactory', function(ExtendedItemFactory) {
                this.extendedInfo = ExtendedItemFactory.get({ id: this.item.id });
            }],
            controllerAs: 'MyDirectiveCtrl',
            bindToController: true
        };
    }]);
    

    【讨论】:

    • 这似乎不起作用,item 在尝试您的代码时尚未在控制器中定义。
    • &lt;my-directive item="myItem"&gt;&lt;/my-directive&gt; 其中myItem 是页面控制器上的范围变量。
    • 我已经多次使用这种模式而没有问题,我不能立即从显示的代码 sn-ps 中看出任何问题。你能用 plunker 或其他东西复制吗?
    猜你喜欢
    • 1970-01-01
    • 2014-07-13
    • 2015-09-18
    • 2012-12-27
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 2015-07-09
    • 1970-01-01
    相关资源
    最近更新 更多