Desativar botão de envio quando o formulário é inválido com AngularJS

174

Eu tenho meu formulário como este:

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

Como você pode ver, o botão será desativado se a entrada estiver vazia, mas não voltará a ser ativada quando contiver texto. Como posso fazer isso funcionar?

todos
fonte

Respostas:

339

Você precisa usar o nome do seu formulário e o ng-disabled: Aqui está uma demonstração do Plunker

<form name="myForm">
    <input name="myText" type="text" ng-model="mytext" required />
    <button ng-disabled="myForm.$invalid">Save</button>
</form>
Ben Lesh
fonte
Desculpe, eu uso agora. No entanto, ele ainda está desativado, mesmo quando a caixa de texto contém texto
ali
1
+1 Coincidentemente, eu estava lendo este grande post de vocês: benlesh.com/2012/11/angular-js-form-validation.html
Ben
e se eu não tiver um formulário? Posso fazer isso também no elemento div?
VsMaX
1
@MichaelCwienczek tecnicamente, você pode adicionar NG-forma a uma tag div: <div ng-form="myForm"> ... stuff here .. </div>. Embora, se você está enviando um valor de insumos, no botão push, eu altamente recomendo usar um <form/>tag, se por nenhuma outra razão do que permite que um usuário hit [ENTER] e enviar o formulário. Mas também provavelmente constitui uma prática melhor devido a questões como acessibilidade.
precisa
2
@ BenLesh, e se o botão enviar não estiver dentro do meu formulário e ainda tiver que desativá-lo se o formulário for inválido.
Assistente Verde
33

Para adicionar a esta resposta. Acabei de descobrir que ele também será quebrado se você usar um hífen no nome do seu formulário (Angular 1.3):

Portanto, isso não vai funcionar:

<form name="my-form">
    <input name="myText" type="text" ng-model="mytext" required />
    <button ng-disabled="my-form.$invalid">Save</button>
</form>
wvdz
fonte
3
Sim, o nome do formulário deve estar em maiúsculas e minúsculas para todas as validações de formulário do AngularJS.
dubilla
7
como regra geral, todos os js como expressões reconhecerão objetos no formato camelcase, enquanto o traço é para html como sintaxe
ecoologic
Então, o que acontece se o formulário for membro de um formset e, portanto, for necessário ter um nome com hífen (como "my_formset_name-0")?
Trubliphone
2
No exemplo acima, acredito myForm.$invalidque ainda deve funcionar, portanto, no seu caso, acho que my_formset_name0.$invaliddeveria funcionar.
Wdc # 7/15
29

A resposta selecionada está correta, mas alguém como eu pode ter problemas com a validação assíncrona com o envio de solicitação para o lado do servidor - o botão não será desativado durante o processamento da solicitação, portanto o botão piscará, o que parece bastante estranho para os usuários.

Para anular isso, você só precisa manipular o estado $ pendente do formulário:

<form name="myForm">
  <input name="myText" type="text" ng-model="mytext" required />
  <button ng-disabled="myForm.$invalid || myForm.$pending">Save</button>
</form>
Ivan Sokalskiy
fonte
Muito obrigado pela solução de validação assíncrona!
Martin Brandl 08/03
Você também deve usar o !myForm.$validque lida com problemas pendentes assíncronos também. itnext.io/valid-and-invalid-in-angular-forms-61cfa3f2a0cd
SavageCore
6

Se você estiver usando Formulários Reativos, poderá usar este:

<button [disabled]="!contactForm.valid" type="submit" class="btn btn-lg btn primary" (click)="printSomething()">Submit</button>
Nelul
fonte
2
Embora esse conselho seja válido para "Angular", esta resposta é inválida para "AngularJS". Nomeadamente, (click)e [disabled]não são códigos AngularJS válidos, nem o Reactive Forms faz parte da estrutura do AngularJS. "Angular é o nome para o angular de hoje e amanhã AngularJS é o nome para todas as versões v1.x de Angular." Angular.io/guide/ajs-quick-reference
dapperdan1985
1

Podemos criar uma diretiva simples e desativar o botão até que todos os campos obrigatórios sejam preenchidos.

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 mais informações clique aqui

Prashobh
fonte
Seu método de solução funciona para mim com pequenos ajustes. Obrigado
Tatipaka
Por que você faria isso quando existem diretivas nativas ng-disabledno angular 1.xe [disabled]no angular 2 | 4.x que são muito melhores testadas que isso ?. Em segundo lugar, por que uma diretiva tem como escopo um formulário para desativar um botão aninhado, é super específica. Uma solução mal pensada IMO.
David Barker
Acima está uma diretiva de exemplo, o original tem muitos cenários, como a caixa de seleção aninhada, etc.
Prashobh 01/11
1

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

Se você quer ser um pouco mais rigoroso

Cengkuru Michael
fonte