包含指令和形式

SET*_*SET 5 angularjs angularjs-directive angularjs-ng-transclude

我正在尝试创建一些用于包装布局的指令,以便可以从该布局中抽象出来(据我所知,这是指令的主要目标之一)。

所以我想要的是这样的:

<dialog>
  <dialog-title></dialog-title>
  <dialog-body></dialog-body>
  <dialog-footer></dialog-footer>
</dialog>
Run Code Online (Sandbox Code Playgroud)

我为此创建了3个简单的伪指令

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

然后,我想确保在一个指令(对话框主体)中定义的模型在另一指令(对话框脚注)中可见,因为我需要该对话框上的某种形式和页脚中的某些导航按钮,而这些内容可能会被禁用,而不取决于两者之一该表格有效与否。

  <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>
Run Code Online (Sandbox Code Playgroud)

ng-modelin dialog-body将在对话框主体的范围内创建age变量,但直到我将其放入object并在中声明时,它才会出现在其他指令中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>
Run Code Online (Sandbox Code Playgroud)

和控制器:

app.controller('MainCtrl', function($scope) {
  $scope.user = {age: 1}
})
Run Code Online (Sandbox Code Playgroud)

现在,我要在中放置一个表格dialog-body。那应该在对话框主体的作用域上创建FormController,就像这样ng-model做(或这里有一些区别吗?)。我需要从dialog-footer访问它以检查表单的有效性。

因此,在模板中创建表单后,我需要在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>
Run Code Online (Sandbox Code Playgroud)

这里是主要问题。当表单有效性发生变化时,dialog-body它不会反映在其他指令中。为什么?我在这里想念什么?

我的主要目标是为应用程序中最常用的组件提供指令,这样我就可以从实际布局中抽象出来-可以用不同的方式来做到这一点吗?

这里是普拉克

use*_*281 4

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

在您的指令中transclude: true,将创建一个新范围并从父级继承scope,在本例中是MainCtrl. 据我所知,当您声明 时<form name="dialogForm">, Angular 会将 formController 绑定到 的嵌入范围dialogBody,即因为dialogBody它会这样做$scope.dialogForm = formController,并且因为它是一个新范围,所以其他嵌入范围将看不到此更改。

要解决此问题,您可以在父作用域中声明共享变量或使用控制器作为语法,这本质上是相同的。

<body ng-controller="MainCtrl as vm">
Run Code Online (Sandbox Code Playgroud)

然后将表单绑定到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>
Run Code Online (Sandbox Code Playgroud)

参见笨蛋

为什么这有效?因为所有新的嵌入作用域都从父作用域继承vm,并且 formControllervm.dialogForm绑定到这个公共变量,所以所有嵌入作用域都会看到此更改。