Angularjs隔离了没有自己模板的指令范围

时间:2014-01-02 08:13:34

标签: javascript angularjs angularjs-directive angularjs-scope

我想在没有自己的模板的情况下在AngularJS中创建可重用的指令。我还希望为该指令设置隔离范围。我的方法的最佳实践是什么? 为什么我的例子不能像我期望的那样工作?

我希望我可以分别从指令编辑obj1和obj2。

HTML:

<div ng-controller="MyCtrl">
  X1: {{ obj1.x }}, Y1: {{ obj1.y }}
  X2: {{ obj2.x }}, Y2: {{ obj2.y }}
  <hr>
  Edit obj1: 
  <div draggable target="obj1">
    <input type="text" ng-model="target.x">
    <input type="text" ng-model="target.y">
  </div>
  Edit obj2:
  <div draggable target="obj2">
    <input type="text" ng-model="target.x">
    <input type="text" ng-model="target.y">
  </div>
</div>

JS:

angular.module("App", [])
  .controller("MyCtrl", function($scope) {
    $scope.obj1 = {
      x: 10,
      y: 20
    };
    $scope.obj2 = {
      x: 30,
      y: 40
    };
  })
  .directive("draggable", function() {
    return {
      scope: {
        target: "="
      },
      link: function(scope, el, attrs) {
        console.log("scope: ", scope);
      }
    }
  });

PLUNKR: http://plnkr.co/edit/Dw8IiFVSOZGjSTFGRMzZ

2 个答案:

答案 0 :(得分:38)

您的代码现在的工作方式是,每个指令的内容都绑定到父作用域,而不是指令的隔离作用域,因此每个target都是对同一个变量的引用。 / p>

您需要做的是transclude指令的内容。通常的用途是您希望内容位于指令的父作用域中,而不是在隔离的作用域中。但是,您希望内容位于指令的隔离范围内。因此,您必须手动调用transclude函数,并将内容绑定到指令的隔离范围:

.directive("draggable", function($compile) {
  return {
    transclude: true,
    scope: {
      target: "="
    },
    link: function(scope, element, attrs, ctrl, transclude) {
      transclude(scope, function(clone) {
       element.append(clone);
      });
    }
  }
})

你可以see this in this Plunker。它没有做的一件事是$watch'target'的内容,所以我怀疑它不会对指令中“target”属性的变化做出反应。这可能最好留给另一个问题。

编辑:transclude的使用不正确/过于复杂。您可以将scope作为第一个参数传递,以将克隆正确绑定到正确的范围。

答案 1 :(得分:10)

来到这里面对同样的困惑。显然,案件如下。

除了排除外,只有指令模板中的元素才会绑定到该指令创建的隔离范围。如果您不使用模板 - 声明该指令的元素的内容将绑定,就像隔离范围不存在一样。

这是一个从上面展示的改良型羽毛球。 http://plnkr.co/edit/WqEKkNAj4p2Rly51LBzC?p=preview