Convalida i campi dopo che l’utente ha lasciato un campo

Con AngularJS, posso usare ng-pristine o ng-dirty per rilevare se l’utente è entrato nel campo. Tuttavia, desidero eseguire la convalida sul lato client solo dopo che l’utente ha lasciato l’area del campo. Questo perché quando un utente entra in un campo come e-mail o telefono, viene sempre generato un errore fino a quando non ha completato la digitazione completa della sua e-mail, e questa non è un’esperienza utente ottimale.

Esempio


AGGIORNARE:

Angular ora viene fornito con un evento di sfocatura personalizzato: https://docs.angularjs.org/api/ng/directive/ngBlur

Angular 1.3 ora ha ng-model-options e puoi impostare l’opzione su { 'updateOn': 'blur'} per esempio, e puoi anche rimbalzare, quando l’uso sta scrivendo troppo velocemente o vuoi salvare un alcune costose operazioni DOM (come un modello che scrive su più domini DOM e non si vuole che un ciclo $ digest avvenga su ogni tasto premuto)

https://docs.angularjs.org/guide/forms#custom-triggers e https://docs.angularjs.org/guide/forms#non-immediate-debounced-model-updates

Per impostazione predefinita, qualsiasi modifica al contenuto attiverà un aggiornamento del modello e la convalida del modulo. È ansible sovrascrivere questo comportamento utilizzando la direttiva ngModelOptions per eseguire il binding solo all’elenco di eventi specificato. Ie ng-model-options = “{updateOn: ‘blur’}” verrà aggiornato e convalidato solo dopo che il controllo ha perso lo stato attivo. È ansible impostare diversi eventi utilizzando un elenco delimitato da spazi. Ie ng-model-options = “{updateOn: ‘mousedown blur’}”

E rimbalzare

È ansible ritardare l’aggiornamento / la convalida del modello utilizzando la chiave di rimbalzo con la direttiva ngModelOptions. Questo ritardo si applicherà anche a parser, validatori e flag di modello come $ dirty o $ pristine.

Ie ng-model-options = “{debounce: 500}” attenderà mezzo secondo dall’ultima modifica del contenuto prima di triggersre l’aggiornamento del modello e la convalida del modulo.

Dalla versione 1.3.0 questo può essere fatto facilmente con $touched , il che è vero dopo che l’utente ha lasciato il campo.

 

Error

https://docs.angularjs.org/api/ng/type/ngModel.NgModelController

Ho risolto questo problema espandendo ciò che @jlmcdonald ha suggerito. Ho creato una direttiva che sarebbe stata automaticamente applicata a tutti gli input e selezionare gli elementi:

 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); 

Questo aggiungerà le classi has-focus e has-visited a vari elementi mentre l’utente focalizza / visita gli elementi. È quindi ansible aggiungere queste classi alle regole CSS per mostrare errori di convalida:

 input.has-visited.ng-invalid:not(.has-focus) { background-color: #ffeeee; } 

Ciò funziona bene in quanto gli elementi ottengono comunque proprietà $ non valide ecc., Ma il CSS può essere usato per dare all’utente un’esperienza migliore.

Sono riuscito a farlo con un bit piuttosto semplice di CSS. Ciò richiede che i messaggi di errore siano fratelli dell’ingresso a cui si riferiscono e che abbiano una class di error .

 :focus ~ .error { display:none; } 

Dopo aver soddisfatto questi due requisiti, questo nasconderà qualsiasi messaggio di errore relativo ad un campo di input focalizzato, qualcosa che penso che angularjs dovrebbe fare comunque. Sembra una svista.

Questo sembra essere implementato come standard nelle versioni più recenti di angular.

Le classi ng-untouched e ng-touched sono impostate rispettivamente prima e dopo che l’utente ha messo a fuoco un elemento convalidato.

CSS

 input.ng-touched.ng-invalid { border-color: red; } 

Per quanto riguarda la soluzione di @ lambinator … Stavo ricevendo il seguente errore in angular.js 1.2.4:

Errore: [$ rootScope: inprog] $ digest già in corso

Non sono sicuro se ho fatto qualcosa di sbagliato o se questo è un cambiamento in Angular, ma la rimozione scope.$apply istruzioni ha risolto il problema e le classi / stati sono ancora aggiornati.

Se vedi anche questo errore, prova quanto segue:

 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); 

