72

Bootstrap で Angular を使用しています。参照用のコードは次のとおりです。

<form name="newUserForm" ng-submit="add()" class="" novalidate>
    <input type="text" class="input" ng-model="newUser.uname" placeholder="Twitter" ng-pattern="/^@[A-Za-z0-9_]{1,15}$/" required></td>
    <button type="submit" ng-disabled="newUserForm.$invalid" class="btn btn-add btn-primary">Add</button>
</form>

Bootstrap には、無効なフィールドのスタイルがinput:invalid {.... };の形式で含まれています。これらは、フィールドが空のときに開始されます。これで、Angular を介したパターン マッチングもできました。これにより、「:invalid」がオフで「.ng-invalid」がオンの場合に奇妙なケースが作成され、「.ng-invalid」クラスのブートストラップ CSS クラスを再実装する必要があります。

2 つの選択肢があるが、どちらも問題がある

  • Angular で「ng-valid」の代わりにカスタム クラス名を使用するようにします (これを行う方法がわかりません)。
  • html5検証を無効にします(フォームタグの「novalidate」属性が行うべきことだと思いましたが、何らかの理由で機能しませんでした)。

そこにある Angular-Bootstrap ディレクティブはスタイリングをカバーしていません。

4

12 に答える 12

92

スタイリングには Bootstrap の「エラー」クラスを使用します。より少ないコードを記述できます。

<form name="myForm">
  <div class="control-group" ng-class="{error: myForm.name.$invalid}">
    <label>Name</label>
    <input type="text" name="name" ng-model="project.name" required>
    <span ng-show="myForm.name.$error.required" class="help-inline">
        Required</span>
  </div>
</form>

編集: 他の回答とコメントが指摘するように-Bootstrap 3では、クラスは「エラー」ではなく「エラーがあります」になりました。

于 2013-02-19T09:08:13.470 に答える
47

クラスは Bootstrap 3 で変更されました。

<form class="form-horizontal" name="form" novalidate ng-submit="submit()" action="/login" method="post">
  <div class="row" ng-class="{'has-error': form.email.$invalid, 'has-success': !form.email.$invalid}">
    <label for="email" class="control-label">email:</label>
    <div class="col">
    <input type="email" id="email" placeholder="email" name="email" ng-model="email" required>
    <p class="help-block error" ng-show="form.email.$dirty && form.email.$error.required">please enter your email</p>
    <p class="help-block error" ng-show="form.email.$error.email">please enter a valid email</p>
  ...

'has-error'との周りの引用符に注意してください'has-success': それを見つけるのにしばらく時間がかかりました...

于 2013-06-25T20:22:23.433 に答える
34

has-error別の解決策:子入力に従ってクラス を切り替えるディレクティブを作成します。

app.directive('bsHasError', [function() {
  return {
      restrict: "A",
      link: function(scope, element, attrs, ctrl) {
          var input = element.find('input[ng-model]'); 
          if (input.length) {
              scope.$watch(function() {
                  return input.hasClass('ng-invalid');
              }, function(isInvalid) {
                  element.toggleClass('has-error', isInvalid);
              });
          }
      }
  };
}]);

そして、それをテンプレートで簡単に使用します

<div class="form-group" bs-has-error>
    <input class="form-control" ng-model="foo" ng-pattern="/.../"/>
</div>
于 2014-02-12T21:20:11.377 に答える
22

@farincz's answer のマイナーな改善。ここではディレクティブが最善のアプローチであることに同意しますが、すべての要素でそれを繰り返す必要はなかった.form-groupので、コードを更新して、.form-groupまたは親<form>要素に追加できるようにしました (これにより、含まれるすべての.form-group要素に追加されます) ):

angular.module('directives', [])
  .directive('showValidation', [function() {
    return {
        restrict: "A",
        link: function(scope, element, attrs, ctrl) {

            if (element.get(0).nodeName.toLowerCase() === 'form') {
                element.find('.form-group').each(function(i, formGroup) {
                    showValidation(angular.element(formGroup));
                });
            } else {
                showValidation(element);
            }

            function showValidation(formGroupEl) {
                var input = formGroupEl.find('input[ng-model],textarea[ng-model]');
                if (input.length > 0) {
                    scope.$watch(function() {
                        return input.hasClass('ng-invalid');
                    }, function(isInvalid) {
                        formGroupEl.toggleClass('has-error', isInvalid);
                    });
                }
            }
        }
    };
}]);
于 2014-03-19T12:30:53.723 に答える
17

@Andrew Smithの回答に対するマイナーな改善。入力要素と使用するrequireキーワードを変更します。

.directive('showValidation', [function() {
    return {
        restrict: "A",
        require:'form',
        link: function(scope, element, attrs, formCtrl) {
            element.find('.form-group').each(function() {
                var $formGroup=$(this);
                var $inputs = $formGroup.find('input[ng-model],textarea[ng-model],select[ng-model]');

                if ($inputs.length > 0) {
                    $inputs.each(function() {
                        var $input=$(this);
                        scope.$watch(function() {
                            return $input.hasClass('ng-invalid');
                        }, function(isInvalid) {
                            $formGroup.toggleClass('has-error', isInvalid);
                        });
                    });
                }
            });
        }
    };
}]);
于 2014-07-04T08:54:25.393 に答える
11

すばらしい答えをくれた@farinczに感謝します。ユースケースに合わせていくつかの変更を加えました。

このバージョンには、次の 3 つのディレクティブが用意されています。

  • bs-has-success
  • bs-has-error
  • bs-has(他の2つを併用したい場合に便利)

