Deshabilitar el botón de enviar cuando el formulario no es válido con AngularJS

174

Tengo mi forma así:

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

Como puede ver, el botón está deshabilitado si la entrada está vacía pero no vuelve a estar habilitada cuando contiene texto. ¿Cómo puedo hacer que funcione?

Ali
fuente

Respuestas:

339

Debe usar el nombre de su formulario, así como ng-disabled: aquí hay una demostración en Plunker

<form name="myForm">
    <input name="myText" type="text" ng-model="mytext" required />
    <button ng-disabled="myForm.$invalid">Save</button>
</form>
Ben Lesh
fuente
Lo siento, lo uso ahora. Sin embargo, todavía está deshabilitado, incluso cuando el cuadro de texto contiene texto
Ali
1
+1 Casualmente, estaba leyendo esta gran publicación tuya: benlesh.com/2012/11/angular-js-form-validation.html
Ben
¿Qué pasa si no tengo un formulario? ¿Puedo hacer eso también en el elemento div?
VsMaX
1
@MichaelCwienczek técnicamente, se puede añadir en forma ng a una etiqueta div: <div ng-form="myForm"> ... stuff here .. </div>. Aunque, si usted está presentando un valor de las entradas, el pulsador, me altamente recomiendo el uso de una <form/>etiqueta, si por ninguna otra razón que permite que un usuario presione [ENTER] y enviar el formulario. Pero también es probable que constituya una mejor práctica debido a problemas de accesibilidad.
Ben Lesh
2
@BenLesh, ¿qué pasa si el botón de envío no está dentro de mi formulario y todavía tengo que deshabilitarlo si el formulario no es válido?
Green Wizard
33

Para agregar a esta respuesta. Me acabo de enterar de que también se descompondrá si usa un guión en el nombre de su formulario (Angular 1.3):

Entonces esto no funcionará:

<form name="my-form">
    <input name="myText" type="text" ng-model="mytext" required />
    <button ng-disabled="my-form.$invalid">Save</button>
</form>
wvdz
fuente
3
Sí, el nombre del formulario debe estar en caso de camello para cualquier validación de formulario AngularJS.
dubilla el
77
como regla general, todas las expresiones js like reconocerán objetos en forma de camelcase, mientras que dash es para html como sintaxis
ecoologic
Entonces, ¿qué sucede si el formulario es miembro de un conjunto de formularios y, por lo tanto, debe tener un nombre con un guión (como "my_formset_name-0")?
Trubliphone
2
En el ejemplo anterior, creo myForm.$invalidque aún debería funcionar, por lo que en su caso, creo que my_formset_name0.$invaliddebería funcionar.
wvdz
29

La respuesta seleccionada es correcta, pero alguien como yo puede tener problemas con la validación asíncrona con el envío de solicitudes al lado del servidor: el botón no se desactivará durante el procesamiento de la solicitud dada, por lo que el botón parpadeará, lo que parece bastante extraño para los usuarios.

Para anular esto, solo necesita manejar el estado $ pendiente del formulario:

<form name="myForm">
  <input name="myText" type="text" ng-model="mytext" required />
  <button ng-disabled="myForm.$invalid || myForm.$pending">Save</button>
</form>
Ivan Sokalskiy
fuente
¡Muchas gracias por la solución de validación asíncrona!
Martin Brandl
Solo debe usar !myForm.$valideso que maneja los problemas pendientes asíncronos también. itnext.io/valid-and-invalid-in-angular-forms-61cfa3f2a0cd
SavageCore
6

Si está utilizando formularios reactivos, puede usar esto:

<button [disabled]="!contactForm.valid" type="submit" class="btn btn-lg btn primary" (click)="printSomething()">Submit</button>
Nelul
fuente
2
Aunque este es un consejo válido para "Angular", esta respuesta no es válida para "AngularJS". A saber, (click)y [disabled]no son códigos válidos de AngularJS, ni los formularios reactivos son parte del marco de AngularJS. "Angular es el nombre de Angular de hoy y de mañana. AngularJS es el nombre de todas las versiones v1.x de Angular" angular.io/guide/ajs-quick-reference
dapperdan1985
1

Podemos crear una directiva simple y deshabilitar el botón hasta que se completen todos los campos obligatorios.

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');
    }
   });
  }
 };
}
);

Para más información haga clic aquí

Prashobh
fuente
Su método de solución funciona para mí con pequeños ajustes. Gracias
Tatipaka
¿Por qué harías esto cuando hay directivas nativas ng-disableden angular 1.xy [disabled]angular 2 | 4.x que están mucho mejor probadas que esta? En segundo lugar, ¿por qué tener una directiva que tiene un alcance en un formulario para deshabilitar un botón anidado? Es súper específico. Una solución mal pensada de la OMI.
David Barker el
Arriba hay una directiva de muestra, las originales tienen muchos escenarios, como la casilla de verificación anidada, etc.
Prashobh
1

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

Si quieres ser un poco más estricto

Cengkuru Michael
fuente