移植指令和表格

时间:2017-05-18 13:32:18

标签: angularjs angularjs-directive angularjs-ng-transclude

我试图创建一些包含布局的指令,这样我就可以从布局中抽象出来(这是我理解的指令的主要目标之一)。

所以我想拥有的是这样的:

<dialog>
  <dialog-title></dialog-title>
  <dialog-body></dialog-body>
  <dialog-footer></dialog-footer>
</dialog>

我为此创建了3个简单的指令,看起来与此类似

app.directive('dialog', ()=>{
  return {
    template: '<div class="dialog" ng-transclude></div>',
    replace: true,
    transclude: true,
    restrict: 'E',
  }
})

然后我想确保在一个指令(dialog-body)中定义的模型在另一个(对话框页脚)中可见,因为我需要在该对话框上有一些表单,并且页脚中的一些导航按钮可能被禁用取决于该表格有效与否。

  <body ng-controller="MainCtrl">
    <p>age: {{age}}</p>
    <dialog>
      <p>age: {{age}}</p>
      <dialog-body>
        <form name="dialogForm">
          <p>age: {{age}}</p>
          <input ng-model="age" minlength="3"/>
        </form>
      </dialog-body>
      <dialog-footer>
        <p>age: {{age}}</p>
      </dialog-footer>
    </dialog>
  </body>
ng-model中的

dialog-body将在对话框主体的范围内创建年龄变量,但它不会出现在其他指令中,直到我将它放在对象中并在MainCtrl中声明。这就是它的工作原理:

  <body ng-controller="MainCtrl">
    <p>age: {{user.age}}</p>
    <dialog>
      <p>age: {{user.age}}</p>
      <dialog-body>
        <form name="dialogForm">
          <p>age: {{user.age}}</p>
          <input ng-model="user.age" minlength="3"/>
        </form>
      </dialog-body>
      <dialog-footer>
        <p>age: {{user.age}}</p>
      </dialog-footer>
    </dialog>
  </body>

和控制器:

app.controller('MainCtrl', function($scope) {
  $scope.user = {age: 1}
})

现在,我想在dialog-body中添加一个表单。这应该在对话框主体的范围内创建FormController,就像ng-model那样(或者这里有一些区别?)。我需要从对话框页脚访问它以检查表单有效性。

所以在模板中创建表单后,我需要在MainCtrl的范围内定义formController,这是第一个问题 - 如何创建FormController的实例?我认为$scope.dialogForm = {$valid: true}应该用于测试目的,这是我的最终模板:

  <body ng-controller="MainCtrl">
    <p>age: {{user.age}}</p>
    <p>validity: {{dialogForm.$valid}}</p>
    <dialog>
      <p>age: {{user.age}}</p>
      <p>validity: {{dialogForm.$valid}}</p>
      <dialog-body>
        <form name="dialogForm">
          <p>age: {{user.age}}</p>
          <p>validity: {{dialogForm.$valid}}</p>
          <input ng-model="user.age" minlength="3"/>
        </form>
      </dialog-body>
      <dialog-footer>
        <p>age: {{user.age}}</p>
        <p>validity: {{dialogForm.$valid}}</p>
      </dialog-footer>
    </dialog>
  </body>

这是主要问题。当表单有效性在dialog-body中更改时,它不会反映在其他指令中。为什么?我在这里缺少什么?

我的主要目标是在应用程序中使用大多数已使用组件的指令,这样我就可以从实际布局中抽象出来 - 这可以用不同的方式完成吗?

以下是plunk

1 个答案:

答案 0 :(得分:3)

  

当对话框体中的表单有效性发生变化时,它不会反映在其他指令中。为什么呢?

在您的指令中transclude: true将创建一个新范围,并从父scope继承,在这种情况下是MainCtrl的范围。据我所知,当你声明<form name="dialogForm">时,angular会将formController绑定到dialogBody的被转换范围,即dialogBody它会$scope.dialogForm = formController,因为它是<body ng-controller="MainCtrl as vm"> 一个新的范围,其他被转换的范围将不会看到这种变化。

要解决此问题,您可以在父作用域中声明共享变量,或使用基本相同的controller as语法。

vm

然后将表单绑定到 <form name="vm.dialogForm"> <p>age: {{vm.user.age}}</p> <p>validity: {{vm.dialogForm.$valid}}</p> <input ng-model="vm.user.age" minlength="3"/> </form>

vm

请参阅plunker

为什么这样做?因为所有新的被转换范围都从父范围继承vm.dialogForm,并且formController function mousePressed(){ var key = floor(map(mouseX, 0, width, 0, notes.length)); playNote(notes[key]); } 绑定到此公共变量,所以所有被转换的范围都将看到此更改。