0

这是一个人为的例子,但它演示了我遇到的一个问题。

我有一个表单,它有一个使用指令生成的输入。代码类似于以下内容。小提琴在这里http://jsfiddle.net/technicolorenvy/CFynn/2/

看法

    <div ng-controller="AppController">
        <form name="myForm">
            <input name="myInput" id="myInput" ng-model="myInputModel" ng-pattern="/\d+/" my-directive required/>
            <button type="submit" ng-click="submitForm()">Submit</button>
        </form>
    </div>

控制器

    app.controller('AppController', function ($scope) {
        $scope.submitForm = function () {
            console.log('form controller inside AppController submitForm()');
            console.log(angular.copy($scope.myForm));
            console.log('is the form valid? ' + $scope.myForm.$valid);
            console.log(' ');
        };
    });

指示

    app.directive('myDirective', function () {
        return {
            template: '<div><input/></div>',
            replace: true,
            restrict: 'A',
            require: '^form',
            compile: function (element, attrs) {
                // some setup here
                // move the id and ng-model down onto the enclosed input
                element.removeAttr('id').removeAttr('ng-model').removeAttr('name');
                element.find('input').attr('id', attrs.id).attr('ng-model', attrs.ngModel).attr('name', attrs.name);

                var inputName = attrs.name,
                    $input = element.find('input');
                if (attrs.required) {
                    element.removeAttr('required');
                    $input.attr('required', true);
                }
                if (attrs.ngPattern) {
                    element.removeAttr('ng-pattern');
                    $input.attr('ng-pattern', attrs.ngPattern);
                }

                return {
                    pre: function (scope, element, attrs, formCtrl) {
                        var patternErrs,
                        fakeNum = 1234;

                        $input.on('change', function () {
                            patternErrs = formCtrl.$error.pattern;
                            if (patternErrs && patternErrs.length > 0) {
                                angular.forEach(patternErrs, function (err) {
                                    if (err.$name === inputName) {
                                        $input.val(fakeNum);
                                        formCtrl[inputName].$setViewValue(fakeNum);
                                        formCtrl[inputName].$setValidity('pattern', true);
                                    }
                                });
                            }
                            console.log('formCtrl inside directive');
                            console.log(angular.copy(formCtrl));
                            console.log('is the form valid? ' + formCtrl.$valid);
                            console.log(' ');
                        });
                    }
                };
            }
        }
    });

在指令中,我在“生成”输入上有一个 onChange 事件,该事件检查与此输入名称匹配的模式错误,然后如果有,则使用假值强制数据成为我们需要的数据,然后使用setViewValue然后设置有效性setValidity.

这工作......有点。问题是,在第一次提交时,表单总是无效的。您必须单击提交两次才能使表格被视为有效。(包括以下步骤)

  1. 在输入中输入一个字符串(例如'abcd')
  2. 输入未通过模式验证,然后获取有效值 (1234)
  3. 指令“myDirective”处理这个+设置输入的值和有效性
  4. 但是,在第一次提交时,表格无效
  5. 在第二次提交时,没有更改输入,表单有效

那么如何在第一次提交时使表单有效而不加强表单的有效性(阅读,我不想手动将表单设置为有效)。这感觉像是一个范围界定问题,但如果是,我不太确定如何解决它。

谢谢!

4

2 回答 2

2

完成更改范围后,您需要调用scope.$apply()更改事件。

那就是说..我不确定您要在这里做什么。

看起来您可能正在尝试以复杂的方式解决一个简单的问题。很明显,代码不是很可测试。也许正在做的一些实际上是可以封装在控制器中的“业务逻辑”?

这里的确切目标是什么?

于 2013-11-13T21:07:39.600 回答
1

你的 $input.on('change') 中的代码永远不会被消化......也就是说,Angular 永远不知道在你的 change 事件之后运行它的所有监视和内部过程。所以它在第一次摘要期间运行它,这发生在您第一次运行提交时。

我认为,如果您将该位包装在 $timeout() 中或使用 $scope.$apply() 它将解决问题。

于 2013-11-13T21:06:20.480 回答