Potrebbe funzionare per te scrivere una direttiva personalizzata che avvolge il metodo sfocatura () javascript (ed esegue una funzione di convalida quando triggersta); c’è un problema Angular che ha un esempio (oltre a una direttiva generica che può associare ad altri eventi non supportati nativamente da Angular):

https://github.com/angular/angular.js/issues/1277

Se non vuoi seguire quella rotta, l’altra opzione sarebbe quella di impostare $ watch sul campo, triggersndo nuovamente la convalida quando il campo è compilato.

Per raccogliere ulteriormente le risposte fornite, è ansible semplificare la codifica dell’input utilizzando pseudo-classi CSS3 e contrassegnando solo i campi visitati con una class per ritardare la visualizzazione degli errori di convalida fino a quando l’utente non ha perso l’attenzione sul campo:

(L’esempio richiede 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

 

basato su @nicolas answer .. Pure CSS dovrebbe il trucco, mostrerà solo il messaggio di errore su sfocatura

  

This is not a valid email.

CSS

 .ng-invalid:focus ~ .bg-danger { display:none; } 

Ecco un esempio che utilizza ng-messages (disponibile in angular 1.3) e una direttiva personalizzata.

Il messaggio di convalida viene visualizzato su sfocatura per la prima volta che l’utente lascia il campo di immissione, ma quando corregge il valore, il messaggio di convalida viene rimosso immediatamente (non più sfocato).

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

 
name is required name is too short name is too long

PS. Non dimenticare di scaricare e includere ngMessage nel tuo modulo:

 var myApp = angular.module('myApp', ['ngMessages']); 

ng-model-options in AngularJS 1.3 (beta al momento della stesura di questo documento) è documentato per supportare {updateOn: ‘blur’}. Per le versioni precedenti, qualcosa come il seguente ha funzionato per me:

 myApp.directive('myForm', function() { return { require: 'form', link: function(scope, element, attrs, formController) { scope.validate = function(name) { formController[name].isInvalid = formController[name].$invalid; }; } }; }); 

Con un modello come questo:

 
Please enter a valid e-mail address.

Usa stato campo $ toccato Il campo è stato toccato per questo come mostrato nell’esempio seguente.

 
You must enter a value

È ansible impostare dynamicmente la class css has error (presupponendo che si stia utilizzando bootstrap) utilizzando ng-class e una proprietà nell’ambito del controller associato:

plunkr: http://plnkr.co/edit/HYDlaTNThZE02VqXrUCH?p=info

HTML:

 

controller:

 $scope.badEmailAddress = false; $scope.emailBlurred = function (isValid) { $scope.badEmailAddress = !isValid; }; 

Se utilizzi bootstrap 3 e lesscss puoi abilitare la convalida della sfocatura con il seguente frammento di codice:

 :focus ~ .form-control-feedback.glyphicon-ok { display:none; } :focus ~ .form-control-feedback.glyphicon-remove { display:none; } .has-feedback > :focus { & { .form-control-focus(); } } 

out Ho usato una direttiva. Ecco il codice:

 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'); }); } } }) 

Tutto il mio controllo di input ha un elemento span come elemento successivo, che è dove viene visualizzato il mio messaggio di convalida e quindi la direttiva come attributo viene aggiunta a ciascun controllo di input.

Ho anche (facoltativo) .has-focus e ha visitato la class css nel mio file css che vedi essere referenziato nella direttiva.

NOTA: ricordarsi di aggiungere “on-blur-val” esattamente in questo modo al controllo di input senza gli apostrofi

Usando ng-focus puoi raggiungere il tuo objective. è necessario fornire ng-focus nel campo di input. E mentre scrivi i tuoi derivati ​​di ng-show devi scrivere anche una logica non uguale. Mi piace il seguente codice:

Possiamo usare le funzioni onfocus e onblur. Sarebbe semplice e migliore.

  
Name:
E-mail:

Prova qui:

http://plnkr.co/edit/NKCmyru3knQiShFZ96tp?p=preview