使用动态生成表单输入进行验证的问题?

时间:2014-07-28 15:13:26

标签: forms angularjs validation angularjs-directive

我有一些基本的表单/输入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并不起作用。有人能解释一下吗?

1 个答案:

答案 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/

希望这有帮助。