我试图创建一些包含布局的指令,这样我就可以从布局中抽象出来(这是我理解的指令的主要目标之一)。
所以我想拥有的是这样的:
<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
答案 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]);
}
绑定到此公共变量,所以所有被转换的范围都将看到此更改。