9

私は AngularJS アプリを作成しています。このアプリにはドメイン管理ツールがあります。ドメインが選択されると、テーブルにドメイン レコードを生成し、ユーザーが各行を編集できるようにします。フィールドは動的に作成されるため、同じ名前を共有しているため、ng-form を使用して各行を個別に検証できるようにします。

各ドメイン レコードには、IP、CNAME などが存在するコンテンツ フィールドがあります。選択されたレコード タイプ (A、CNAME、TXT など) に基づいて関数から生成された正規表現パターンを使用して、このフィールドを検証します。

問題は、たとえば A レコードを編集して、レコード タイプを CNAME に変更すると、コンテンツ フィールドの新しい検証が実行されていないため、フォームがまだ有効に見えることです。再検証する唯一の方法は、コンテンツ フィールドに入力を開始することです。

以下の画像を確認してください。

A レコードで編集を押すと、すべて問題なく表示されます。 ここに画像の説明を入力

レコード タイプを CNAME に変更すると、正規表現が変更されてもフォームは有効に見えます。タイプを変更すると、新しい正規表現が配置されているため、コンテンツ (1.2.3.4) を再検証する必要があります。 ここに画像の説明を入力

コンテンツ フィールドに入力を開始すると、フォームが正しく無効になります。入力を再開したときだけでなく、レコードタイプを変更したときにこれが発生することを望みます。 ここに画像の説明を入力

#Slim version of the template to give you an idea on whats going on
<form novalidate name="recordForm" class="css-form" ng-controller="EditRecordCtrl">

    <table>

        <tr ng-repeat="record in domain.data.0" class="gradeA">

            <td ng-init="startingTypeData = record.type" class="domains-td" ng-switch on="record.edit">
                <span ng-switch-default>{{record.type}}</span>
                <span ng-switch-when="true">
                    <select ng-change="domainRecordContentType(record.type)" ng-init="domainRecordContentType(record.type)" ng-model="record.type" ng-options="c for c in domainRecordTypes" class="span12">
                    </select>
                </span>
            </td>

            <td ng-init="startingContentData = record.content" class="domains-td validation-dropdown-error-parent" ng-switch on="record.edit">
                <span ng-switch-default>{{record.content}}</span>
                <span ng-switch-when="true">
                    <ng-form name="innercContentForm">
                        <span class="validation-dropdown-error" ng-show="innercContentForm.content.$error.pattern">
                            {{ 'RECORD_EDIT_FORM_RECORD_CONTENT_PATTERN_MSG' | translate }} ( {{ record.type }} )
                        </span>
                        <input type="text" ng-model="record.content" name="content" required class="span12 edit-record-input" ng-pattern="domainRecordContentRegex.0" required />
                    </ng-form>
                </span>
            </td>

        </tr>

    </table>

</form>

ドロップダウン メニューを変更したときに入力フィールドを再検証するにはどうすればよいですか?

プランカーの例: http://plnkr.co/edit/VAR5ho 注意! 最初の行に A レコードが表示されない小さなバグ。上の画像で行ったように、問題をテストすることもできます。

Thomas カスタム ディレクティブを使用して更新する

ドロップダウンを変更する前に ここに画像の説明を入力

最初のドロップダウンを A から CNAME に変更すると、すべてのコンテンツ フィールドが消去されます ここに画像の説明を入力

更新保存ボタン

<button ng-disabled="recordForm.$invalid" ng-switch-when="true" ng-if="hideRecordType(record.type)" ng-click="recordForm.$valid && editRecord(record, domainId); record.edit=false; $parent.startingNameData=record.name; $parent.startingTypeData=record.type; $parent.startingContentData=record.content; $parent.startingTTLData=record.ttl; $parent.startingPrioData=record.prio" type="submit" class="btn btn-block btn-primary btn-icon" ><i></i>{{ 'DOMAINS_SAVE_BUTTON' | translate }}</button>

最終更新..コンパイルされた要素に関する奇妙な動作

編集を押すと、通常の編集ビューに移動します ここに画像の説明を入力

有効になるまで、新しい IP アドレスを入力し始めます ここに画像の説明を入力

ドットを追加するなど、一度有効にした後にコンテンツを無効にすると、値が消去されます。なんで? ここに画像の説明を入力

Thomas コードに基づく現在のディレクティブ:

domainModule.directive('revalidate', function($compile) {
    return {
        restrict: 'A',
        link : function (scope, element, attrs) {
          scope.$watch(attrs.ngModel, function (v) {
              var reg = scope.$parent.domainRecordContentRegex[0];

              if(!$(element).parent().parent().next().find('ng-form').find('input').val().match(reg)){

                  $compile($(element).parent().parent().next().find('ng-form').children('input[name="content"]').removeClass('ng-valid-pattern'))(scope);
                  $compile($(element).parent().parent().next().find('ng-form').children('input[name="content"]').addClass('ng-invalid-pattern'))(scope);

              }

            });
        }
    };
});

ここで実際のフィールドを選択し、クラスを変更して、正規表現が一致しない場合は無効にします。この方法では、[保存] ボタンも無効になります。これはドロップダウンで変更すると機能しますが、コンパイルされた要素が何らかの形で破損します。

4

4 に答える 4

3

最善の解決策は、独自の検証ディレクティブを作成することだと思います。

.directive('myValidRec', function () {
  var genRegex = function(type){ //...
  };
  return {
    require:'ngModel',
    link: function (scope, el, attrs, ngModel) {

      var validate = function(data){
        var regex = genRegex(scope.$eval(attrs.myValidRec));
        if(regex){
          ngModel.$setValidity('record', regex[0].test(data));  
        }
        return data;
      };

      // triggers validation when the model value changes
      ngModel.$formatters.push(validate);
      ngModel.$parsers.push(validate);

      // triggers validation when the user changes the record type
      scope.$watch(attrs.myValidRec,function(){
        validate(scope.$eval(attrs.ngModel));
      });
    }
  }
});

これにより、よりクリーンなマークアップが可能になります。

<td>
  <select ng-model="record.type" ng-options="c for c in types">
  </select>
</td>

<td>
  <ng-form name="innercContentForm">
    <span ng-show="innercContentForm.content.$error.record">
      Pattern error ( {{ record.type }} )
    </span>
    <input type="text" ng-model="record.content" name="content" 
           my-valid-rec="record.type" required />
  </ng-form>
</td>

このplnkrをチェックしてください:http://plnkr.co/edit/QzQdYN?p= preview

于 2013-09-22T09:04:50.183 に答える