Search code examples
angularjsangular-schema-form

Focus on the first field that is .ng-invalid at Submit - not working for radios-inline


I am using the directive from accepted answer on Set focus on first invalid input in AngularJs form to accomplish this:

app.directive('accessibleForm', function () {
    return {
        restrict: 'A',
        link: function (scope, elem) {

            // set up event handler on the form element
            elem.on('submit', function () {

                console.log("inside focus directive");
                // find the first invalid element
                var firstInvalid = elem[0].querySelector('.ng-invalid');
                //if we find one, set focus
                if (firstInvalid) {
                    firstInvalid.focus();
                }
            });
        }
    };
});

As long as I do not use radios-inline the focus works. Please refer: http://jsfiddle.net/mutharasus/mu7y4k8f/

But if the first error happens to be on a radios-inline field the focus does not work. Please refer: http://jsfiddle.net/mutharasus/00jzbL6g/

I am not sure how to fix. Please help.


Solution

  • The radio-inline is adding the ng-invalid class to the field label instead of to each individual radio input.

    You could change that directive and implement your desired behaviour in your custom one (you would need to add ng-invalid to each radio input) or change the accessibleForm directive to check if the invalid element is a label and, in that case, find the the first radio input associated to it:

    app.directive('accessibleForm', function () {
        return {
            restrict: 'A',
            link: function (scope, elem) {
    
                // set up event handler on the form element
                elem.on('submit', function () {
    
                    console.log("inside focus directive");
    
                    // find the first invalid element
                    var firstInvalid = elem[0].querySelector('.ng-invalid');
    
                    // If we got a label, then it is a radio-inline
                    if(firstInvalid && firstInvalid.tagName === 'LABEL') {
                        firstInvalid =  elem[0].querySelector('.ng-invalid + div input[type=radio]')
                    }
    
                    firstInvalid && firstInvalid.focus();
    
                });
            }
        };
    });
    

    Although it may seem like the easiest solution, it does not look right for me to have that second query selector that depends so much on the structure of that specific directive, as if that changes then the accessibleForm directive will be broken again.