指令没有加载范围变量

问题描述:

所以我有一个是应该执行的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被填充后才会显示div。日志为scope.rating返回'null',但是如果我自己记录'scope',它就会清楚地显示按照预期填充的'rating'属性。

此外,如果我只是输入一个硬编码的数字'评级'属性该指令按预期工作。

我不确定我要去哪里错了?有任何想法吗?

本质的问题是,当你正在使用ng-show,你的指令被从Ajax检索您的star值之前加载到DOM树,它处理和barrating被连接到DOM与star价值0。基本上ng-show所做的只是在HTML上隐藏或显示DOM,只需在DOM上切换display css属性即可。

所以你可以有两个选项让你的星形组件工作。

  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 &进行评分时才显示评分,那么评分的任何变化将由$watch进行处理以更新barrating元素。
+1

非常感谢 - 非常感谢为什么它不工作的解释! – alimac83

更改指令作出反应,在评级调整:

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插件。


更新

我没想到用的手表,但我很好奇,为什么我的原始设置没有工作。

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

另请注意,另一个答案hardwires手表特定范围变量(不明智)。使用属性来声明特定的作用域变量是明智的。它使得一个更通用的指令。

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

+0

谢谢。我确实想过使用手表,但我很好奇,为什么我的原始设置不起作用。我只是因为完整的解释才将答案标记为解决方案 – alimac83