私が行った変更:

  • フォーム フィールドがダーティな場合にのみ has ステートを表示するチェックを追加しました。つまり、誰かが操作するまで表示されません。
  • Angular の jQLite では、タグ名による要素の検索のみがサポートされelement.find()ているため、jQuery を使用していない場合に 渡される文字列を変更しました。element.find()
  • 選択ボックスとテキストエリアのサポートが追加されました。
  • 要素の子がまだ DOM にレンダリングされていない可能性がある場合 (たとえば、要素の子が でマークされている場合) をサポートするためelement.find()に、をラップしました。$timeoutng-if
  • if返された配列の長さをチェックするように式を変更しました ( if(input)from @farincz の回答は常に true を返しますelement.find()。これは、from が jQuery 配列であるためです)。

誰かがこれが役立つことを願っています!

angular.module('bs-has', [])
  .factory('bsProcessValidator', function($timeout) {
    return function(scope, element, ngClass, bsClass) {
      $timeout(function() {
        var input = element.find('input');
        if(!input.length) { input = element.find('select'); }
        if(!input.length) { input = element.find('textarea'); }
        if (input.length) {
            scope.$watch(function() {
                return input.hasClass(ngClass) && input.hasClass('ng-dirty');
            }, function(isValid) {
                element.toggleClass(bsClass, isValid);
            });
        }
      });
    };
  })
  .directive('bsHasSuccess', function(bsProcessValidator) {
    return {
      restrict: 'A',
      link: function(scope, element) {
        bsProcessValidator(scope, element, 'ng-valid', 'has-success');
      }
    };
  })
  .directive('bsHasError', function(bsProcessValidator) {
    return {
      restrict: 'A',
      link: function(scope, element) {
        bsProcessValidator(scope, element, 'ng-invalid', 'has-error');
      }
    };
  })
  .directive('bsHas', function(bsProcessValidator) {
    return {
      restrict: 'A',
      link: function(scope, element) {
        bsProcessValidator(scope, element, 'ng-valid', 'has-success');
        bsProcessValidator(scope, element, 'ng-invalid', 'has-error');
      }
    };
  });

使用法:

<!-- Will show success and error states when form field is dirty -->
<div class="form-control" bs-has>
  <label for="text"></label>
  <input 
   type="text" 
   id="text" 
   name="text" 
   ng-model="data.text" 
   required>
</div>

<!-- Will show success state when select box is anything but the first (placeholder) option -->
<div class="form-control" bs-has-success>
  <label for="select"></label>
  <select 
   id="select" 
   name="select" 
   ng-model="data.select" 
   ng-options="option.name for option in data.selectOptions"
   required>
    <option value="">-- Make a Choice --</option>
  </select>
</div>

<!-- Will show error state when textarea is dirty and empty -->
<div class="form-control" bs-has-error>
  <label for="textarea"></label>
  <textarea 
   id="textarea" 
   name="textarea" 
   ng-model="data.textarea" 
   required></textarea>
</div>

これらすべてをまとめたGuilherme's bower パッケージをインストールすることもできます。

于 2014-05-12T20:44:14.977 に答える
4

スタイルが問題であるが、ネイティブの検証を無効にしたくない場合は、独自のより具体的なスタイルでスタイルをオーバーライドしてみませんか?

input.ng-invalid, input.ng-invalid:invalid {
   background: red;
   /*override any styling giving you fits here*/
}

CSS セレクターの特異性により、問題をカスケードします。

于 2013-02-04T20:39:07.570 に答える
2

返信するには遅すぎると思いますが、気に入っていただけることを願っています。

選択、日付、パスワードなどの他のタイプのコントロールを追加できるCSS

input[type="text"].ng-invalid{
    border-left: 5px solid #ff0000;
    background-color: #FFEBD6;
}
input[type="text"].ng-valid{
    background-color: #FFFFFF;
    border-left: 5px solid #088b0b;
}
input[type="text"]:disabled.ng-valid{
    background-color: #efefef;
    border: 1px solid #bbb;
}

HTML : ng-required の場合を除いて、コントロールに何も追加する必要はありません。

<input type="text"
       class="form-control"
       ng-model="customer.ZipCode"
       ng-required="true">

試してみて、コントロールにテキストを入力してください。本当に便利で素晴らしいと思います。

于 2015-07-19T21:29:37.800 に答える
1
<div class="form-group has-feedback" ng-class="{ 'has-error': form.uemail.$invalid && form.uemail.$dirty }">
  <label class="control-label col-sm-2" for="email">Email</label>
  <div class="col-sm-10">
    <input type="email" class="form-control" ng-model="user.email" name="uemail" placeholder="Enter email" required>
    <div ng-show="form.$submitted || form.uphone.$touched" ng-class="{ 'has-success': form.uemail.$valid && form.uemail.$dirty }">
    <span ng-show="form.uemail.$valid" class="glyphicon glyphicon-ok-sign form-control-feedback" aria-hidden="true"></span>
    <span ng-show="form.uemail.$invalid && form.uemail.$dirty" class="glyphicon glyphicon-remove-circle form-control-feedback" aria-hidden="true"></span>
    </div>
  </div>
</div>
于 2015-12-28T11:22:07.043 に答える
1

フィドルなしで確実に判断するのは困難ですが、angular.js コードを見ると、クラスは置き換えられず、独自のクラスが追加および削除されるだけです。したがって、ブートストラップ クラス (ブートストラップ UI スクリプトによって動的に追加される) は、angular によって変更されないようにする必要があります。

とはいえ、Angular と同時に検証に Bootstrap の JS 機能を使用しても意味がありません。Angular のみを使用してください。ブートストラップ スタイルと angular JS を採用することをお勧めします。つまり、カスタム検証ディレクティブを使用して要素にブートストラップ css クラスを追加します。

于 2013-01-16T13:57:08.070 に答える