0

更新 1: 詳細を追加します。
更新 2: 問題を再現するためにプランカー コードを追加しました。以下のリンクを参照してください。
更新 3: github の angular チームから返信がありました。ここで確認してください
更新 4: AngularJS チームの要求に応じて、github に更新を投稿しました。また、以前に追加した提案された解決策は、新しい視覚的な問題を引き起こしていることが判明しました。以下の詳細を参照してください。
更新 5: Angular チームから別のフィードバックを取得します。80% 解決に近づいていると思います。

プロジェクトに Angular UI の datepicker を実装しました。しばらくすると、ポップアップ ボックスを開いて月をクリックして別の月に変更すると、別のポップアップ ウィンドウが既存のポップアップの上に表示されることに気付きました。詳細については、以下のスナップショットを参照してください。

ここに画像の説明を入力

もともと、月をクリックすると、現在のポップアップが消え、別のポップアップが表示されて新しい月が選択されるはずです。

ただし、月 (下の黄色で強調表示) を 2 回クリックすると、ポップアップが消えて正常に動作します。しかし、日付を選択すると、問題が再発します。

angular ui datepicker の公式デモ Web サイトと同じサンプル コードを使用しています。関連する Web サイトと plunker コードの下を見つけます。

http://angular-ui.github.io/bootstrap/versioned-docs/1.3.3/#/datepickerPopup http://plnkr.co/edit/lEgJ9eC9SzBWsgVhhQkq?p=preview

私のコードは、上記の plunker サンプルのコードとまったく同じです。唯一の違いは、$compile必要なフィールドの検証を動的に追加するためにサービスを使用していることです。

$compile()広範なトラブルシューティングの後、サービスがこの動作を引き起こしていることがわかりました。いくつかの調査を行ったところ、この$compileサービスによってドロップダウン リストまたはselect要素のアイテムが重複することもわかりました。提案された回避策を使用しましたが、うまくいきました。以下のコードを参照してください。

$compile(child)(elmScope, function (clone) {
    angular.element(child).after(clone);     
    angular.element(child).remove();
});

私が使用している理由は、このアプローチhere$compileを使用して、DB から要素に動的検証ルールを追加するためです。

github で angular チームから返信を受け取った後、彼らがこの修正を提案していることがわかりました:

.directive('checkIfRequired', ['$compile', function ($compile) {
    return {
      priority: 1000,
      terminal: true,
        /*require: '?ngModel',*/
        //JIRA: NE-2535 - inject the current 'ngForm' controller with this directive
        //      This is required to add automatice error message when the Form Field is invalid.
        require: '?^form',
      link: function (scope, el, attrs, ngForm) {
        el.removeAttr('check-if-required');
        el.attr('ng-required', 'true');
        $compile(el, 1000)(scope);
      }
    };
}]);

提案された修正を適用しようとすると、多数のエラーが発生します。使用するとterminal=true、「ng-init」の下の内部要素のすべてのコードが実行されなかったようです。多くのスコープ変数が「未定義」になることに気付きました。

これは、解決策を見つけるためのgithub の最終更新です。以下のコードを参照してください。

app.directive('checkIfRequired', ['$compile', '$timeout', function ($compile, $timeout) {
  return {
    priority: 2000,
    terminal: true,
    /*link: function (scope, el, attrs) {
      el.removeAttr('check-if-required');
      var children = $(':input', el);
      children.each(function(key, child) {
        if (child && child.id === 'test_me') {
            angular.element(child).attr('ng-required', 'true');
                }
      });
      $compile(children)(scope);
    },*/
    compile: function (el, attrs) {
        el.removeAttr('check-if-required');
        var children = $(':input', el);
        children.each(function(key, child) {
            if (child && child.id === 'test_me') {
                angular.element(child).attr('ng-required', 'true');
                    }
            });
        var compiled = $compile(children, null, 2000);
        return function( scope ) {
            compiled( scope );
        };
    }
  };
}]);

私のプロジェクトで正しい方法で修正を適用するためにあなたの助けに感謝します. コードの関連部分については、こちらを参照してください


以前に解決策を投稿しましたが、その後削除しました。後になって、以前に報告したものよりも悪い、おかしなスタック効果が発生していることに気付きました。

完全な詳細を含む github の更新は次のとおりです。

https://github.com/angular/angular.js/issues/15956#issuecomment-300324812

AngularJS チームから返信があり次第、更新を続けます。

恒久的な解決策が見つかるまで、しばらくお待ちください。


古い提案された解決策:

この問題を回避するには、$compileサービスを使用しないでください。または、このコード サンプルを使用して問題を解決する必要がある場合:

$compile(child)(elmScope, function (clone) {
    angular.element(child).after(clone);     
    angular.element(child).remove();
});

これが同じ問題に直面している他の人にとって価値があることを願っています。

4

2 に答える 2

0

補正を行うためです。以前に追加されたソリューションは期待どおりに機能しませんでした。

完全な詳細については、github の更新を確認してください。

https://github.com/angular/angular.js/issues/15956#issuecomment-300324812

今のところ、DB に保存され、AngularJS フォームで読み込まれる動的検証ルールを使用する別のアプローチを提案できます。

この提案されたソリューションの基礎として、次のコード部分を参照してください。

無効な場合はフィールドが強調表示された、フィールドのグループのAngular動的必須検証

$compileディレクティブでを使用する代わりに、フィールドcheck-if-requiredの新しいscope変数を次のように作成しますchild.id

if (scope.isFieldRequired(child.id)) {
    //angular.element(child).attr('ng-required', "true");
    //$compile(child)(elmScope);
    scope.RootController.ngRequired[child.id] = true;
} else {
    scope.RootController.ngRequired[child.id] = false;
}

要素を定義したときは、次のようになっていることを確認してください。

<input id="customer_id" name="customer_id" ng-model="customer_id" ng-required="RootController.ngRequired.customer_id"/>

RootController'. For simplicity, the required validation will be under基本的に、すべての検証ルールは、ルート Angular Controller RootController.ngRequired`で定義する必要があるスコープ変数にリンクする必要があります。

一番外側のコントローラーRootControllerの表記で定義する必要があります。controller asそうしないと、上記の解決策は機能しません。以下は、ルート コントローラーの要素定義のサンプルです。

<body ng-app="myApp" ng-controller="formMainController as RootController">
...
</body>

を使用したために見つかった問題に関して、Angular チームから満足のいく回答が得られない場合は$compile、上記の方法に切り替えます。上記の方法がうまくいくことはほぼ確実です。

フィードバックがありましたら、ぜひお寄せください。

タレク

于 2017-05-01T22:38:25.100 に答える