J'utilise Angular avec Bootstrap. Voici le code de référence:
<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 a des styles pour les champs invalides sous la forme de input:invalid {.... }
; ceux-ci entrent en jeu lorsque le champ est vide. Maintenant, j'ai aussi un motif correspondant par l'intermédiaire angulaire. Cela crée des cas étranges lorsque ": invalid" est désactivé, mais que ".ng-invalid" est activé, ce qui m'obligerait à réimplémenter bootstrap les classes CSS pour la classe ".ng-invalid".
Je vois deux options, mais avoir des problèmes avec les deux
Les directives Angular-Bootstrap ne couvrent pas le style.
Utilisez la classe "error" de Bootstrap pour le style. Vous pouvez écrire moins de code.
<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>
EDIT: Comme le soulignent d’autres réponses et commentaires - in Bootstrap 3, la classe est maintenant "has-error", pas "error".
Les classes ont changé dans 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>
...
Notez les guillemets autour de 'has-error'
et 'has-success'
: a mis du temps à trouver ça ...
Une autre solution: Créer une directive qui bascule has-error
classe selon une entrée enfant.
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);
});
}
}
};
}]);
puis utilisez-le simplement dans un modèle
<div class="form-group" bs-has-error>
<input class="form-control" ng-model="foo" ng-pattern="/.../"/>
</div>
Amélioration mineure à réponse de @ farincz . Je conviens qu’une directive est la meilleure approche ici, mais je ne voulais pas la répéter à chaque .form-group
element, j’ai donc mis à jour le code pour permettre de l’ajouter à la .form-group
ou au parent <form>
élément (qui l’ajoutera à tous les contenus .form-group
éléments):
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);
});
}
}
}
};
}]);
Amélioration mineure de la réponse de @Andrew Smith. Je change d'éléments d'entrée et j'utilise le mot clé 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);
});
});
}
});
}
};
}]);
Merci à @farincz pour cette excellente réponse. Voici quelques modifications que j'ai apportées pour correspondre à mon cas d'utilisation.
Cette version fournit trois directives:
bs-has-success
bs-has-error
bs-has
(Pratique pour utiliser les deux autres ensemble)Les modifications que j'ai apportées:
element.find()
pour ceux qui n'utilisent pas jQuery, car element.find()
dans jularite d'Angular ne prend en charge que la recherche d'éléments par nom.element.find()
dans un $timeout
Pour prendre en charge les cas où l'élément n'a pas encore ses enfants rendus au DOM (par exemple, si un enfant de l'élément est marqué avec ng-if
).if
pour vérifier la longueur du tableau renvoyé (if(input)
de réponse de @ farincz renvoie toujours la valeur true, comme le retour de element.find()
est un tableau jQuery).J'espère que quelqu'un trouvera cela utile!
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');
}
};
});
Usage:
<!-- 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>
Vous pouvez également installer le package bower de Guilherme qui regroupe tout cela ensemble.
Si le style pose problème, mais que vous ne souhaitez pas désactiver la validation native, pourquoi ne pas remplacer le style par votre propre style, plus spécifique style?
input.ng-invalid, input.ng-invalid:invalid {
background: red;
/*override any styling giving you fits here*/
}
Cascade vos problèmes avec la spécificité de sélecteur CSS!
Mon amélioration à la réponse de Jason Im ajoute ce qui suit deux nouvelles directives show-validation-errors et 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);
});
}
};
});
})();
Les erreurs show-validation-peuvent être ajoutées à un conteneur d'erreurs afin qu'il puisse afficher/masquer le conteneur en fonction de la validité des champs du formulaire.
et l'erreur show-validation-error affiche ou masque un élément en fonction de la validité des champs de formulaire sur un type donné.
Un exemple d'utilisation prévue:
<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>
Je pense qu'il est trop tard pour répondre mais j'espère que vous allez l'aimer:
CSS vous pouvez ajouter d'autres types de contrôles tels que select, date, password, etc
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 : inutile d'ajouter quoi que ce soit dans les contrôles sauf ng-required si c'est le cas
<input type="text"
class="form-control"
ng-model="customer.ZipCode"
ng-required="true">
Essayez-le et tapez du texte sous votre contrôle, je le trouve vraiment pratique et génial.
Je sais que c’est un très vieux fil de questions-réponses quand je n’ai pas entendu le nom d’AngularJS lui-même :-)
Mais pour les autres qui atterrissent sur cette page à la recherche de la validation des formulaires Angular + Bootstrap de manière propre et automatisée, j’ai écrit un assez petit module permettant d’obtenir la même chose sans modifier le code HTML ou Javascript dans aucun des cas. forme.
Checkout Validation de Bootstrap Angular .
Voici les trois étapes simples:
bower install bootstrap-angular-validation --save
<script src="bower_components/bootstrap-angular-validation/dist/bootstrap-angular-validation.min.js"></script>
bootstrap.angular.validation
À votre application et c'est tout !! Cela fonctionne avec Bootstrap 3 et jQuery est non requis .
Ceci est basé sur le concept de validation jQuery. Ce module fournit une validation supplémentaire et des messages génériques communs en cas d'erreur de validation.
<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>
Il est difficile de dire avec certitude sans un violon, mais l'examen du code angular.js ne remplace pas les classes, il ajoute et supprime le sien. Ainsi, toutes les classes bootstrap (ajoutées dynamiquement par bootstrap UI)) ne doivent pas être modifiées de manière angulaire.
Cela dit, il n’a aucun sens d’utiliser la fonctionnalité JS de Bootstrap pour la validation en même temps que Angular - utilisez uniquement Angular. Je vous suggérerais d’employer le bootstrap = styles et le angular JS, c’est-à-dire, ajoutez les classes bootstrap css à vos éléments à l’aide d’une directive de validation personnalisée.