Angular.js secara terprogram mengatur bidang formulir menjadi kotor

105

Saya secara terprogram memperbarui beberapa bidang di formulir saya dengan nilai dan saya ingin menyetel status bidang ke $dirty. Melakukan sesuatu seperti:

$scope.myForm.username.$dirty = true; sepertinya tidak berhasil.

Ada metode $setPristineyang dapat saya gunakan untuk mengatur ulang status lapangan tetapi tidak ada $setDirtymetode?

Jadi bagaimana cara melakukan ini?

Saya melihat posting ini https://groups.google.com/forum/#!topic/angular/NQKGAFlsln4 tetapi sepertinya saya tidak dapat menemukan $setDirtymetodenya. Saya menggunakan Angular versi 1.1.5.

super9
sumber
mungkin Anda hanya perlu menetapkan beberapa nilai (default)?
Cherniv
3
Metode $ setDirty didokumentasikan di sini: docs.angularjs.org/api/ng.directive:form.FormController
David Lin
2
Tampaknya berada pada level bentuk. Saya membutuhkan $setDirtydi tingkat lapangan.
super9
mengambil risiko di sini, tetapi satu solusi yang mungkin, tetapi agak hacky, untuk ini adalah mencari tahu apa yang digunakan event listener angular untuk mengikat ke jenis bidang tersebut, dan mengaktifkan listener tersebut secara manual segera setelah pembaruan. </uglyHack>
bguiz
Saya berpikir untuk mengubah kelas secara terprogram tetapi itu tidak akan mengubah status bidang formulir dengan cara yang benar seperti yang saya pikirkan ...
super9

Jawaban:

51

Sejak AngularJS 1.3.4 Anda dapat menggunakan $setDirty()di bidang ( sumber ). Misalnya, untuk setiap bidang dengan kesalahan dan ditandai diperlukan, Anda dapat melakukan hal berikut:

angular.forEach($scope.form.$error.required, function(field) {
    field.$setDirty();
});
Mateusz Rasiński
sumber
87

Dalam kasus Anda, $scope.myForm.username.$setViewValue($scope.myForm.username.$viewValue);lakukan triknya - membuat formulir dan bidang menjadi kotor, dan menambahkan kelas CSS yang sesuai.

Sejujurnya, saya menemukan solusi ini di posting baru di topik dari tautan dari pertanyaan Anda. Ini bekerja dengan sempurna untuk saya, jadi saya meletakkan ini di sini sebagai jawaban mandiri agar lebih mudah ditemukan.

EDIT:

Solusi di atas bekerja paling baik untuk versi Angular hingga 1.3.3. Mulai 1.3.4, Anda harus menggunakan metode API yang baru dibuka $setDirty()dari ngModel.NgModelController.

kain perca
sumber
Ini tampaknya berubah bagi saya antara Angular 1.3.0-beta5 dan 1.3.0, di mana 1.3.0 membuat bidang $ murni selama $ viewValue tidak berubah. Saya harus melakukannya $scope.myForm.myField.$pristine = false; $scope.myForm.myField.$setViewValue(...). Sepertinya jawaban di bawah ini menyatakan bahwa field.$setDirty()ditambahkan di Angular 1.3.4 akan menjadi solusi yang lebih baik
Johann
4
Terima kasih atas catatan Anda, Anda telah menghemat hari saya "hingga 1.3.3. Dimulai dengan 1.3.4 Anda harus menggunakan metode API yang baru dibuka"
Ahmed Mahmoud
pengguna rmag, dan bagaimana dengan angular 2?
pengguna5260143
17

Anda harus mengatur $dirtyke truedan $pristineke secara manual falseuntuk bidang tersebut. Jika Anda ingin kelas muncul pada masukan Anda, maka Anda harus menambah ng-dirtydan menghapus ng-pristinekelas dari elemen secara manual. Anda dapat menggunakan $setDirty()di tingkat formulir untuk melakukan semua ini di formulir itu sendiri, tetapi bukan masukan formulir, masukan formulir saat ini tidak memiliki $setDirty()seperti yang Anda sebutkan.

Jawaban ini mungkin berubah di masa depan karena harus menambah $setDirty()masukan, tampaknya logis.

