Angularjs mencegah pengiriman formulir ketika validasi input gagal

155

Saya sedang menulis formulir login sederhana menggunakan angularjs dengan beberapa validasi input sisi klien untuk memeriksa bahwa nama pengguna dan kata sandi tidak kosong dan lebih panjang dari tiga karakter. Lihat kode di bawah ini:

<form name="loginform" novalidate ng-submit="login.submit()" class="css-form">
    <fieldset>

        <div class="control-group input-prepend">
            <span class="add-on"><i class="icon-user"></i></span>
            <input type="text" ng-model="login.username" name="username" required ng-minlength="3" placeholder="username" />
        </div>

        <div class="control-group input-prepend">
            <span class="add-on"><i class="icon-lock"></i></span>
            <input type="password" ng-model="login.password" name="password" required ng-minlength="3" placeholder="" />
        </div>

        <div class="control-group">
            <input class="btn" type="submit" value="Log in">
        </div>

    </fieldset>
</form>

Dan pengontrolnya:

var controller = function($scope) {

    $scope.login = {
        submit: function() {

            Console.info($scope.login.username + ' ' + $scope.login.password);
        }
    }

};

Masalahnya adalah bahwa login.submitfungsi tersebut akan dipanggil bahkan jika inputnya tidak valid. Apakah mungkin untuk mencegah perilaku ini?

Sebagai catatan saya dapat menyebutkan bahwa saya juga menggunakan bootstrap dan requireejs.

Runar Halse
sumber
bisakah kita menggunakannya tanpa tag form dan masih form.valid akan berfungsi pada ng-klik!
Rizwan Patel

Jawaban:

329

Anda dapat melakukan:

<form name="loginform" novalidate ng-submit="loginform.$valid && login.submit()">

Tidak perlu untuk memeriksa pengontrol.

