Ich benutze Angular mit Bootstrap. Hier ist der Code als Referenz:
<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 hat Stile für ungültige Felder in Form von input:invalid {.... }
; Diese treten ein, wenn das Feld leer ist. Jetzt habe ich auch einige Musterübereinstimmungen über Angular. Dies führt zu seltsamen Fällen, wenn ": invalid" deaktiviert ist, ".ng-invalid" jedoch aktiviert ist. Daher müsste ich die Bootstrap-CSS-Klassen für die Klasse ".ng-invalid" erneut implementieren.
Ich sehe zwei Möglichkeiten, habe aber Probleme mit beiden
- Lassen Sie Angular einen benutzerdefinierten Klassennamen anstelle von "ng-valid" verwenden (ich weiß nicht, wie das geht).
- Deaktivieren Sie die HTML5-Validierung (ich dachte, dass dies das Attribut "novalidate" im Formular-Tag tun sollte, konnte es aber aus irgendeinem Grund nicht zum Laufen bringen).
Die Angular-Bootstrap-Direktiven decken das Styling nicht ab.
twitter-bootstrap
angularjs
Ivan P.
quelle
quelle
Antworten:
Verwenden Sie die "Fehler" -Klasse von Bootstrap für das Styling. Sie können weniger Code schreiben.
<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>
BEARBEITEN: Wie andere Antworten und Kommentare zeigen - in Bootstrap 3 ist die Klasse jetzt "has-error", nicht "error".
quelle
ng-class="{'has-error': myForm.name.$invalid}"
&& myForm.name.$dirty
, damit der Validierungsstil erst angezeigt wird, nachdem der Benutzer mit dem Formularsteuerelement interagiert hat.Die Klassen haben sich in Bootstrap 3 geändert:
<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> ...
Beachten Sie die Anführungszeichen
'has-error'
und'has-success'
: Es dauerte eine Weile, bis ...quelle
ng-class="(form.email.$invalid ? 'has-error' : 'has-success')"
an die Arbeit gemacht?{'has-error': form.email.$dirty && form.email.$invalid, 'has-success': form.email.$dirty && !form.email.$invalid}
Jetzt wird dieser Ausdruck jedoch so lang, dass er für Tippfehler anfällig und schwer lesbar ist und immer ist ähnlich sollte es also einen besseren Weg geben, nicht?Eine andere Lösung: Erstellen Sie eine Direktive, die die
has-error
Klasse gemäß einer untergeordneten Eingabe umschaltet .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); }); } } }; }]);
und dann einfach in Vorlage verwenden
<div class="form-group" bs-has-error> <input class="form-control" ng-model="foo" ng-pattern="/.../"/> </div>
quelle
element[attribute]
Selektorsyntax nicht unterstützt. Daher muss dies ein wenig geändert werden, wenn Sie jQuery nicht verwenden.input.controller('ngModel').$invalid
stattinput.hasClass('ng-invalid')
. Ich hatte ein Problem damit, dass die CSS-Klasse nicht aktualisiert wurde, bevor $ watch ausgelöst wurde.Kleinere Verbesserung der Antwort von @ farincz . Ich bin damit einverstanden, dass eine Direktive hier der beste Ansatz ist, aber ich wollte sie nicht für jedes
.form-group
Element wiederholen müssen, also habe ich den Code aktualisiert, damit er entweder dem.form-group
oder dem übergeordneten<form>
Element hinzugefügt werden kann (wodurch er allen enthaltenen.form-group
Elementen hinzugefügt wird) ):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); }); } } } }; }]);
quelle
Kleinere Verbesserung der Antwort von @Andrew Smith. Ich ändere Eingabeelemente und benutze
require
Schlüsselwörter..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); }); }); } }); } }; }]);
quelle
Vielen Dank an @farincz für eine großartige Antwort. Hier sind einige Änderungen, die ich vorgenommen habe, um sie an meinen Anwendungsfall anzupassen.
Diese Version enthält drei Anweisungen:
bs-has-success
bs-has-error
bs-has
(eine Annehmlichkeit, wenn Sie die anderen beiden zusammen verwenden möchten)Von mir vorgenommene Änderungen:
element.find()
für diejenigen geändert, die jQuery nicht verwenden, daelement.find()
in Angulars jQLite nur das Suchen von Elementen anhand des Tagnamens unterstützt wird.element.find()
in a$timeout
, um Fälle zu unterstützen, in denen die Elemente des Elements möglicherweise noch nicht im DOM gerendert wurden (z. B. wenn ein untergeordnetes Element des Elements mit markiert istng-if
).if
Ausdruck wurde geändert , um die Länge des zurückgegebenen Arrays zu überprüfen (if(input)
aus der Antwort von @ farincz wird immer true zurückgegeben, da die Rückgabe vonelement.find()
ein jQuery-Array ist).Ich hoffe jemand findet das nützlich!
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'); } }; });
Verwendung:
<!-- 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>
Sie können auch das Laubenpaket von Guilherme installieren , das all dies zusammen bündelt.
quelle
.form-group
Elemente wiederholen können . Das ist schön, aber es funktioniert nur, wenn Sie jQuery einschließen, da die integrierte eckige jqlite-Implementierung vonfind
nur das Suchen nach Tagname und nicht nach Selektor unterstützt. Möglicherweise möchten Sie zu diesem Zweck eine Notiz in der README-Datei hinzufügen.form.$submitted
, um Fehler nur beim Senden anzuzeigen. In den Angular-Dokumenten finden Sie hier ein Beispiel: docs.angularjs.org/guide/forms . Suchen Sie nach der Überschrift "Bindung an Form und Kontrollstatus".Wenn das Styling das Problem ist, Sie aber die native Validierung nicht deaktivieren möchten, können Sie das Styling mit Ihrem eigenen, spezifischeren Stil überschreiben .
input.ng-invalid, input.ng-invalid:invalid { background: red; /*override any styling giving you fits here*/ }
Kaskadieren Sie Ihre Probleme mit der CSS-Selektorspezifität!
quelle
Meine Verbesserung der folgenden Antwort von Jason Im fügt zwei neue Anweisungen hinzu: show-validation-error und show-validation-error.
'use strict'; (function() { function getParentFormName(element,$log) { var parentForm = element.parents('form:first'); var parentFormName = parentForm.attr('name'); if(!parentFormName){ $log.error("Form name not specified!"); return; } return parentFormName; } angular.module('directives').directive('showValidation', function () { return { restrict: 'A', require: 'form', link: function ($scope, element) { 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') && !input.hasClass('ng-pristine'); }, function (isInvalid) { formGroup.toggleClass('has-error', isInvalid); }); $scope.$watch(function () { return input.hasClass('ng-valid') && !input.hasClass('ng-pristine'); }, function (isInvalid) { formGroup.toggleClass('has-success', isInvalid); }); }); } }); } }; }); angular.module('directives').directive('showValidationErrors', function ($log) { return { restrict: 'A', link: function ($scope, element, attrs) { var parentFormName = getParentFormName(element,$log); var inputName = attrs['showValidationErrors']; element.addClass('ng-hide'); if(!inputName){ $log.error("input name not specified!") return; } $scope.$watch(function () { return !($scope[parentFormName][inputName].$dirty && $scope[parentFormName][inputName].$invalid); },function(noErrors){ element.toggleClass('ng-hide',noErrors); }); } }; }); angular.module('friport').directive('showValidationError', function ($log) { return { restrict: 'A', link: function ($scope, element, attrs) { var parentFormName = getParentFormName(element,$log); var parentContainer = element.parents('*[show-validation-errors]:first'); var inputName = parentContainer.attr('show-validation-errors'); var type = attrs['showValidationError']; element.addClass('ng-hide'); if(!inputName){ $log.error("Could not find parent show-validation-errors!"); return; } if(!type){ $log.error("Could not find validation error type!"); return; } $scope.$watch(function () { return !$scope[parentFormName][inputName].$error[type]; },function(noErrors){ element.toggleClass('ng-hide',noErrors); }); } }; }); })();
Die Show-Validation-Fehler können einem Fehlercontainer hinzugefügt werden, sodass der Container basierend auf der Gültigkeit eines Formularfelds angezeigt / ausgeblendet wird.
und der Show-Validierungsfehler zeigt oder verbirgt ein Element, das auf der Gültigkeit dieses Formularfelds für einen gegebenen Typ basiert.
Ein Beispiel für den Verwendungszweck:
<form role="form" name="organizationForm" novalidate show-validation> <div class="form-group"> <label for="organizationNumber">Organization number</label> <input type="text" class="form-control" id="organizationNumber" name="organizationNumber" required ng-pattern="/^[0-9]{3}[ ]?[0-9]{3}[ ]?[0-9]{3}$/" ng-model="organizationNumber"> <div class="help-block with-errors" show-validation-errors="organizationNumber"> <div show-validation-error="required"> Organization number is required. </div> <div show-validation-error="pattern"> Organization number needs to have the following format "000 000 000" or "000000000". </div> </div> </div> </form>
quelle
Ich denke, es ist zu spät, um zu antworten, aber ich hoffe, Sie werden es lieben:
Mit CSS können Sie andere Steuerelemente wie Auswahl, Datum, Kennwort usw. Hinzufügen
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 : Es ist nicht erforderlich, Steuerelemente hinzuzufügen, außer ng-require, falls dies der Fall ist
<input type="text" class="form-control" ng-model="customer.ZipCode" ng-required="true">
Probieren Sie es einfach aus und geben Sie Text in Ihr Steuerelement ein. Ich finde es sehr praktisch und großartig.
quelle
Ohne Geige ist es schwer zu sagen, aber wenn man sich den Code angle.js ansieht, ersetzt er keine Klassen - er fügt nur seine eigenen hinzu und entfernt sie. Daher sollten alle Bootstrap-Klassen (die dynamisch durch Bootstrap-UI-Skripte hinzugefügt werden) von Angular unberührt bleiben.
Es ist jedoch nicht sinnvoll, die JS-Funktionalität von Bootstrap zur Validierung gleichzeitig mit Angular zu verwenden - verwenden Sie nur Angular. Ich würde vorschlagen, dass Sie die Bootstrap-Stile und das eckige JS verwenden, dh die Bootstrap-CSS-Klassen mithilfe einer benutzerdefinierten Validierungsanweisung zu Ihren Elementen hinzufügen.
quelle
<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>
quelle
Ich weiß, dass dies ein sehr alter Frage-Antwort-Thread ist, wenn ich den Namen AngularJS selbst nicht gehört habe :-)
Aber für andere, die auf dieser Seite landen und auf saubere und automatisierte Weise nach einer Angular + Bootstrap-Formularvalidierung suchen, habe ich ein ziemlich kleines Modul geschrieben, um dasselbe zu erreichen, ohne HTML oder Javascript in irgendeiner Form zu ändern.
Checkout Bootstrap Angular Validation .
Es folgen die drei einfachen Schritte:
bower install bootstrap-angular-validation --save
<script src="bower_components/bootstrap-angular-validation/dist/bootstrap-angular-validation.min.js"></script>
bootstrap.angular.validation
zu Ihrer Anwendung hinzu und fertig!Dies funktioniert mit Bootstrap 3 und jQuery ist nicht erforderlich .
Dies basiert auf dem Konzept der jQuery-Validierung. Dieses Modul bietet einige zusätzliche Validierungs- und allgemeine generische Meldungen für Validierungsfehler.
quelle