Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set focus on first invalid input in AngularJs form

I've read several articles and StackOverflow questions relating to the setting of focus in AngularJs.

Unfortunately all the examples that I have read assume that there is some attribute that I can add to the element to gain focus, e.g. a focusMe directive.

However what if I don't know in advance which input to set focus to? In particular how do I set focus to the first input element in a form that has $invalid set - i.e. an element that fails validation. There could be several inputs that fail validation, so I cannot use a directive that just tries to call .focus() based on this. (I am doing this for Accessibility/WCAG reasons, its good practice to do so on submit being clicked to minimize keypresses to find the first field that has failed validation).

The $error object will give all controls that fail validation, but they are grouped by the type of failure not in any order of appearance on the form.

I'm sure I can come up with some kludged way of doing this. A directive on the form, which receives some broadcast when focus needs to be set - that directive can then search for the first $invalid element. However this seems very complex and I'd like to know whether these is a better more 'angular' way of doing this.

like image 699
iandotkelly Avatar asked Dec 04 '13 01:12

iandotkelly


People also ask

How to set focus on input field in AngularJS?

' Everytime <input> becomes visible (e.g. by clicking some button), set focus on it. app. directive('focusMe', function($timeout) { return { scope: { trigger: '@focusMe' }, link: function(scope, element) { scope. $watch('trigger', function(value) { if(value === "true") { $timeout(function() { element[0].

What is Ng focus in AngularJS?

The ng-focus directive tells AngularJS what to do when an HTML element gets focus. The ng-focus directive from AngularJS will not override the element's original onfocus event, both will be executed.

How do you focus a form control?

Focusing input with Renderer2 Although, I have a reactive form below for demonstration, all you need is an input with a unique id. Inject Renderer 2 in the constructor and access the input element with selectRootElement() method. In addition, you can focus on input element on load, using the ngAfterViewInit() hook.

What is Ng invalid in angular?

ng-pristine The field has not been modified yet. ng-dirty The field has been modified. ng-valid The field content is valid. ng-invalid The field content is not valid.


1 Answers

Ok, so the answer was simpler than I thought.

All I needed was a directive to put on the form itself, with an event handler looking for the submit event. This can then traverse the DOM looking for the first element that has the .ng-invalid class on it.

Example using jQLite:

myApp.directive('accessibleForm', function () {     return {         restrict: 'A',         link: function (scope, elem) {              // set up event handler on the form element             elem.on('submit', function () {                  // find the first invalid element                 var firstInvalid = elem[0].querySelector('.ng-invalid');                  // if we find one, set focus                 if (firstInvalid) {                     firstInvalid.focus();                 }             });         }     }; }); 

The example here uses an Attribute directive, you could expand the example to have this be an element directive (restrict: 'E') and include a template that converts this to a . This is however a personal preference.

like image 158
iandotkelly Avatar answered Sep 18 '22 09:09

iandotkelly