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.

これはうまくいきます...ちょっと。問題は、最初の送信時にフォームが常に無効になることです。フォームが有効であると見なされるには、[送信] を 2 回クリックする必要があります。(手順は以下に含まれます)

  1. 入力に文字列 (例: 'abcd') を入力します
  2. 入力はパターン検証に失敗し、有効な値を取得します (1234)
  3. ディレクティブ「myDirective」がこれを処理 + 入力の値と有効性を設定
  4. ただし、最初の送信では、フォームは無効です
  5. 入力を変更せずに 2 回目の送信を行うと、フォームは有効になります。

したがって、フォームの有効性を強化せずに、最初の送信時にフォームを有効にするにはどうすればよいですか (フォームを手動で有効に設定したくありません)。これはスコーピングの問題のように感じますが、そうである場合、それを修正する方法がよくわかりません.

ありがとう!

4

2 に答える 2

2

scope.$apply()スコープの変更が完了したら、変更イベントを呼び出す必要があります。

そうは言っても..ここで何をしようとしているのかわかりません。

単純な問題を複雑な方法で解決しようとしているように見えます。コードがあまりテスト可能でないことは明らかです。おそらく、実際に行われていることの一部は、コントローラーにカプセル化できる「ビジネス ロジック」でしょうか?

ここでの正確な目標は何ですか?

于 2013-11-13T21:07:39.600 に答える
1

$input.on('change') 内のそのコードは決して消化されません...つまり、Angular は変更イベントの後にすべてのウォッチと内部プロシージャを実行することを知りませんでした。そのため、Submit を初めて実行したときに発生する最初のダイジェスト中に実行されます。

そのビットを $timeout() でラップするか、 $scope.$apply() を使用すると、問題が解決すると思います。

于 2013-11-13T21:06:20.480 に答える