Rectangle 27 1

The main thing seems to be that the promise should either resolve for a valid value or reject for an invalid one.

// don't forget to inject the $q service
c.$asyncValidators.ensureUniqueValidator = function(modelValue, viewValue) {
    if (ctrl.$isEmpty(modelValue)) {
        // consider empty model valid
        return $q.when();
    }

    var params = {
        method: 'is' + attrs.name + 'unique'
    };
    params[attrs.name] = modelValue;

    return $http.get('MainServlet.do', {
        params: params
    }).then(function(response) {
        if (!response.data) {
            return $q.reject();
        }
        return true;
    });
};

Hi Phil, this code worked, I am accepting the answer. Thanks!... I was initially trying the server validation on the "Blur" event. I mean, the form should stay invalid until the value is returned as unique == true from the server. It will avoid continuous calls to server while user is typing in the field (currently happening). Could you please help me to achieve the same? Thanks!

@JVM Still working on decent server-side validation on submit myself. I'm not a fan of the continuous validation style that Angular promotes. There's some ideas in this post ~ stackoverflow.com/questions/12864887/

I used "debounce" for the fields I need to check with server and it helped. It is letting me finish the typing and then makes a server call, working similar to blur event. ng-model-options="{ debounce: 500 }"

Angularjs $setValidity is not blocking Form Submission when set to fal...

angularjs angularjs-directive directive custom-validators angularjs-ng-form
Rectangle 27 1

My understanding is that because the function is being watched, it's actually being evaluated by Angular periodically during each digest. A simple solution might be to set the validity of textOrLocation to true when that particular form is not in focus. This would allow the button state to depend on the validity of the field in the id form.

function textOrLocationValid() {
    var usingTextOrLocation = $scope.search.mode == 'textOrLocation';
    if (usingTextOrLocation) {
        var textModel = $scope.form.searchText || {},
            textValid = textModel.$valid,
            textValue = textModel.$modelValue,
            latModel = $scope.form.searchLat || {},
            latValid = latModel.$valid,
            latValue = latModel.$modelValue,
            lngModel = $scope.form.searchLng || {},
            lngValid = lngModel.$valid,
            lngValue = lngModel.$modelValue,
            formValid = (textValid && latValid && lngValid) && // No invalid fields
            ((latValue && 1 || 0) + (lngValue && 1 || 0) != 1) && // Either both lat and long have values, or neither do
            (textValue || latValue); // Either text or location are filled out
        if (formValid) {
            // Explicitly set form validity to true
            $scope.form.$setValidity('textOrLocation', true);
        } else {
            // Explicitly set form validity to false
            $scope.form.$setValidity('textOrLocation', false);
        }
    }
    else{
        // Explicitly set form validity to true because form is not active
        $scope.form.$setValidity('textOrLocation', true);
    }
}

Thanks! This is exactly what I was missing. I didn't understand the purpose of the 'validationErrorKey' (the first argument taken by $setValidity. I thought that using form.$setValidity() with true as the second argument would force the form's $valid state to true. That wasn't correct. Instead, it set the value assigned to the 'textOrLocation' error key to true, allowing all my other validation directives to function normally.

javascript - After using $setValidity at the form level, validity is s...

javascript angularjs forms validation
Rectangle 27 1

To create complex tests, you can use a small directive use-form-error, which may also be useful to you in the future.

With this directive, you can write:

<div ng-form="myForm">
  <div>
    <input type="text" ng-model="searchText" name="searchText">
    <input type="number" ng-model="searchLat" name="searchLat" min="-90" max="90" step="0.000001">
    <input type="number" ng-model="searchLng" name="searchLng" min="-180" max="180" step="0.000001">
    <span use-form-error="textOrLocation" use-error-expression="textOrLocationValid()" use-error-input="myForm"></span>
  </div>
  {{myForm.$error}}
  <br>
  <button ng-disabled="myForm.$invalid">Submit</button>
