Question

I have the following form:

<form name="formuser" action='/signup' method='post' novalidate>

    <input type="text" name="firstname" ng-model="firstname" ng-class="{ 'has-error' : (formuser.firstname.$invalid && !formuser.firstname.$pristine) || hasSubmitted}" required />

    <button type="submit" ng-disabled="formuser.$invalid" ng-click="hasSubmitted=true">Submit</button>
</form>

I'm trying to add the class 'has-error' to the input field that is invalid after the user has either typed in something or hit the submit button while the input is still pristine. I've added ng-disabled to the submit button to disable the form submition but I still want the ng-click to fire to change the hasSubmitted scope. The problem is that ng-disable on the button also disabled the ng-click.

I know I could always use ng-submit on the form, do validation in my controller, and then fire off an ajax request but my authentication framework requires that I actually submit the form and redirect the browser.

Was it helpful?

Solution

Well, instead of making hacks the most clean solution would be to make the button enabled and just handle the submit using simple directive:

angular.module('common', []).directive('preventSubmit', function () {
    return {
        restrict: 'A',
        scope: {
            preventSubmit: '='
        },
        link: function (scope, element) {
            element.bind('submit', function(e) {
                if (scope.preventSubmit) {
                    e.preventDefault();
                }
            });
        }
    }
});

So what it does it binds to the submit event and if the form is invalid it prevents the form from submitting. If you don't use action attribute Angular handles it automatically and you can handle this but in case of specified action and normal submit this directive can be very useful.

And in the markup:

<form name="formuser" action='/signup' method='post' 
      novalidate prevent-submit="formuser.$invalid">
  ...
  <button type="submit" ng-click="hasSubmitted=true">Submit</button>
</form>

And using ng-style or ng-class you can style your button as expected depending on your form state.

OTHER TIPS

Instead of setting input to disabled, set it to readonly. This will allow ng-clicks to continue functioning.

You could wrap it in another element:

<span ng-click="hasSubmitted=true">
  <button type="submit" ng-class="{noclick:formuser.$invalid}" ng-disabled="formuser.$invalid">Submit</button>
</span>

CSS:

.noclick {
  pointer-events: none;
}

Replace the button with div. ng-click will be fired even though the div is disabled.

See this post for more details.

BTW, you'd need to set the button style on the div. Good luck.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top