Wyłącz przycisk przesyłania, gdy formularz jest nieprawidłowy w AngularJS

174

Mam taki formularz:

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

Jak widać, przycisk jest wyłączony, jeśli wejście jest puste, ale nie zmienia się z powrotem na włączony, gdy zawiera tekst. Jak mogę to zrobić?

ali
źródło

Odpowiedzi:

339

Musisz użyć nazwy swojego formularza, a także ng-disabled: Oto demo na Plunker

<form name="myForm">
    <input name="myText" type="text" ng-model="mytext" required />
    <button ng-disabled="myForm.$invalid">Save</button>
</form>
Ben Lesh
źródło
Przepraszam, używam go teraz. Jednak nadal jest wyłączony, nawet jeśli pole tekstowe zawiera tekst
ali
1
+1 Przypadkowo właśnie czytałem ten twój wspaniały post: benlesh.com/2012/11/angular-js-form-validation.html
Ben
co jeśli nie mam formularza? Czy mogę to zrobić również na elemencie div?
VsMaX
1
@MichaelCwienczek technicznie, można dodać NG-formularz do znacznika div: <div ng-form="myForm"> ... stuff here .. </div>. Chociaż, jeśli przesyłasz wartość z danych wejściowych, po naciśnięciu przycisku, bardzo polecam użycie <form/>tagu, jeśli nie ma innego powodu niż pozwala użytkownikowi nacisnąć [ENTER] i przesłać formularz. Ale prawdopodobnie stanowi to również lepszą praktykę z powodu takich kwestii, jak problemy z dostępnością.
Ben Lesh
2
@BenLesh, co jeśli przycisku przesyłania nie ma w moim formularzu, a mimo to muszę go wyłączyć, jeśli formularz jest nieprawidłowy.
Green Wizard
33

Aby dodać do tej odpowiedzi. Właśnie się dowiedziałem, że również się zepsuje, jeśli użyjesz łącznika w nazwie formularza (Angular 1.3):

Więc to nie zadziała:

<form name="my-form">
    <input name="myText" type="text" ng-model="mytext" required />
    <button ng-disabled="my-form.$invalid">Save</button>
</form>
wvdz
źródło
3
Tak, nazwa formularza powinna być w wielbłądzie dla wszystkich walidacji formularza AngularJS.
Dubilla
7
ogólnie
A więc co się stanie, jeśli formularz jest członkiem zestawu formularzy i dlatego wymaga się, aby nazwa zawierała łącznik (np. „My_formset_name-0”)?
trubliphone
2
W powyższym przykładzie uważam, że myForm.$invalidpowinno nadal działać, więc w twoim przypadku myślę, że my_formset_name0.$invalidpowinno działać.
wvdz
29

Wybrana odpowiedź jest poprawna, ale ktoś taki jak ja może mieć problemy z walidacją asynchroniczną przy wysyłaniu żądania do serwera - przycisk nie będzie wyłączony podczas przetwarzania danego żądania, więc przycisk będzie mrugał, co dla użytkowników wygląda dość dziwnie.

Aby to unieważnić, wystarczy obsłużyć stan $ pending formularza:

<form name="myForm">
  <input name="myText" type="text" ng-model="mytext" required />
  <button ng-disabled="myForm.$invalid || myForm.$pending">Save</button>
</form>
Ivan Sokalskiy
źródło
Bardzo dziękuję za rozwiązanie do walidacji asynchronicznej!
Martin Brandl
Powinieneś po prostu użyć !myForm.$validtego, który obsługuje również oczekujące problemy asynchroniczne. itnext.io/valid-and-invalid-in-angular-forms-61cfa3f2a0cd
SavageCore
6

Jeśli korzystasz z Reactive Forms, możesz użyć tego:

<button [disabled]="!contactForm.valid" type="submit" class="btn btn-lg btn primary" (click)="printSomething()">Submit</button>
Nelul
źródło
2
Chociaż jest to ważna rada dla „Angular”, ta odpowiedź jest nieprawidłowa dla „AngularJS”. Mianowicie, (click)i [disabled]nie są poprawnym kodem AngularJS, ani Reactive Forms nie są częścią frameworka AngularJS. „Angular to nazwa Angulara
dapperdan1985
1

Możemy utworzyć prostą dyrektywę i wyłączyć przycisk, aż wszystkie obowiązkowe pola zostaną wypełnione.

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

Aby uzyskać więcej informacji, kliknij tutaj

Prashobh
źródło
Twoja metoda rozwiązania działa dla mnie z niewielkimi zmianami. Dziękuję
Tatipaka
Dlaczego miałbyś to robić, skoro natywne dyrektywy ng-disabledw angular 1.x i [disabled]angular 2 | 4.x są znacznie lepiej przetestowane niż to? Po drugie, dlaczego mamy dyrektywę, która jest ograniczona do formularza, aby wyłączyć zagnieżdżony przycisk, jest super specyficzna. Źle przemyślane rozwiązanie IMO.
David Barker
Powyżej znajduje się przykładowa dyrektywa, oryginalna ma wiele scenariuszy, takich jak zagnieżdżone pole wyboru itp. I nie chcę bałaganić mojego kodu HTML, dodając w każdej formie, zamiast tego ta dyrektywa zajmie się wszystkimi rzeczami.
Prashobh
1

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

Jeśli chcesz być nieco bardziej rygorystyczny

Cengkuru Michael
źródło