</div>
angular.module('ExampleApp', ['use']).controller('ExampleController', function($scope) {
$scope.search = {
  mode: 'textOrLocation'
};
$scope.textOrLocationValid = function() {
  var usingTextOrLocation = $scope.search.mode == 'textOrLocation';
  if (usingTextOrLocation) {
    var textModel = $scope.myForm.searchText || {},
      textValid = textModel.$valid,
      textValue = textModel.$modelValue,
      latModel = $scope.myForm.searchLat || {},
      latValid = latModel.$valid,
      latValue = latModel.$modelValue,
      lngModel = $scope.myForm.searchLng || {},
      lngValid = lngModel.$valid,
      lngValue = lngModel.$modelValue,
      formValid = (textValid && latValid && lngValid) && // No invalid fields
      ((latValue && 1 || 0) + (lngValue && 1 || 0) != 1) && // Either both lat and long have values, or neither do
      (textValue || latValue); // Either text or location are filled out
    return !formValid;
  } else {
    // Explicitly set form validity to true because form is not active
    return false;
  }
}

javascript - After using $setValidity at the form level, validity is s...

javascript angularjs forms validation
Rectangle 27 1

Nothing in your code modifies the conflict validation key, except for when $setValidity('conflict', false) is explicitly called. Since that is the only code setting the state of the conflict validation key and there is nothing else resetting it to true, it's expected behaviour that editing the textbox wouldn't reset its conflict validation state.

To get the behaviour that you want, you need to code for it. One way is to use ng-change.

<input name="email" type="email" ng-model="..." required ng-change="resetConflictState()">

$scope.resetConflictState = function() {
    $scope.form.email.$setValidity('conflict', true);
}

javascript - Serverside validation of AngularJS forms, use $setValidit...

javascript angularjs forms validation
Rectangle 27 5

//This directive is to update Form validity when any of the elements decorated
// with customRequired is not empty.
app.directive("customRequiredContainer",function(){
  return {
    restrict:"A",
    require:"form",
    controller:function($element,$scope){
      var properties = []; //store the list of properties to check. 

      //customRequired will register the property to be checked.
      this.registerProperty = function(property){
       if (properties.indexOf(property) === -1){
           properties.push(property);

          $scope.$watch(property,function(value){
            if ($element.form){

              //If any of the elements is checked, Form is valid otherwise not valid.
              for (var i=0;i<properties.length;i++){
                if ($scope[properties[i]]){
                  //we should use $setValidity(), 
                  //I don't know why it does not work, check that later.
                  $element.form.$invalid = false;
                  $element.form.$valid = true;
                  return;
                }
              }

              $element.form.$invalid = true;
              $element.form.$valid = false;
            }
          });
        }
      };
    },
    link:function(scope,element,attrs,formController){
      element.form = formController;
    }
  }
});

//This directive is to decorate which element should be checked for validity
app.directive("customRequired",function(){
  return {
    restrict:"A",
    require:"^customRequiredContainer",
    link:function(scope,element,attrs,containerController){
      containerController.registerProperty(attrs.ngModel);
    }
  }
});
<form name="myFrm" custom-required-container>
    <ul>
      <li>
        <input type="checkbox" ng-model="sunday" custom-required/>Sunday</li>
      <li>
        <input type="checkbox" ng-model="monday" custom-required/>Monday</li>
      <li>
        <input type="checkbox" ng-model="tuesday" custom-required/>Tuesday</li>
      <li>
        <input type="checkbox" ng-model="wednesday" custom-required/>Wednesday</li>
      <li>
        <input type="checkbox"  ng-model="thursday"  custom-required/>Thursday</li>
      <li>
        <input type="checkbox"  ng-model="friday" custom-required />Friday</li>
      <li>
        <input type="checkbox"  ng-model="saturday" custom-required />Saturday</li>
    </ul>

    <p ng-if="myFrm.$invalid">Atleast one day should be selected</p>
  </form>

By giving the inputs names: name="sunday", angular will add the input name as a property of the form: myFrm.sunday. From then, we can check whether the input is selected using its $error.required property.

<form name="myFrm">
    <ul>
      <li>
        <input type="checkbox" ng-model="sunday" />Sunday</li>
      <li>
        <input type="checkbox" ng-model="monday" />Monday</li>
      <li>
        <input type="checkbox" ng-model="tuesday" />Tuesday</li>
      <li>
        <input type="checkbox" ng-model="wednesday" />Wednesday</li>
      <li>
        <input type="checkbox"  ng-model="thursday"  />Thursday</li>
      <li>
        <input type="checkbox"  ng-model="friday"  />Friday</li>
      <li>
        <input type="checkbox"  ng-model="saturday"  />Saturday</li>
    </ul>

    <p ng-if="!sunday&&!monday&&!tuesday&&!wednesday&&
    !thursday&&!friday&&!saturday">Atleast one day should be selected</p>
  </form>

@Khanh TO thanx for the solution, it worked but there is only 1 problem, when 1 checkbox is selected error message goes but other checkbox still has the RED border around it, how to remove that RED border?

@KhanhTO there is no CSS for that... and also you have kept each checkbox as required, because of that my submit button gets disabled because i am checking on submit button like '<a ng-disabled="myFrm.$invalid" title="save">save</a>'

@Jay: See my update for a quick solution if you only need to show/hide error message.

angularjs - One checkbox should be selected from multiple checkboxs wi...

angularjs
Rectangle 27 5

//This directive is to update Form validity when any of the elements decorated
// with customRequired is not empty.
app.directive("customRequiredContainer",function(){
  return {
    restrict:"A",
    require:"form",
    controller:function($element,$scope){
      var properties = []; //store the list of properties to check. 

      //customRequired will register the property to be checked.
      this.registerProperty = function(property){
       if (properties.indexOf(property) === -1){
           properties.push(property);

          $scope.$watch(property,function(value){
            if ($element.form){

              //If any of the elements is checked, Form is valid otherwise not valid.
              for (var i=0;i<properties.length;i++){
                if ($scope[properties[i]]){
                  //we should use $setValidity(), 
                  //I don't know why it does not work, check that later.
                  $element.form.$invalid = false;
                  $element.form.$valid = true;
                  return;
                }
              }

              $element.form.$invalid = true;
              $element.form.$valid = false;
            }
          });
        }
      };
    },
    link:function(scope,element,attrs,formController){
      element.form = formController;
    }
  }
});

//This directive is to decorate which element should be checked for validity
app.directive("customRequired",function(){
  return {
    restrict:"A",
    require:"^customRequiredContainer",
    link:function(scope,element,attrs,containerController){
      containerController.registerProperty(attrs.ngModel);
    }
  }
});
<form name="myFrm" custom-required-container>
    <ul>
      <li>
        <input type="checkbox" ng-model="sunday" custom-required/>Sunday</li>
      <li>
        <input type="checkbox" ng-model="monday" custom-required/>Monday</li>
      <li>
        <input type="checkbox" ng-model="tuesday" custom-required/>Tuesday</li>
      <li>
        <input type="checkbox" ng-model="wednesday" custom-required/>Wednesday</li>
      <li>
        <input type="checkbox"  ng-model="thursday"  custom-required/>Thursday</li>
      <li>
        <input type="checkbox"  ng-model="friday" custom-required />Friday</li>
      <li>
        <input type="checkbox"  ng-model="saturday" custom-required />Saturday</li>
    </ul>

    <p ng-if="myFrm.$invalid">Atleast one day should be selected</p>
  </form>

By giving the inputs names: name="sunday", angular will add the input name as a property of the form: myFrm.sunday. From then, we can check whether the input is selected using its $error.required property.

<form name="myFrm">
    <ul>
      <li>
        <input type="checkbox" ng-model="sunday" />Sunday</li>
      <li>
        <input type="checkbox" ng-model="monday" />Monday</li>
      <li>
        <input type="checkbox" ng-model="tuesday" />Tuesday</li>
      <li>
        <input type="checkbox" ng-model="wednesday" />Wednesday</li>
      <li>
        <input type="checkbox"  ng-model="thursday"  />Thursday</li>
      <li>
        <input type="checkbox"  ng-model="friday"  />Friday</li>
      <li>
        <input type="checkbox"  ng-model="saturday"  />Saturday</li>
    </ul>

    <p ng-if="!sunday&&!monday&&!tuesday&&!wednesday&&
    !thursday&&!friday&&!saturday">Atleast one day should be selected</p>
  </form>

@Khanh TO thanx for the solution, it worked but there is only 1 problem, when 1 checkbox is selected error message goes but other checkbox still has the RED border around it, how to remove that RED border?

@KhanhTO there is no CSS for that... and also you have kept each checkbox as required, because of that my submit button gets disabled because i am checking on submit button like '<a ng-disabled="myFrm.$invalid" title="save">save</a>'

@Jay: See my update for a quick solution if you only need to show/hide error message.

angularjs - One checkbox should be selected from multiple checkboxs wi...

angularjs
Rectangle 27 7

.directive('disableChildren', function() {
  return {
    require: '^form',
    restrict: 'A',
    link: function(scope, element, attrs,form) {
      var control;

      scope.$watch(function() {
        return scope.$eval(attrs.disableChildren);
      }, function(value) {
        if (!control) {
          control = form[element.find("input").attr("name")];
        }
        if (value === false) {
          form.$addControl(control);
          angular.forEach(control.$error, function(validity, validationToken) {
            form.$setValidity(validationToken, !validity, control);
          });
        } else {
          form.$removeControl(control);
        }
      });
    }
  }
})

For more information and explanation of how it works. Check out my similar directive for excluding hidden elements from validation:

I think we could somehow combine these directives to create a general directive that could be used everywhere depending on how we evaluate an expression.

Yeah, the $addControl and $removeControl possibly could do the trick. I'll try to sketch up a plunk that would disable validation for all children. The problem here is that there might by a ng-form somewhere between the disable-children and the inputs to disable, as well as not picking up select elements.

@RJo: yes, that's just a demo for your case and just to give the idea of $addControl and $removeControl. You could extend it. Happy coding.

Sign up for our newsletter and get our top new questions delivered to your inbox (see an example).

forms - Validation of invisible and disabled fields in AngularJS - Sta...

forms angularjs validation
Rectangle 27 41

As I wrote in the comments, I just figured it out. I just need to use different validity flags. Nothing says that I have to use the same key in $setValidity() as the name of the directive!

<span ng-show="name.$error.nameinvalid">This is not a valid username, it must be alphanmueric</span>
<span ng-show="name.$error.nametaken">Sorry, the username {{ name }} is already taken</span>

And in the directive

// if I got a 409
ngModel.$setValidity("nametaken",false);
// if I got a 400
ngModel.$setValidity("nameinvalid",false);

The name of the $error is the error message!

You could also just bind a model within your directive, and add your error message here (if you have many different error messages that come from the server)

Can you please provide example of this?

AngularJS custom form validation error message - Stack Overflow

angularjs angularjs-directive
Rectangle 27 1

var app = angular.module('login-form', []);
var INTEGER_REGEXP = new RegExp('^[a-z0-9]+(\.[_a-z0-9]+)*@@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,50})$', 'i');
app.directive('cemail', function () {
    return {
        require: 'ngModel',
        link: function (scope, elm, attrs, ctrl) {
            ctrl.$parsers.unshift(function (viewValue) {
                if (INTEGER_REGEXP.test(viewValue)) {
                    // it is valid
                    ctrl.$setValidity('cemail', true);
                    return viewValue;
                } else {
                    // it is invalid, return undefined (no model update)
                    ctrl.$setValidity('cemail', false);
                    return undefined;
                }
            });
        }
    };
});

and in html

<label>Email</label>
<input id="UserName" name="UserName" type="text" value="" data-ng-model="email" required="" cemail>
<span data-ng-show="form.UserName.$dirty && form.UserName.$invalid">
    <span data-ng-show="form.UserName.$error.required">Required</span>
    <span data-ng-show="form.UserName.$error.cemail">Invalid Email</span>
</span>

Form Validation - Email Validation not working as expected in AngularJ...

angularjs
Rectangle 27 2

function updateValidity() {
            if (group.isRequired) {
                modelCtrl.$setValidity('required', false);
                modelCtrl.$setValidity('parse', false); 
            } else {
                modelCtrl.$setValidity('required', true);
                modelCtrl.$setValidity('parse', true);
            }
        }

angularjs - Form validation - Required one of many in a group - Stack ...

angularjs
Rectangle 27 479

Angular supports this out of the box. Have you tried ngSubmit on your form element?

<form ng-submit="myFunc()" ng-controller="mycontroller">
   <input type="text" ng-model="name" />
    <br />
    <input type="text" ng-model="email" />
</form>
<input type="submit" style="position: absolute; left: -9999px; width: 1px; height: 1px;"/>

If you don't like the hidden submit button solution, you'll need to bind a controller function to the Enter keypress or keyup event. This normally requires a custom directive, but the AngularUI library has a nice keypress solution set up already. See http://angular-ui.github.com/

After adding the angularUI lib, your code would be something like:

<form ui-keypress="{13:'myFunc($event)'}">
  ... input fields ...
</form>

or you can bind the enter keypress to each individual field.

Also, see this SO questions for creating a simple keypres directive: How can I detect onKeyUp in AngularJS?

EDIT (2014-08-28): At the time this answer was written, ng-keypress/ng-keyup/ng-keydown did not exist as native directives in AngularJS. In the comments below @darlan-alves has a pretty good solution with:

<input ng-keyup="$event.keyCode == 13 && myFunc()"... />

It only works if I have a submit button inside the form, too.

Just leaving a note: If you've ended up here and submit buttons don't work for you, you could be using a bad name for your submit function. I was foolishly using ng-submit="join()" for a registration controller that had $scope.join = function() {...} and changing that function name to foo() got enter-button submission working again.

At the time this answer was written, ng-keypress/ng-keyup did not exist in Angular

ng-keyup="$event.keyCode == 13 && myFunc()"

function - Submit form on pressing Enter with AngularJS - Stack Overfl...

function angularjs call keypress enter
Rectangle 27 270

angular.module('yourModuleName').directive('ngEnter', function() {
        return function(scope, element, attrs) {
            element.bind("keydown keypress", function(event) {
                if(event.which === 13) {
                    scope.$apply(function(){
                        scope.$eval(attrs.ngEnter, {'event': event});
                    });

                    event.preventDefault();
                }
            });
        };
    });
<div ng-app="" ng-controller="MainCtrl">
    <input type="text" ng-enter="doSomething()">    
</div>

Is there a clever way to get this to trigger any time they hit enter while on your page?

@EpokK I wanna disable the enter key for the entire form, how can I do that? (I want to avoid form submission with enter)

very nice, but as per AngularJs' reccomendation, you shouldn't create directives, services, or filters that are prefixed with ng-, in case an official release later uses the same name.

Great solution. I just changed the name to keyBind and this line "if(event.which === 13) {" to this "if(event.which === Number(attrs.key)) {" And then my input to "<input type="text" bind-key="doSomething()" key="13">" so that I could re-use it for different key events.

IMPORTANT: Adding both the keydown and keypress events without a comma to delimit them means both may fire simultaneously. This is likely to spawn $rootScope:inprog errors. Adding a comma between them creates a disjunctive, and ensures only only $digest cycle occurs. Couldn't apply the edit since it's only a single character.

function - Submit form on pressing Enter with AngularJS - Stack Overfl...

function angularjs call keypress enter
Rectangle 27 172

If you only have one input you can use the form tag.

<form ng-submit="myFunc()" ...>

If you have more than one input, or don't want to use the form tag, or want to attach the enter-key functionality to a specific field, you can inline it to a specific input as follows:

<input ng-keyup="$event.keyCode == 13 && myFunc()" ...>

This is a clever way of doing this without even having to write your own directive

Works great, I used the ng-keyup directive, but I have one big issue with it, if I only have one text field, he submits the complete form (postback) but I don't want that. I tried already ng-keyup="$event.keyCode == 13 && onTextBoxKeyUp($event)" and in the function "event.preventDefault();", but did not help ;(

this is shorter but keeping DRY approach in my mind i would still create directive and use it with directive.

function - Submit form on pressing Enter with AngularJS - Stack Overfl...

function angularjs call keypress enter
Rectangle 27 55

A very-very simple solution is to give the form a name so you can refer to it and then tweak the ng-click to fire only if the form is valid:

<form name="myform">
    <input type="text" ng-model='name' ng-required="true" />
    <button ng-click="myform.$valid && preview()">Preview</button>
    <button ng-click="myform.$valid && update()">Update</button>
</form>

I like separating validation (a business concern) from the view, to that end I created egkyron that lets you define the model constraints in code and use programmatic validation along with standard Angular form validation.

That is one option. But since there can be many input and select fields in the form, I wanted to let user know what he is missing on button click instead of him figuring out what he is missing and why button is disabled.

Display a marker on the invalid fields then? Angular is giving the tools to do it - starting with the ng-invalid CSS class.

Above code doesn't ignore ng-disabled fields. How can i make it ignore ng-disabled fields (even if it has ng-required).

ng-disabled
ng-required
<input ... ng-disabled="foo.condition" ng-required="!foo.condition" />

Looks like pain in the back. Thanks for helping :)

Form validation on ng-click angularjs - Stack Overflow

angularjs
Rectangle 27 479

Angular supports this out of the box. Have you tried ngSubmit on your form element?

<form ng-submit="myFunc()" ng-controller="mycontroller">
   <input type="text" ng-model="name" />
    <br />
    <input type="text" ng-model="email" />
</form>
<input type="submit" style="position: absolute; left: -9999px; width: 1px; height: 1px;"/>

If you don't like the hidden submit button solution, you'll need to bind a controller function to the Enter keypress or keyup event. This normally requires a custom directive, but the AngularUI library has a nice keypress solution set up already. See http://angular-ui.github.com/

After adding the angularUI lib, your code would be something like:

<form ui-keypress="{13:'myFunc($event)'}">
  ... input fields ...
</form>

or you can bind the enter keypress to each individual field.

Also, see this SO questions for creating a simple keypres directive: How can I detect onKeyUp in AngularJS?

EDIT (2014-08-28): At the time this answer was written, ng-keypress/ng-keyup/ng-keydown did not exist as native directives in AngularJS. In the comments below @darlan-alves has a pretty good solution with:

<input ng-keyup="$event.keyCode == 13 && myFunc()"... />

It only works if I have a submit button inside the form, too.

Just leaving a note: If you've ended up here and submit buttons don't work for you, you could be using a bad name for your submit function. I was foolishly using ng-submit="join()" for a registration controller that had $scope.join = function() {...} and changing that function name to foo() got enter-button submission working again.

At the time this answer was written, ng-keypress/ng-keyup did not exist in Angular

ng-keyup="$event.keyCode == 13 && myFunc()"

function - Submit form on pressing Enter with AngularJS - Stack Overfl...

function angularjs call keypress enter
Rectangle 27 270

angular.module('yourModuleName').directive('ngEnter', function() {
        return function(scope, element, attrs) {
            element.bind("keydown keypress", function(event) {
                if(event.which === 13) {
                    scope.$apply(function(){
                        scope.$eval(attrs.ngEnter, {'event': event});
                    });

                    event.preventDefault();
                }
            });
        };
    });
<div ng-app="" ng-controller="MainCtrl">
    <input type="text" ng-enter="doSomething()">    
</div>

Is there a clever way to get this to trigger any time they hit enter while on your page?

@EpokK I wanna disable the enter key for the entire form, how can I do that? (I want to avoid form submission with enter)

very nice, but as per AngularJs' reccomendation, you shouldn't create directives, services, or filters that are prefixed with ng-, in case an official release later uses the same name.

Great solution. I just changed the name to keyBind and this line "if(event.which === 13) {" to this "if(event.which === Number(attrs.key)) {" And then my input to "<input type="text" bind-key="doSomething()" key="13">" so that I could re-use it for different key events.

IMPORTANT: Adding both the keydown and keypress events without a comma to delimit them means both may fire simultaneously. This is likely to spawn $rootScope:inprog errors. Adding a comma between them creates a disjunctive, and ensures only only $digest cycle occurs. Couldn't apply the edit since it's only a single character.

function - Submit form on pressing Enter with AngularJS - Stack Overfl...

function angularjs call keypress enter
Rectangle 27 28

I wanted something a little more extensible/semantic than the given answers so I wrote a directive that takes a javascript object in a similar way to the built-in ngClass:

<input key-bind="{ enter: 'go()', esc: 'clear()' }" type="text"></input>

The values of the object are evaluated in the context of the directive's scope - ensure they are encased in single quotes otherwise all of the functions will be executed when the directive is loaded(!)

esc : 'clear()'
esc : clear()
myModule
    .constant('keyCodes', {
        esc: 27,
        space: 32,
        enter: 13,
        tab: 9,
        backspace: 8,
        shift: 16,
        ctrl: 17,
        alt: 18,
        capslock: 20,
        numlock: 144
    })
    .directive('keyBind', ['keyCodes', function (keyCodes) {
        function map(obj) {
            var mapped = {};
            for (var key in obj) {
                var action = obj[key];
                if (keyCodes.hasOwnProperty(key)) {
                    mapped[keyCodes[key]] = action;
                }
            }
            return mapped;
        }

        return function (scope, element, attrs) {
            var bindings = map(scope.$eval(attrs.keyBind));
            element.bind("keydown keypress", function (event) {
                if (bindings.hasOwnProperty(event.which)) {
                    scope.$apply(function() {
                         scope.$eval(bindings[event.which]);
                    });
                }
            });
        };
    }]);

function - Submit form on pressing Enter with AngularJS - Stack Overfl...

function angularjs call keypress enter
Rectangle 27 172

If you only have one input you can use the form tag.

<form ng-submit="myFunc()" ...>

If you have more than one input, or don't want to use the form tag, or want to attach the enter-key functionality to a specific field, you can inline it to a specific input as follows:

<input ng-keyup="$event.keyCode == 13 && myFunc()" ...>

This is a clever way of doing this without even having to write your own directive

Works great, I used the ng-keyup directive, but I have one big issue with it, if I only have one text field, he submits the complete form (postback) but I don't want that. I tried already ng-keyup="$event.keyCode == 13 && onTextBoxKeyUp($event)" and in the function "event.preventDefault();", but did not help ;(

this is shorter but keeping DRY approach in my mind i would still create directive and use it with directive.

function - Submit form on pressing Enter with AngularJS - Stack Overfl...

function angularjs call keypress enter
Rectangle 27 76

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.

elem is already a angular.element(), so if you're using jQuery at least you can just do elem.find('.ng-invalid:first').focus(). Not sure if jqLite supports the :first selector as well.

This could be made better by focusing only on visible elements like so: var firstInvalid = element.find('.ng-invalid:visible').first(); There are a few edge cases when this could make sense.

@pcatre - I also see you made an edit which was rejected suggesting a change to an 'A' attribute directive. Of course an A directive or even a C directive would also work - but why didn't the E directive work for you? It seems to work just fine for me.

@iandotkelly with an attribute directive we can do something like this: <form accessible-form></form> With an element directive where would you put the element? Inside the form? Something like <form><accessible-form></accessible-form></form>? Or would your <accessible-form> be a replacement for the form element?

@pcatre Yes, the <accessible-form> I've created is a replacement for <form> and does convert to a <form> when run .... but you are correct, the example here doesn't show all that. So I should change it like you suggest - its a better example - thanks.

validation - Set focus on first invalid input in AngularJs form - Stac...

validation angularjs angularjs-directive wcag
Rectangle 27 76

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.

elem is already a angular.element(), so if you're using jQuery at least you can just do elem.find('.ng-invalid:first').focus(). Not sure if jqLite supports the :first selector as well.

This could be made better by focusing only on visible elements like so: var firstInvalid = element.find('.ng-invalid:visible').first(); There are a few edge cases when this could make sense.

@pcatre - I also see you made an edit which was rejected suggesting a change to an 'A' attribute directive. Of course an A directive or even a C directive would also work - but why didn't the E directive work for you? It seems to work just fine for me.

@iandotkelly with an attribute directive we can do something like this: <form accessible-form></form> With an element directive where would you put the element? Inside the form? Something like <form><accessible-form></accessible-form></form>? Or would your <accessible-form> be a replacement for the form element?

@pcatre Yes, the <accessible-form> I've created is a replacement for <form> and does convert to a <form> when run .... but you are correct, the example here doesn't show all that. So I should change it like you suggest - its a better example - thanks.

validation - Set focus on first invalid input in AngularJs form - Stac...

validation angularjs angularjs-directive wcag