我已经构建了一个基于meta($scope.meta
)数据生成输入字段的指令。
我的问题是支持角度表单验证。
Plunkr:http://plnkr.co/edit/AfR5cWyywGlCECS6h6Dr?p=preview
说明:指令采用meta
参数来描述它是什么输入字段类型以及用于呈现字段的其他相关信息。指令中定义的所有属性都将复制到元素,最后将在编译和链接后替换该指令。
查看:
<form name="userForm">
<!-- Username -->
<poly-field ng-model="storage" meta="meta" key="username" name="username" ng-minlength="3" ng-maxlength="8"></poly-field>
<p ng-show="userForm.username.$error.minlength" class="help-block">Username is too short.</p>
<p ng-show="userForm.username.$error.maxlength" class="help-block">Username too long</p>
<!-- Email -->
<poly-field ng-model="storage" meta="meta" key="email" name="email" ng-required></poly-field>
<p ng-show="userForm.email.$error.minlength" class="help-block">Email is too short.</p>
<p ng-show="userForm.email.$error.maxlength" class="help-block">Email is too long</p>
</form>
输入比允许的更长或更短的用户名应该会显示错误。 跳过电子邮件字段也显示错误。
以下是应用指令后的View源代码:
<form name="userForm" class="ng-pristine ng-valid ng-valid-required">
<!-- Username -->
<input type="undefined" ng-model="storage.username" meta="meta" key="username" name="username" ng-minlength="3" ng-maxlength="8" class="ng-scope ng-valid-minlength ng-dirty ng-valid ng-valid-maxlength">
<p ng-show="userForm.username.$error.minlength" class="help-block ng-hide">Username is too short.</p>
<p ng-show="userForm.username.$error.maxlength" class="help-block ng-hide">Username too long</p>
<!-- Email -->
<input type="undefined" ng-model="storage.email" meta="meta" key="email" name="email" ng-required="" class="ng-scope ng-valid ng-valid-required ng-dirty">
<p ng-show="userForm.email.$error.minlength" class="help-block ng-hide">Email is too short.</p>
<p ng-show="userForm.email.$error.maxlength" class="help-block ng-hide">Email is too long</p>
</form>
以下是视图和使用指令的模型,它在ParentCtrl中声明。
$scope.storage = {
username: "Kitkat",
email: "flying@kitkat.com"
};
这是元信息,它告诉输入字段是什么样的(是文本吗?日期等等)
$scope.meta = {
username: { type: "text" },
email: { type: "text" }
};
指令声明:
app.directive('polyField', function($compile) {
var linkFn = function(scope, element, attributes) {
// create input element depending on the type
var template = document.createElement("input");
template.type = scope.storage[attributes.key].type;
// copy all attributes
for (var attr in attributes.$attr) {
if (attributes.$attr[attr] == 'ng-model') {
template.setAttribute('ng-model', attributes[attr] + '.' + attributes.key);
} else {
template.setAttribute(attributes.$attr[attr], attributes[attr]);
}
}
// template compilation, linking and element replacement
template = angular.element(template.outerHTML);
var linkTemplate = $compile(template);
var domElement = linkTemplate(scope);
element.replaceWith(domElement);
}
var directive = {
restrict: 'E',
scope: {
meta: '=',
storage: '=ngModel',
key: '=',
},
link: linkFn
};
return directive;
});
一些想法:
每个指令都创建一个隔离的范围,因此,在指令userForm
内部是看不见的,但是,从指令的范围和父级中可以看到双向绑定的storage
(ng-模型)范围,如果userForm看到storage
里面的内容应该没问题,那不是吗?
我试图将userForm
传递给指令范围:
// directive
scope: {
meta: '=',
storage: '=ngModel',
key: '=',
userForm: '='
}
// template
<poly-field user-form="userForm" ng-model="storage" meta="meta" key="username" name="username" ng-minlength="3" ng-maxlength="8"></poly-field>
但没有效果。
当我查看指令范围时,在userForm
字段中,我看到输入字段实际上是$dirty: false
,$invalid: true
,并且在我输入用户名/电子邮件字段后,< / p>
在源代码中,它似乎正确应用了验证类:
ng-valid-minlength
ng-dirty
ng-invalid
ng-invalid-maxlength
仍然没有显示验证错误。
我能用它做什么吗?
答案 0 :(得分:2)
为了让Angular的表单验证能够启动,ngModel
在其控制器的实例化过程中查找父ngForm
/ form
指令阶段(在预连接阶段之前)。
由于您在将元素添加到DOM之前编译并链接该元素,因此当时没有父元素,因此无法注册。
您只需要先将元素插入DOM,然后进行编译和链接。
<强> Updated plunkr 强>