使用指令创建隔离范围

时间:2014-08-06 18:52:33

标签: javascript angularjs angularjs-scope

我有一组显示在表单上的客户端,它们必须具有单独的范围(每个客户端):

View plunker here

当然,我希望创建一个带有隔离范围的新指令,不允许使用像这样的自定义指令将元素绑定到oustide $scope

<fieldset client="156510">
      <legend>Client 156510</legend>
      <!-- Form elements -->
      </section>
</fieldset>

同样地:

angular.module("plunker", [])

  .controller("ClientCtrl", function($scope) {})

  .directive("client", function() {
    return {
      restrict: "A",
      scope: {
        name: "@name",
        client: "=client"
      }
    };
  });

鉴于ng-repeat不是一个选项,如何使用指令隔离任何包含HTML的范围?角度文档seem to suggest this is possible,但我的实现似乎没有按预期工作。

提前致谢。

4 个答案:

答案 0 :(得分:2)

具有隔离范围WITHOUT template / templateUrl的元素的任何指令实际上都没有获得新的范围。

这是证明 http://plnkr.co/edit/jXwrtG?p=preview

.directive("client", function() {
    return {
      restrict: "A",
      template: '  ',//notice extra spaces
      replace: true,//notice this
      scope: {
        name: "@name",
        client: "=client"
      }
    };
  });

scope = true也可以解决您的问题。

http://plnkr.co/edit/JdiCVV?p=preview

  .directive("client", function() {
    return {
      restrict: "A",

      scope: true
    };
  });

同样正如@imscrb指出的那样 transclude = true也有效,但您必须将ng-transclude添加到元素

<fieldset client="156510" ng-transclude>

http://plnkr.co/edit/b0hX5h?p=preview

.directive("client", function() {
    return {
      restrict: "A",
      transclude: true,

      scope: {
        name: "@name",
        client: "=client"
      }
    };
  });

答案 1 :(得分:1)

如果您希望每个客户端完全隔离,那么您需要将template directive中使用的所有HTML放在其中。这是因为您拥有的当前html,以及模型的绑定是由控制器而不是指令控制的

IE ..(没有经过您的代码测试,但是您需要做的事情) - 您可能需要将模板中的ng-model更改为模型虽然推进了指令 - 这只是一个例子

return{
    ....
    template: '<legend>Client 156510</legend>'
            + '<section>'
            + '<div class="horizontal-field">'
            ...........
            + '</section>'
}

然后你的html就像是(再次,伪代码):

<fieldset client="156510" ng-model="yourModel"></fieldset>

答案 2 :(得分:0)

如果我正确理解您的问题,那么启用转换可以解决您的问题:

angular.module("plunker", [])
  .controller("ClientCtrl", function($scope) {})
  .directive("client", function() {
    return {
      restrict: "A",
      scope: {
        name: "@name",
        client: "=client"
      },
      transclude: true,
      template: '<div ng-transclude></div>'
    };
  });

答案 3 :(得分:-1)

我相信你做错了事,因为你打破了DRY原则。不要为视图中的每个客户端重复HTML,而是将其移动到指令的模板中,然后传递给指令隔离范围客户端。当然,如果你愿意的话,你只能在指令中传入指令客户端的id并从某个服务获取客户端。 并且不要像ng-pristine, ng-dirty等手动指定所有Angular服务类。

控制器和指令

app = angular.module("plunker", []).controller("ClientCtrl", function($scope) {
  $scope.clients = [{
    id: 12345,
    firstName: 'First',
    lastName: 'First',
    middleInitial: 'A'
  }, {
    id: 123456,
    firstName: 'Second',
    lastName: 'Second',
    middleInitial: 'B'
  }];

})
.directive("client", function() {
  return {
    restrict: "A",
    templateUrl: 'client-form.html',
    scope: {
      client: "=client"
    }
  };
});

客户表单模板

<fieldset ng-form='clientForm'>
  <legend>Client {{client.id}}</legend>
  <section>
    <div class="horizontal-field">
      <label for="title">Title</label>
      <select ng-model="client.title" name="title">
        <option value=""></option>
        <option value="mr">Mr.</option>
        <option value="mrs">Mrs.</option>
        <option value="ms">Ms.</option>
        <option value="miss">Miss</option>
        <option value="dr">Dr.</option>
      </select>
    </div>
    <div class="horizontal-field">
      <label for="first-name">First Name</label>
      <input placeholder="First Name" required="" autofocus="" ng-model="client.firstName" name='first_name' type="text" >
    </div>
    <div class="horizontal-field">
      <label for="middle-initial">Middle Initial</label>
      <input maxlength="1" ng-model="client.middleInitial" type="text" name="middle_initial" value="" id="middle-initial">
    </div>
    <div class="horizontal-field">
      <label for="last-name">Last Name</label>
      <input placeholder="First Name" ng-model="client.lastName" type="text" name="last_name">
    </div>
  </section>
</fieldset>

查看

<div ng-repeat='client in clients' client='client' ></div>

Plunker