170

ng-repeatを使用して作成されたテーブルがあります。テーブルの各要素に検証を追加したいと思います。問題は、各入力セルの名前が上下のセルと同じであるということです。値を使用し{{$index}}て入力に名前を付けようとしましたが、HTMLの文字列リテラルが正しく表示されているにもかかわらず、機能しています。

これが今の私のコードです:

<tr ng-repeat="r in model.BSM ">
   <td>
      <input ng-model="r.QTY" class="span1" name="QTY{{$index}}" ng-pattern="/^[\d]*\.?[\d]*$/" required/>
      <span class="alert-error" ng-show="form.QTY{{$index}}.$error.pattern"><strong>Requires a number.</strong></span>
      <span class="alert-error" ng-show="form.QTY{{$index}}.$error.required"><strong>*Required</strong></span>
   </td>
</tr>

インデックスから削除しようとしました{{}}が、それも機能しません。現在、入力の検証プロパティは正しく機能していますが、エラーメッセージは表示されません。

誰か提案がありますか?

編集:以下の優れた回答に加えて、この問題をより詳細にカバーするブログ記事があります:http ://www.thebhwgroup.com/blog/2014/08/angularjs-html-form-design-part-2 //

4

14 に答える 14

231

質問が寄せられて以来、Angular チームは入力名を動的に作成できるようにすることでこの問題を解決しました。

Angular バージョン 1.3 以降では、これを実行できるようになりました。

<form name="vm.myForm" novalidate>
  <div ng-repeat="p in vm.persons">
    <input type="text" name="person_{{$index}}" ng-model="p" required>
    <span ng-show="vm.myForm['person_' + $index].$invalid">Enter a name</span>
  </div>
</form>

デモ

Angular 1.3 では、フォーム検証のためのより強力なツールである ngMessages も導入されました。ngMessages でも​​同じ手法を使用できます。

<form name="vm.myFormNgMsg" novalidate>
    <div ng-repeat="p in vm.persons">
      <input type="text" name="person_{{$index}}" ng-model="p" required>
      <span ng-messages="vm.myFormNgMsg['person_' + $index].$error">
        <span ng-message="required">Enter a name</span>
      </span>
    </div>
  </form>
于 2015-10-02T12:27:46.370 に答える
197

AngularJS は入力名に依存して検証エラーを公開します。

残念ながら、現在のところ、(カスタム ディレクティブを使用しないと) 入力の名前を動的に生成することはできません。確かに、入力ドキュメントを確認すると、name 属性が文字列のみを受け入れることがわかります。

「動的な名前」の問題を解決するには、内部フォームを作成する必要があります ( ng-formを参照) :

<div ng-repeat="social in formData.socials">
      <ng-form name="urlForm">
            <input type="url" name="socialUrl" ng-model="social.url">
            <span class="alert error" ng-show="urlForm.socialUrl.$error.url">URL error</span>
      </ng-form>
  </div>

もう 1 つの方法は、このためのカスタム ディレクティブを作成することです。

ngForm の使用法を示す jsFiddle は次のとおりです: http://jsfiddle.net/pkozlowski_opensource/XK2ZT/2/

于 2012-08-20T20:24:29.823 に答える
13

ng-form を使用したくない場合は、フォームの name 属性を変更するカスタム ディレクティブを使用できます。このディレクティブを ng-model と同じ要素の属性として配置します。

他のディレクティブを組み合わせて使用​​している場合は、「ターミナル」プロパティが設定されていないことに注意してください。そうしないと、この関数を実行できません (優先度が -1 の場合)。

たとえば、このディレクティブを ng-options とともに使用する場合、次の 1 行の monkeypatch を実行する必要があります: https://github.com/AlJohri/bower-angular/commit/eb17a967b7973eb7fc1124b024aa8b3ca540a155

angular.module('app').directive('fieldNameHack', function() {
    return {
      restrict: 'A',
      priority: -1,
      require: ['ngModel'],
      // the ngModelDirective has a priority of 0.
      // priority is run in reverse order for postLink functions.
      link: function (scope, iElement, iAttrs, ctrls) {

        var name = iElement[0].name;
        name = name.replace(/\{\{\$index\}\}/g, scope.$index);

        var modelCtrl = ctrls[0];
        modelCtrl.$name = name;

      }
    };
});

