我有一些基本的表单/输入html可以工作(包括验证),如果明确写如下:
<form name="forms.create" novalidate>
<div class="si-container">
<div class="si-input-container">
<input class="si-input" name="someNum" placeholder="Enter a number" ng-model="formdata.number" type="number" min="40"/>
</div>
<div class="si-error">
<div ng-show="forms.create.someNum.$error.min">Error! Value must be > 40.</div>
</div>
</div>
</form>
现在我要做的是创建一个允许我编写下面的html的指令,但结果是上面的html:
<form name="forms.create" novalidate>
<div special-input name="someNum" placeholder="Enter a number" type="number" ng-model="formdata.number">
<div error-type="min" error-value="40">Error! Value must be > 40.</div>
</div>
</form>
我对special-input
指令(简化)的尝试如下:
.directive('specialInput', [function(){
return {
compile: function(elem, attrs){
var input = angular.element('<input class="si-input"/>');
input.attr('placeholder', attrs.placeholder);
input.attr('type', attrs.type);
input.attr('name', attrs.name);
input.attr('ng-model', attrs.ngModel);
var errorCont = angular.element('<div class="si-error"></div>');
var errors = elem.children();
angular.forEach(errors, function(error){
var err = angular.element(error);
var type = err.attr('error-type');
var value = err.attr('error-value');
input.attr(type, value);
var formName = elem.parent().attr('name');
errorCont.append('<div ng-show="' + formName + '.' + attrs.name + '.$error.' + type + '">' + err.html() + '</div>');
});
var cont = angular.element('<div class="si-container"></div>');
cont.append('<div class="si-floating-label">' + attrs.placeholder + '</div>');
cont.append('<div class="si-input-container">' + input[0].outerHTML + '</div>');
cont.append('<div class="si-underline"></div>');
cont.append(errorCont);
elem.replaceWith(cont[0].outerHTML);
}
};
}]);
现在使用上面指令得到的html看起来是正确的。如果我将{{formdata.number}}
放在表单下方,则值会按预期更改。问题是现在验证从未显示过。
例如,如果我将值5
放在输入中并检查表单对象,我会得到奇怪的结果。 $dirty
的{{1}}设置为true,但form
的值不设置为form.someNum
。如果我在输入中添加了55
,$dirty
的{{1}}仍设为false,但form.someNum
和$modelValue
都显示为55。
有任何想法或建议吗?这是一个 fiddle ,可以帮助您进行任何测试。 如果你在输入框中输入50,你会看到下面的值,但是输入5并且没有出现错误
更新
我已经设法通过将dom更改移动到链接函数而不是编译函数来实现它,并添加:
$viewValue
我仍然感到困惑,至于为什么这样做,虽然在编译功能中以完全相同的方式改变dom并不起作用。有人能解释一下吗?
答案 0 :(得分:1)
这是因为原始的ng-model
仍然被编译,即使原始的DOM已经被编译函数中的新DOM替换了。
ng-model
指令会在其postLink函数中将自身注册到父表单。由于postLink函数将以反向执行(孩子在父母之前),新的ng-model
将首先进行注册,因此它将被来自的{@ 1}覆盖。原来ng-model
最终。
要避免此问题,您可以将原始ng-model
更改为其他名称,例如my-model
,然后在编译功能中将其重命名为ng-model
。
示例jsfiddle: http://jsfiddle.net/Wr3cJ/1/
希望这有帮助。