【问题标题】:Issues getting validation working with dynamically generating form inputs?使用动态生成表单输入进行验证时遇到问题?
【发布时间】:2014-07-28 15:13:26
【问题描述】:

如果明确编写如下,我有一些基本的表单/输入 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>

我对@9​​87654324@ 指令(简化)的尝试如下:

.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 对于 form 设置为 true,但对于 form.someNum 不设置。如果我在输入中输入55$dirty 对于form.someNum 仍然设置为 false,但 $modelValue$viewValue 都显示为 55。

有什么想法或建议吗?这是一个 fiddle,可帮助您进行任何测试。 如果你在输入框中输入 50 应该会看到下面的值,但是输入 5 并不会出现错误


更新

我已经设法通过将 dom 更改移动到链接函数而不是编译函数来使其工作,并添加以下内容:

elem.replaceWith(cont);
$compile(cont)(scope);

尽管如此,我仍然感到困惑,为什么这会起作用,而在 compile 函数中以完全相同的方式更改 dom 是行不通的。有人能解释一下吗?

【问题讨论】:

    标签: forms angularjs validation angularjs-directive


    【解决方案1】:

    这是因为原来的 ng-model 仍然在编译,即使原来的 DOM 已经在你的编译函数中被新的 DOM 替换了。

    ng-model 指令将在其 postLink 函数中将自身注册到父表单。由于 postLink 函数将反向执行(子函数在父函数之前),新的 ng-model 将首先进行注册,因此最终将被原始 ng-model 中的函数覆盖。

    为避免此问题,您可以将原来的 ng-model 更改为另一个名称,例如 my-model,然后稍后在您的编译函数中将其重命名为 ng-model

    jsfiddle 示例: http://jsfiddle.net/Wr3cJ/1/

    希望这会有所帮助。

    【讨论】:

    • 感谢您的精彩回答。
    猜你喜欢
    • 1970-01-01
    • 2012-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-15
    • 2023-04-05
    相关资源
    最近更新 更多