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它不会反映在其他指令中。为什么?我在这里想念什么?
我的主要目标是为应用程序中最常用的组件提供指令,这样我就可以从实际布局中抽象出来-可以用不同的方式来做到这一点吗?
这里是普拉克
当对话框主体中的表单有效性发生变化时,它不会反映在其他指令中。为什么?
在您的指令中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绑定到这个公共变量,所以所有嵌入作用域都会看到此更改。