TheSharpieOne
sumber
3
$ setPristine () ada di level input-field tapi masih tidak ada $ setDirty di 1.2.26 :-(
Sebastian
10

Jika Anda memiliki akses ke NgModelController (Anda hanya bisa mengaksesnya dari arahan) maka Anda dapat memanggil

ngModel.$setViewValue("your new view value");
// or to keep the view value the same and just change it to dirty
ngModel.$setViewValue(ngModel.$viewValue);
Marshall Brekka
sumber
Terima kasih! Persis apa yang saya cari.
dreyln
10

Membuat jsFiddle hanya untuk Anda yang memecahkan masalah ini. cukup setel $ dirty menjadi true, tetapi dengan $timeout 0begitu ini berjalan setelah DOM dimuat.

Temukan di sini: JsFiddle

$timeout(function () {
  $scope.form.uName.$dirty = true;
}, 0);
Gilad Peleg
sumber
6

Inilah yang berhasil bagi saya

$scope.form_name.field_name.$setDirty()
shakirthow
sumber
5

Fungsi pembantu untuk melakukan pekerjaan:

function setDirtyForm(form) {
    angular.forEach(form.$error, function(type) {
        angular.forEach(type, function(field) {
            field.$setDirty();
        });
    });
    return form;
}
Rodolfo Jorge Nemer Nogueira
sumber
Hei, sayangnya saya tidak sengaja meremehkan ini. Bagaimana cara mengembalikannya. Jadi memberi tahu saya bahwa saya tidak dapat melakukan ini tanpa jawaban diedit ..
smk
Ini bekerja dengan baik; upvoting sebagai pemeriksaan untuk 'form. $ error' memastikan kita tidak 'dirtifying' bidang yang tidak disentuh pengguna, tetapi yang valid.
Sam T
Terima kasih! Solusi mudah dan sederhana. Mungkin bukan yang tercepat tetapi tidak melakukan sesuatu yang berat jadi tidak masalah imo. Kerja bagus!
jwanglof
4

Sudut 2

Bagi siapa pun yang ingin melakukan hal yang sama di Angular 2 itu sangat mirip selain mendapatkan formulirnya

<form role="form" [ngFormModel]="myFormModel" (ngSubmit)="onSubmit()" #myForm="ngForm">
<div class="form-group">
    <label for="name">Name</label>
    <input autofocus type="text" ngControl="usename" #name="ngForm" class="form-control" id="name" placeholder="Name">
    <div [hidden]="name.valid || name.pristine" class="alert alert-danger">
        Name is required
    </div>
</div>
</form>
<button type="submit" class="btn btn-primary" (click)="myForm.ngSubmit.emit()">Add</button>

import { Component, } from '@angular/core';
import { FormBuilder, Validators } from '@angular/common';

@Component({
    selector: 'my-example-form',
    templateUrl: 'app/my-example-form.component.html',
    directives: []
})
export class MyFormComponent {
    myFormModel: any;

    constructor(private _formBuilder: FormBuilder) {
        this.myFormModel = this._formBuilder.group({
            'username': ['', Validators.required],
            'password': ['', Validators.required]
        });
    }

    onSubmit() {
        this.myFormModel.markAsDirty();
        for (let control in this.myFormModel.controls) {
            this.myFormModel.controls[control].markAsDirty();
        };

        if (this.myFormModel.dirty && this.myFormModel.valid) {
            // My submit logic
        }
    }
}
edqwerty.dll
sumber
3

Catatan tambahan kecil untuk jawaban @ rmag. Jika Anda memiliki bidang kosong tapi wajib diisi yang ingin Anda jorok gunakan ini:

$scope.myForm.username.$setViewValue($scope.myForm.username.$viewValue !== undefined 
    ? $scope.myForm.username.$viewValue : '');
Fran Arant
sumber
Inilah jawaban yang akhirnya membantu saya!
Kirk Liemohn
-1

Saya tidak yakin mengapa Anda mencoba menandai bidang sebagai kotor, tetapi saya mengalami situasi yang sama karena saya ingin kesalahan validasi muncul saat seseorang mencoba mengirimkan formulir yang tidak valid. Saya akhirnya menggunakan jQuery untuk menghapus .ng-pristinetag kelas dan menambahkan .ng-dirtytag kelas ke bidang yang sesuai. Sebagai contoh:

$scope.submit = function() {
    // `formName` is the value of the `name` attribute on your `form` tag
    if (this.formName.$invalid)
    {
        $('.ng-invalid:not("form")').each(function() {
            $(this).removeClass('ng-pristine').addClass('ng-dirty');
        });
        // the form element itself is index zero, so the first input is typically at index 1
        $('.ng-invalid')[1].focus();
    }
}
Ben Harold
sumber
5
Mengingat bahwa kami sudah menggunakan AngularJS, solusi jQuery tampaknya berlebihan. Banyak orang lebih suka tidak menggunakan jQuery dengan AngularJS, misalnya.
StevenClontz