179

I have my form like this:

<form name="myForm">
    <input name="myText" type="text" ng-model="mytext" required />
    <button disabled="{{ myForm.$invalid }}">Save</button>
</form>

As you may see, the button is disabled if the input is empty but it doesn't change back to enabled when it contains text. How can I make it work?

0

6 Answers 6

351

You need to use the name of your form, as well as ng-disabled: Here's a demo on Plunker

<form name="myForm">
    <input name="myText" type="text" ng-model="mytext" required />
    <button ng-disabled="myForm.$invalid">Save</button>
</form>
Sign up to request clarification or add additional context in comments.

6 Comments

Sorry, I use it now. Yet, it is still disabled even when the textbox contains text
+1 Coincidentally, I was just reading this great post of yours: benlesh.com/2012/11/angular-js-form-validation.html
what if I don't have a form? Can I do that also on div element?
@MichaelCwienczek technically, you can add ng-form to a div tag: <div ng-form="myForm"> ... stuff here .. </div>. Although, if you're submitting a value from inputs, on button push, I highly recommend using a <form/> tag, if for no other reason than it allows a user to hit [ENTER] and submit the form. But it also likely constitutes better practice because of things like accessibility concerns.
@BenLesh, what if the submit button is not inside my form and still I have to disable it if the form in invalid.
|
34

To add to this answer. I just found out that it will also break down if you use a hyphen in your form name (Angular 1.3):

So this will not work:

<form name="my-form">
    <input name="myText" type="text" ng-model="mytext" required />
    <button ng-disabled="my-form.$invalid">Save</button>
</form>

4 Comments

Yes, the form name should be in camel case for any AngularJS form validations.
as a rule of thumb, all js like expressions will recognise objects in the camelcase form, while dash is for html like syntax
So, what happens if the form is a member of a formset, and therefore is required to have a name w/ a hyphen in it (like "my_formset_name-0")?
In the example above, I believe myForm.$invalid should still work, so in your case, I would think my_formset_name0.$invalid should work.
29

Selected response is correct, but someone like me, may have issues with async validation with sending request to the server-side - button will be not disabled during given request processing, so button will blink, which looks pretty strange for the users.

To void this, you just need to handle $pending state of the form:

<form name="myForm">
  <input name="myText" type="text" ng-model="mytext" required />
  <button ng-disabled="myForm.$invalid || myForm.$pending">Save</button>
</form>

2 Comments

Thank you very much for the async validation solution!
You should just use !myForm.$valid that handles async Pending issues as well. itnext.io/valid-and-invalid-in-angular-forms-61cfa3f2a0cd
6

If you are using Reactive Forms you can use this:

<button [disabled]="!contactForm.valid" type="submit" class="btn btn-lg btn primary" (click)="printSomething()">Submit</button>

1 Comment

Although this is valid advice for "Angular", this answer is invalid for "AngularJS". Namely, (click) and [disabled] aren't valid AngularJS code, nor are Reactive Forms a part of the AngularJS framework. "Angular is the name for the Angular of today and tomorrow. AngularJS is the name for all v1.x versions of Angular" angular.io/guide/ajs-quick-reference
2

<form name="myForm">
        <input name="myText" type="text" ng-model="mytext" required/>
        <button ng-disabled="myForm.$pristine|| myForm.$invalid">Save</button>
</form>

If you want to be a bit more strict

Comments

1

We can create a simple directive and disable the button until all the mandatory fields are filled.

angular.module('sampleapp').directive('disableBtn',
function() {
 return {
  restrict : 'A',
  link : function(scope, element, attrs) {
   var $el = $(element);
   var submitBtn = $el.find('button[type="submit"]');
   var _name = attrs.name;
   scope.$watch(_name + '.$valid', function(val) {
    if (val) {
     submitBtn.removeAttr('disabled');
    } else {
     submitBtn.attr('disabled', 'disabled');
    }
   });
  }
 };
}
);

For More Info click here

3 Comments

Your method of solution works for me with little tweak. Thank you
Why would you do this when there are native directives ng-disabled in angular 1.x and [disabled] in angular 2|4.x that are much better tested than this?. Secondly, why have a directive that is scoped to a form to disable a nested button, it's super specific. An ill thought out solution IMO.
Above is a sample directive , original have many scenarios like nested check box etc and I dont want to messy my html code by adding in every form,instead this directive will take care all the things.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.