指令未加载范围变量

时间:2017-07-16 00:44:44

标签: angularjs angular-directive

所以我有一个非常简单的指令,它应该执行一个jquery插件函数:

angular.module('myproject.directives').directive('starRating', function () {
    return {
        restrict: 'A',
        scope: {
            rating: '='
        },
        link: function (scope, elem, attr) {
            console.log('rating', scope.rating);

            elem.barrating({
                theme: 'css-stars',
                readonly: true
            });

            elem.barrating('set', scope.rating);
        }
    };
});

这是HTML:

<select class="service-rating" 
        ng-show="!!currentJob.Review.ServiceRating"
        star-rating rating="currentJob.Review.ServiceRating">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
    <option value="5">5</option>
</select>

'currentJob'变量仅在$ http调用后设置,但div仅在填充后才设置为显示。对于scope.rating,日志返回'null',但是如果我自己记录'scope',它会清楚地显示按预期填充的'rating'属性。

此外,如果我只输入'rating'属性的硬编码数字,该指令将按预期工作。

我不确定我在哪里错了?有什么想法吗?

2 个答案:

答案 0 :(得分:2)

基本上问题是,当您使用ng-show时,您的指令会在从star检索到的Ajax值之前加载到DOM树中,它会被处理并barrating 1}}附加到star0的DOM。基本上ng-show的作用是,它只是通过在DOM上切换display css属性来隐藏或显示html上的DOM。

因此,您可以使用两个选项来使星形组件正常工作。

  1. 使用ng-if代替ng-show
  2. 在组件中使用$watch来更新star评级(这将是一个很好的解决方案)。

    link: function (scope, elem, attr) {
        console.log('rating', scope.rating);
    
        elem.barrating({
            theme: 'css-stars',
            readonly: true
        });
        scope.$watch('star', function(newValue){
            elem.barrating('set', newValue);
        });
    }
    
  3. 你可以将两者结合起来。仅在您使用ng-if&amp;进行评分时显示评分然后$watch会对barrating元素上的任何更改进行更新。

答案 1 :(得分:1)

更改指令以对评级中的更改作出反应:

app.directive('starRating', function () {
    return {
        restrict: 'A',
        scope: false,
        link: function (scope, elem, attr) {

            elem.barrating({
                theme: 'css-stars',
                readonly: true
            });

            scope.$watch(attr.rating, function (newValue) {
                elem.barrating('set', newValue);
                console.log('rating', newValue);
            });

        }
    };
});

以这种方式编码,在每个摘要周期,观察者检查rating属性定义的角度表达式的更改,并相应地更新barrating插件。

更新

  

我确实想过使用手表,但我很好奇为什么我的原始设置不起作用。

原始设置不起作用,因为它在指令初始化时仅设置星级评分一次。由于数据在指令初始化后从服务器到达,因此插件不会看到新数据。通过使用手表,每次控制器更改变量时设置都会更新,包括值从服务器到达的时间。

另请注意,另一个答案将手表硬连线到特定的范围变量(不明智)。使用属性声明特定范围变量更明智。它是一个更通用的指令。

当指令缺少使用AngularJS绑定的模板时,避免隔离范围更明智。将手表直接放在属性上,如本例所示。