从指令设置ngModel时的范围问题

时间:2012-10-24 09:03:17

标签: javascript angularjs

我的指令类似于:

var myApp = angular.module('myApp',[])
    .directive("test", function() {
      return {
        template: '<button ng-click="setValue()">Set value</button>',
        require: 'ngModel',
        link: function(scope, iElement, iAttrs, ngModel) {
          scope.setValue = function(){
            ngModel.$setViewValue(iAttrs.setTo);
          }
        }
      };
    });

问题在于,如果我在页面中多次使用此指令,则setValue仅在最后声明的指令上被调用。显而易见的解决方案是使用scope: {}隔离范围,但是在指令之外无法访问ngModel。

这是我的代码的JSFiddle:http://jsfiddle.net/kMybm/3/

2 个答案:

答案 0 :(得分:3)

对于这种情况,ngModel可能不是正确的解决方案。这主要是为了将表单的值绑定到像标记它们的脏和验证......

在这里你可以使用来自隔离范围的双向绑定,如下所示:

app.directive('test', function() {
   return {
      restrict: 'E',
      scope: { 
         target: '=target',
         setTo: '@setTo'
      },
      template: '<button ng-click="setValue()">Set value</button>',
      controller: function($scope) {
          $scope.setValue = function() {
              $scope.target = $scope.setTo;
          };
          //HACK: to get rid of strange behavior mentioned in comments
          $scope.$watch('target',function(){});
      }
   };
});

答案 1 :(得分:2)

您需要做的就是将scope: true添加到指令哈希中。这为您的指令的每个实例创建了一个新的继承子范围,而不是在已经发挥作用的任何范围上不断覆盖“setValue”。

你对隔离范围是正确的。我对新手的建议就是不要永远使用它。

对评论的回应:

我现在更好地理解这个问题了。通过表达式设置值时,它会将其设置为最直接的范围。因此人们通常使用Angular的方法是读取和改变值而不是覆盖值。这需要包含像Object或Array这样的结构中的东西。

请参阅更新的小提琴:

http://jsfiddle.net/kMybm/20/

(“foo”通常会通过ngController连接到控制器。)

另一种选择,如果你真的想要“无范围”,那就是不要使用ng-click,只需自己点击即可。

http://jsfiddle.net/WnU6z/8/