cyberwombat
sumber
8
Ini harus menjadi jawaban yang diterima. Tidak perlu memeriksa apa pun di controller
Howie
10
Saya tidak setuju dengan "tidak perlu untuk memeriksa kontroler". Bagaimana jika kami melakukan pemeriksaan validasi tambahan terjadi dalam fungsi kirim.
SlaterCodes
6
Lakukan validasi tambahan dalam arahan. Perbarui validasi dengan $ setValidity.
TMB
@ b1tsh1ft Akan lebih baik untuk memiliki status validasi saat ini yang selalu diketahui daripada mencari tahu saat pengiriman. Itulah inti dari validasi sudut. Anda tidak dapat memiliki indikasi visual dari keadaan tidak valid ketika ruang lingkup tidak mengetahuinya.
Kevin Beal
1
Saya telah mencoba pendekatan ini, tetapi tampaknya ia mengevaluasi keduanya (yaitu tidak menyebabkan korsleting boolean setelah &&saya mencoba meneruskan nilainya sebagai bagian dari pengiriman dan mengonfirmasi bahwa nilainya sendiri "salah"
Archimedes Trajano
67

Ubah tombol kirim ke:

<button type="submit" ng-disabled="loginform.$invalid">Login</button>
Bijan
sumber
1
Jawaban yang bagus Kamu keren!
Harsha.Vaswani
24
Anda masih dapat mengirimkan formulir jika Anda menekan enter saat bidang input memiliki fokus!
fabsenet
2
@ Merah: Lihat komentar di atas.
Andrei Rînea
Meskipun menonaktifkan tombol biasanya merupakan cara terbaik untuk menyelesaikan ini, bukan itu yang diminta OP.
turun tangan
1
Menggabungkan teknik ini untuk memberikan umpan balik visual bagi pengguna bersama dengan jawaban @Yashua untuk mencegah pengiriman formulir adalah sempurna. Terima kasih!
tkarls
43

Jadi jawaban yang disarankan dari TheHippo tidak bekerja untuk saya, sebagai gantinya saya akhirnya mengirim formulir sebagai parameter ke fungsi seperti:

<form name="loginform" novalidate ng-submit="login.submit(loginForm)" class="css-form">

Ini membuat formulir tersedia dalam metode pengontrol:

$scope.login = {
    submit : function(form) {
        if(form.$valid)....
    }
Runar Halse
sumber
Saya memiliki masalah yang sama. Namun, menggunakan metode Anda berhasil.
Panda4Man
Ini sedikit lebih baik daripada Jawaban yang Diterima karena formulir. $ Cek valid dilakukan dalam JS dan bukan dalam HTML.
cellepo
Namun, saya tidak berpikir Anda harus melewati loginForm untuk mengirimkan fungsi: Saya pikir $ scope.loginform harus tersedia di JS (setidaknya itu untuk saya), sehingga Anda dapat mengganti formulir. $ Valid dengan $ scope.loginform . $ valid.
cellepo
13

Formulir Anda secara otomatis dimasukkan ke dalam $ scope sebagai objek. Itu dapat diakses melalui$scope[formName]

Di bawah ini adalah contoh yang akan bekerja dengan pengaturan asli Anda dan tanpa harus menyerahkan formulir itu sendiri sebagai parameter dalam ng-kirim.

var controller = function($scope) {

    $scope.login = {
        submit: function() {
            if($scope.loginform.$invalid) return false;

        }
    }

};

Contoh kerja: http://plnkr.co/edit/BEWnrP?p=preview

davidmdem
sumber
4
Bagaimana Anda mengakses formulir jika Anda menggunakan notasi "As Controller" alih-alih $ scope?
masimplo
@masimakopoulos: Anda cukup menggunakan if(this.loginform.$invalid).. sebagai gantinya tetapi kemudian dalam HTML Anda harus memberikan formulir nama <form name="ctrl.loginform" ... Dan itu dengan asumsi Anda menggunakan <div ng-controller="controller as ctrl"..sintaks-controller Anda. Terima kasih @JoshCaroll
Bart
13

HTML:

<div class="control-group">
    <input class="btn" type="submit" value="Log in" ng-click="login.onSubmit($event)">
</div>

Di controller Anda:

$scope.login = {
    onSubmit: function(event) {
        if (dataIsntValid) {
            displayErrors();
            event.preventDefault();
        }
        else {
            submitData();
        }
    }
}
TheHippo
sumber
apakah benar-benar perlu melakukan pemeriksaan dalam metode onsubmit? Ini berarti Anda harus memeriksa bahwa input memenuhi semua kriteria baik dalam markup (melalui sudut) dan dalam kode js. Menurut pendapat saya, angular seharusnya tidak memanggil onsubmit ketika input tidak valid. lihat benlesh.com/2012/11/angular-js-form-validation.html mengatakan "ng-kirim tidak dapat dipanggil sampai seluruh formulir $ valid"
Runar Halse
Anda juga dapat menonaktifkan tombol untuk tidak mengizinkan pengiriman jika formulir valid. Anda juga bisa menggunakan formulir ng-kirim. Jika angular tidak menangani validasi formulir maka event.preventDefault()itu cara untuk pergi, untuk menghentikan pengiriman formulir.
TheHippo
@RunarHalse Sangat penting untuk melakukan pemeriksaan. Saya setuju dengan Anda bahwa seharusnya tidak seperti ini. Alasan bahwa metode onsubmit tidak dipanggil dalam contoh yang Anda tautkan adalah karena contoh itu tidak memiliki set novalidate. Browser mencegah acara meningkat, bukan Angular. Ini adalah contohnya w / nobalidate di: plnkr.co/edit/R0C8XA?p=preview . Perhatikan formulir yang diajukan.
davidmdem
sempurna hanya apa yang saya cari, cara untuk memblokir form submit menggunakan angular
setebos
3

Meskipun bukan solusi langsung untuk pertanyaan OPs, jika formulir Anda berada dalam ng-appkonteks, tetapi Anda ingin Angular mengabaikannya sama sekali, Anda bisa melakukan ini secara eksplisit menggunakan ngNonBindablearahan:

<form ng-non-bindable>
  ...
</form>
Ian Clark
sumber
2

Hanya untuk menambah jawaban di atas,

Saya memiliki 2 tombol biasa seperti yang ditunjukkan di bawah ini. (Tanpa tipe = "kirim" di mana saja)

<button ng-click="clearAll();" class="btn btn-default">Clear Form</button>
<button ng-disabled="form.$invalid" ng-click="submit();"class="btn btn-primary pull-right">Submit</button>

Tidak peduli berapa banyak saya mencoba, menekan enter setelah formulir itu valid , tombol "Hapus Formulir" dipanggil, membersihkan seluruh formulir.

Sebagai solusinya,

Saya harus menambahkan tombol kirim dummy yang dinonaktifkan dan disembunyikan. Dan tombol boneka ini harus berada di atas semua tombol lain seperti yang ditunjukkan di bawah ini .

<button type="submit" ng-hide="true" ng-disabled="true">Dummy</button>

<button ng-click="clearAll();" class="btn btn-default">Clear Form</button>

<button ng-disabled="form.$invalid" ng-click="submit();"class="btn btn-primary pull-right">Submit</button>

Yah, maksud saya adalah tidak pernah mengirimkan pada Enter, jadi peretasan yang diberikan di atas berfungsi dengan baik.

vighnu
sumber
Anda dapat berhenti mengirimkan saat tekan enter juga dengan menghapus atribut pada saat mengirimkan dari formulir Anda
Kieran
1

Saya tahu ini adalah utas lama tapi saya pikir saya juga akan memberikan kontribusi. Solusi saya mirip dengan posting yang sudah ditandai sebagai jawaban. Beberapa pemeriksaan inline JavaScript melakukan triknya.

ng-click="form.$invalid ? alert('Please correct the form') : saveTask(task)"
Dave Russell
sumber
1
Anda masih dapat mengirimkan formulir jika Anda menekan enter saat bidang input memiliki fokus!
Yevgeniy Afanasyev
0

Saya tahu ini sudah larut dan dijawab, tetapi saya ingin membagikan hal-hal rapi yang saya buat. Saya membuat arahan validasi ng yang mengaitkan pengiriman formulir, lalu mengeluarkan default-default jika $ eval salah:

app.directive('ngValidate', function() {
  return function(scope, element, attrs) {
    if (!element.is('form'))
        throw new Error("ng-validate must be set on a form elment!");

    element.bind("submit", function(event) {
        if (!scope.$eval(attrs.ngValidate, {'$event': event}))
            event.preventDefault();
        if (!scope.$$phase)
            scope.$digest();            
    });
  };
});

Di html Anda:

<form name="offering" method="post" action="offer" ng-validate="<boolean expression">
Ran Cohen
sumber