ng-init を使用して $index を変数名に設定すると便利なことがよくあります。例えば:

<fieldset class='inputs' ng-repeat="question questions" ng-init="qIndex = $index">

これにより、正規表現が次のように変更されます。

name = name.replace(/\{\{qIndex\}\}/g, scope.qIndex);

複数のネストされた ng-repeat がある場合、$parent.$index の代わりにこれらの変数名を使用できるようになりました。

ディレクティブの「ターミナル」と「優先度」の定義: https://docs.angularjs.org/api/ng/service/ $compile#directive-definition-object

ng-option monkeypatch の必要性に関する Github コメント: https://github.com/angular/angular.js/commit/9ee2cdff44e7d496774b340de816344126c457b3#commitcomment-6832095 https://twitter.com/aljohri/status/482963541520314369

アップデート:

これを ng-form で機能させることもできます。

angular.module('app').directive('formNameHack', function() {
    return {
      restrict: 'A',
      priority: 0,
      require: ['form'],
      compile: function() {
        return {
          pre: function(scope, iElement, iAttrs, ctrls) {
            var parentForm = $(iElement).parent().controller('form');
            if (parentForm) {
                var formCtrl = ctrls[0];
                delete parentForm[formCtrl.$name];
                formCtrl.$name = formCtrl.$name.replace(/\{\{\$index\}\}/g, scope.$index);
                parentForm[formCtrl.$name] = formCtrl;
            }
          }
        }
      }
    };
});
于 2014-06-28T20:00:52.570 に答える
1

pkozlowski.opensource's answerに基づいて、 ngMessagesでも​​機能する動的な入力名を持つ方法を追加しました。要素のng-init部分と の使用に注意してください。の属性の変数値を含む変数名になります。ng-formfurryNamefurryNameinputname

<ion-item ng-repeat="animal in creatures track by $index">
<ng-form name="animalsForm" ng-init="furryName = 'furry' + $index">
        <!-- animal is furry toggle buttons -->
        <input id="furryRadio{{$index}}"
               type="radio"
               name="{{furryName}}"
               ng-model="animal.isFurry"
               ng-value="radioBoolValues.boolTrue"
               required
                >
        <label for="furryRadio{{$index}}">Furry</label>

        <input id="hairlessRadio{{$index}}"
               name="{{furryName}}"
               type="radio"
               ng-model="animal.isFurry"
               ng-value="radioBoolValues.boolFalse"
               required
               >
        <label for="hairlessRadio{{$index}}">Hairless</label>

        <div ng-messages="animalsForm[furryName].$error"
             class="form-errors"
             ng-show="animalsForm[furryName].$invalid && sectionForm.$submitted">
            <div ng-messages-include="client/views/partials/form-errors.ng.html"></div>
        </div>
</ng-form>
</ion-item>
于 2015-08-28T03:41:18.427 に答える
0

これにより、ng-repeat で名前が取得され、フォーム検証で個別に表示されます。

<td>
    <input ng-model="r.QTY" class="span1" name="{{'QTY' + $index}}" ng-pattern="/^[\d]*\.?[\d]*$/" required/>
</td>

しかし、検証メッセージで検索するのに苦労したので、ng-init を使用して変数をオブジェクト キーとして解決する必要がありました。

<td>
    <input ng-model="r.QTY" class="span1" ng-init="name = 'QTY' + $index" name="{{name}}" ng-pattern="/^[\d]*\.?[\d]*$/" required/>
    <span class="alert-error" ng-show="form[name].$error.pattern"><strong>Requires a number.</strong></span>
    <span class="alert-error" ng-show="form[name].$error.required"><strong>*Required</strong></span> 

于 2015-05-04T13:38:52.883 に答える
0

私の要件は、元の質問で尋ねられたものとは少し異なりましたが、うまくいけば、私と同じ問題を抱えている人を助けることができます..

スコープ変数に基づいて、フィールドが必要かどうかを定義する必要がありました..したがって、基本的に設定する必要がありましたng-required="myScopeVariable"(これはブール変数です)。

<div class="align-left" ng-repeat="schema in schemas">
    <input type="text" ng-required="schema.Required" />
</div>
于 2016-10-28T01:57:15.167 に答える