forms - validacion - validar formulario javascript onclick
Validar campos despuƩs de que el usuario haya dejado un campo (17)
Con AngularJS, puedo usar ng-pristine
o ng-dirty
para detectar si el usuario ha ingresado al campo. Sin embargo, quiero hacer la validación del lado del cliente solo después de que el usuario haya abandonado el área del campo. Esto se debe a que cuando un usuario ingresa a un campo como el correo electrónico o el teléfono, siempre recibirá un error hasta que haya terminado de escribir su correo electrónico completo, y esta no es una experiencia de usuario óptima.
ACTUALIZAR:
Angular ahora se envía con un evento de desenfoque personalizado: https://docs.angularjs.org/api/ng/directive/ngBlur
A partir de la versión 1.3.0 esto se puede hacer fácilmente con $touched
, lo cual es cierto después de que el usuario haya abandonado el campo.
<p ng-show="form.field.$touched && form.field.$invalid">Error</p>
https://docs.angularjs.org/api/ng/type/ngModel.NgModelController
Al usar ng-focus puedes lograr tu objetivo. necesita proporcionar ng-focus en su campo de entrada. Y al escribir sus derivados de ng-show, debe escribir una lógica que no sea igual también. Como el siguiente código:
<input type="text" class="form-control" name="inputPhone" ng-model="demo.phoneNumber" required ng-focus> <div ng-show="demoForm.inputPhone.$dirty && demoForm.inputPhone.$invalid && !demoForm.inputPhone.$focused"></div>
Angular 1.3 ahora tiene opciones ng-model, y puede configurar la opción como { ''updateOn'': ''blur''}
por ejemplo, e incluso puede rebotar, cuando el uso es escribir muy rápido o quiere guardar un algunas costosas operaciones de DOM (como un modelo de escritura en varios lugares DOM y no desea un ciclo $ digest en cada tecla)
https://docs.angularjs.org/guide/forms#custom-triggers y https://docs.angularjs.org/guide/forms#non-immediate-debounced-model-updates
De manera predeterminada, cualquier cambio en el contenido activará una actualización del modelo y la validación del formulario. Puede anular este comportamiento utilizando la directiva ngModelOptions para vincular solo a la lista de eventos especificada. Ie ng-model-options = "{updateOn: ''blur''}" se actualizará y validará solo después de que el control pierda el foco. Puede establecer varios eventos usando una lista delimitada por espacios. Ie ng-model-options = "{updateOn: ''mousedown blur''}"
Y rebotar
Puede retrasar la actualización / validación del modelo utilizando la clave antirrebote con la directiva ngModelOptions. Esta demora también se aplicará a analizadores sintácticos, validadores y indicadores de modelo como $ dirty o $ pristine.
Ie ng-model-options = "{rebote: 500}" esperará medio segundo desde el último cambio de contenido antes de activar la actualización del modelo y la validación del formulario.
Aquí hay un ejemplo que usa ng-messages (disponible en angular 1.3) y una directiva personalizada.
El mensaje de validación se muestra en el desenfoque por primera vez cuando el usuario abandona el campo de entrada, pero cuando corrige el valor, el mensaje de validación se elimina inmediatamente (ya no se borra).
JavaScript
myApp.directive("validateOnBlur", [function() {
var ddo = {
restrict: "A",
require: "ngModel",
scope: {},
link: function(scope, element, attrs, modelCtrl) {
element.on(''blur'', function () {
modelCtrl.$showValidationMessage = modelCtrl.$dirty;
scope.$apply();
});
}
};
return ddo;
}]);
HTML
<form name="person">
<input type="text" ng-model="item.firstName" name="firstName"
ng-minlength="3" ng-maxlength="20" validate-on-blur required />
<div ng-show="person.firstName.$showValidationMessage" ng-messages="person.firstName.$error">
<span ng-message="required">name is required</span>
<span ng-message="minlength">name is too short</span>
<span ng-message="maxlength">name is too long</span>
</div>
</form>
PD. No olvide descargar e incluir ngMessages en su módulo:
var myApp = angular.module(''myApp'', [''ngMessages'']);
En @lambinator''s solución de @lambinator''s ... estaba obteniendo el siguiente error en angular.js 1.2.4:
Error: [$ rootScope: inprog] $ digest ya está en progreso
No estoy seguro de si hice algo mal o si esto es un cambio en Angular, pero eliminando el scope.$apply
resuelve el problema y las clases / estados todavía se están actualizando.
Si también está viendo este error, pruebe lo siguiente:
var blurFocusDirective = function () {
return {
restrict: ''E'',
require: ''?ngModel'',
link: function (scope, elm, attr, ctrl) {
if (!ctrl) {
return;
}
elm.on(''focus'', function () {
elm.addClass(''has-focus'');
ctrl.$hasFocus = true;
});
elm.on(''blur'', function () {
elm.removeClass(''has-focus'');
elm.addClass(''has-visited'');
ctrl.$hasFocus = false;
ctrl.$hasVisited = true;
});
elm.closest(''form'').on(''submit'', function () {
elm.addClass(''has-visited'');
scope.$apply(function () {
ctrl.hasFocus = false;
ctrl.hasVisited = true;
});
});
}
};
};
app.directive(''input'', blurFocusDirective);
app.directive(''select'', blurFocusDirective);
Esto parece implementarse como estándar en las versiones más nuevas de angular.
Las clases ng-untouched y ng-touched se establecen respectivamente antes y después de que el usuario haya tenido foco en un elemento validado.
CSS
input.ng-touched.ng-invalid {
border-color: red;
}
Lo resolví ampliando lo que sugirió @jlmcdonald. Creé una directiva que se aplicaría automáticamente a todos los elementos de entrada y selección:
var blurFocusDirective = function () {
return {
restrict: ''E'',
require: ''?ngModel'',
link: function (scope, elm, attr, ctrl) {
if (!ctrl) {
return;
}
elm.on(''focus'', function () {
elm.addClass(''has-focus'');
scope.$apply(function () {
ctrl.hasFocus = true;
});
});
elm.on(''blur'', function () {
elm.removeClass(''has-focus'');
elm.addClass(''has-visited'');
scope.$apply(function () {
ctrl.hasFocus = false;
ctrl.hasVisited = true;
});
});
elm.closest(''form'').on(''submit'', function () {
elm.addClass(''has-visited'');
scope.$apply(function () {
ctrl.hasFocus = false;
ctrl.hasVisited = true;
});
});
}
};
};
app.directive(''input'', blurFocusDirective);
app.directive(''select'', blurFocusDirective);
Esto agregará clases has-focus
y has-visited
a varios elementos a medida que el usuario enfoca / visita los elementos. A continuación, puede agregar estas clases a sus reglas de CSS para mostrar los errores de validación:
input.has-visited.ng-invalid:not(.has-focus) {
background-color: #ffeeee;
}
Esto funciona bien porque los elementos todavía obtienen $ propiedades inválidas, etc., pero el CSS se puede usar para brindarle al usuario una mejor experiencia.
Logré hacer esto con un poco de CSS muy simple. Esto requiere que los mensajes de error sean hermanos de la entrada con la que se relacionan y que tengan una clase de error
.
:focus ~ .error {
display:none;
}
Después de cumplir esos dos requisitos, esto ocultará cualquier mensaje de error relacionado con un campo de entrada enfocado, algo que creo que angularjs debería estar haciendo de todos modos. Parece un descuido.
Para continuar con las respuestas dadas, puede simplificar el etiquetado de entrada mediante el uso de pseudo-clases CSS3 y solo marcar los campos visitados con una clase para retrasar la visualización de los errores de validación hasta que el usuario pierda el foco en el campo:
(El ejemplo requiere jQuery)
JavaScript
module = angular.module(''app.directives'', []);
module.directive(''lateValidateForm'', function () {
return {
restrict: ''AC'',
link: function (scope, element, attrs) {
$inputs = element.find(''input, select, textarea'');
$inputs.on(''blur'', function () {
$(this).addClass(''has-visited'');
});
element.on(''submit'', function () {
$inputs.addClass(''has-visited'');
});
}
};
});
CSS
input.has-visited:not(:focus):required:invalid,
textarea.has-visited:not(:focus):required:invalid,
select.has-visited:not(:focus):required:invalid {
color: #b94a48;
border-color: #ee5f5b;
}
HTML
<form late-validate-form name="userForm">
<input type="email" name="email" required />
</form>
Podemos usar las funciones onfocus y onblur. Sería simple y mejor
<body ng-app="formExample">
<div ng-controller="ExampleController">
<form novalidate class="css-form">
Name: <input type="text" ng-model="user.name" ng-focus="onFocusName=''focusOn''" ng-blur="onFocusName=''''" ng-class="onFocusName" required /><br />
E-mail: <input type="email" ng-model="user.email" ng-focus="onFocusEmail=''focusOn''" ng-blur="onFocusEmail=''''" ng-class="onFocusEmail" required /><br />
</form>
</div>
<style type="text/css">
.css-form input.ng-invalid.ng-touched {
border: 1px solid #FF0000;
background:#FF0000;
}
.css-form input.focusOn.ng-invalid {
border: 1px solid #000000;
background:#FFFFFF;
}
</style>
Intenta aquí:
Podría funcionar para usted escribir una directiva personalizada que ajuste el método javascript blur () (y ejecute una función de validación cuando se active); hay un problema angular que tiene un ejemplo (además de una directiva genérica que puede vincularse a otros eventos no admitidos nativamente por Angular):
https://github.com/angular/angular.js/issues/1277
Si no desea seguir esa ruta, su otra opción sería configurar $ watch en el campo, lo que de nuevo activará la validación cuando se complete el campo.
Puede establecer dinámicamente la clase hash de error css (suponiendo que está utilizando el arranque) utilizando ng-class y una propiedad en el alcance del controlador asociado:
plunkr: http://plnkr.co/edit/HYDlaTNThZE02VqXrUCH?p=info
HTML:
<div ng-class="{''has-error'': badEmailAddress}">
<input type="email" class="form-control" id="email" name="email"
ng-model="email"
ng-blur="emailBlurred(email.$valid)">
</div>
Controlador:
$scope.badEmailAddress = false;
$scope.emailBlurred = function (isValid) {
$scope.badEmailAddress = !isValid;
};
Si usa bootstrap 3 y lesscss, puede activar la validación de desenfoque con el siguiente fragmento de menos:
:focus ~ .form-control-feedback.glyphicon-ok {
display:none;
}
:focus ~ .form-control-feedback.glyphicon-remove {
display:none;
}
.has-feedback > :focus {
& {
.form-control-focus();
}
}
Usar el estado del campo $ tocado El campo ha sido tocado para esto como se muestra en el ejemplo a continuación.
<div ng-show="formName.firstName.$touched && formName.firstName.$error.required">
You must enter a value
</div>
basado en la respuesta de @nicolas. El CSS puro debería ser el truco, solo mostrará el mensaje de error en el desenfoque
<input type="email" id="input-email" required
placeholder="Email address" class="form-control" name="email"
ng-model="userData.email">
<p ng-show="form.email.$error.email" class="bg-danger">This is not a valid email.</p>
CSS
.ng-invalid:focus ~ .bg-danger {
display:none;
}
ng-model-options en AngularJS 1.3 (beta al momento de escribir este documento) está documentado para admitir {updateOn: ''blur''}. Para versiones anteriores, algo como lo siguiente funcionó para mí:
myApp.directive(''myForm'', function() {
return {
require: ''form'',
link: function(scope, element, attrs, formController) {
scope.validate = function(name) {
formController[name].isInvalid
= formController[name].$invalid;
};
}
};
});
Con una plantilla como esta:
<form name="myForm" novalidate="novalidate" data-my-form="">
<input type="email" name="eMail" required="required" ng-blur="validate(''eMail'')" />
<span ng-show="myForm.eMail.isInvalid">Please enter a valid e-mail address.</span>
<button type="submit">Submit Form</button>
</form>
outIuse una directiva. Aquí está el código:
app.directive(''onBlurVal'', function () {
return {
restrict: ''A'',
link: function (scope, element, attrs, controller) {
element.on(''focus'', function () {
element.next().removeClass(''has-visited'');
element.next().addClass(''has-focus'');
});
element.on(''blur'', function () {
element.next().removeClass(''has-focus'');
element.next().addClass(''has-visited'');
});
}
}
})
Todo mi control de entrada tiene un elemento span como el siguiente elemento, que es donde se muestra mi mensaje de validación y, por lo tanto, la directiva como atributo se agrega a cada control de entrada.
También tengo (opcional) .has-focus y has-visited clase css en mi archivo css, que ves que se hace referencia en la directiva.
NOTA: recuerde agregar ''on-blur-val'' exactamente de esta manera a su control de entrada sin los apóstrofes