Angular.js programowo ustawiając pole formularza na brudne

105

Programowo aktualizuję niektóre pola w moim formularzu za pomocą wartości i chcę ustawić stan pola na $dirty. Robię coś takiego:

$scope.myForm.username.$dirty = true; nie wydaje się działać.

Istnieje metoda $setPristine, której mogę użyć, aby zresetować stan pola, ale nie ma $setDirtymetody?

Jak więc można to zrobić?

Widziałem ten post https://groups.google.com/forum/#!topic/angular/NQKGAFlsln4, ale nie mogę znaleźć $setDirtymetody. Używam Angular w wersji 1.1.5.

super9
źródło
może po prostu trzeba ustawić jakąś (domyślną) wartość?
Czerniow
3
Metoda $ setDirty jest udokumentowana tutaj: docs.angularjs.org/api/ng.directive:form.FormController
David Lin,
2
Wygląda na to, że jest na poziomie formularza. Potrzebuję $setDirtyna poziomie pola.
super9
ale jednym z możliwych, ale raczej hackerskim, rozwiązaniem byłoby ustalenie, jakiego detektora zdarzeń używa angular do łączenia się z tym typem pola i ręczne uruchomienie tego nasłuchu natychmiast po aktualizacji. </uglyHack>
bguiz
Myślałem o programowej zmianie klasy, ale nie zmieni to stanu pola formularza w prawidłowy sposób, bym pomyślał ...
super9

Odpowiedzi:

51

Od AngularJS 1.3.4 możesz używać $setDirty()na polach ( źródło ). Na przykład dla każdego pola z błędem i oznaczonym jako wymagane możesz wykonać następujące czynności:

angular.forEach($scope.form.$error.required, function(field) {
    field.$setDirty();
});
Mateusz Rasiński
źródło
87

W twoim przypadku $scope.myForm.username.$setViewValue($scope.myForm.username.$viewValue);załatwia sprawę - brudzi zarówno formularz, jak i pole oraz dołącza odpowiednie klasy CSS.

Szczerze mówiąc to rozwiązanie znalazłem w nowym poście w temacie z linku z Twojego pytania. U mnie zadziałało idealnie, więc umieszczam to tutaj jako samodzielną odpowiedź, aby łatwiej ją znaleźć.

EDYTOWAĆ:

Powyższe rozwiązanie działa najlepiej dla wersji Angular do 1.3.3. Począwszy od wersji 1.3.4, powinieneś użyć nowo ujawnionej metody API $setDirty()z ngModel.NgModelController.

rmag
źródło
Wydawało mi się, że zmieniło się to między Angular 1.3.0-beta5 a 1.3.0, gdzie 1.3.0 utrzymuje pole $ w stanie nieskazitelnym, o ile $ viewValue się nie zmienia. Musiałem to zrobić $scope.myForm.myField.$pristine = false; $scope.myForm.myField.$setViewValue(...). Wygląda na to, że odpowiedź poniżej stwierdzająca, że field.$setDirty()została dodana w Angular 1.3.4 będzie lepszym rozwiązaniem
Johann
4
Dzięki za wiadomość, uratowałeś mi dzień „do wersji 1.3.3. Począwszy od wersji 1.3.4 powinieneś używać nowo ujawnionej metody API”
Ahmed Mahmoud
użytkownik rmag, a co z angularem 2?
user5260143
17

trzeba będzie ustawić ręcznie $dirty, aby truei $pristinena falsena polu. Jeśli chcesz, aby klasy pojawiały się na twoim wejściu, będziesz musiał ręcznie dodawać ng-dirtyi usuwać ng-pristineklasy z elementu. Możesz użyć $setDirty()na poziomie formularza, aby zrobić to wszystko w samym formularzu, ale nie na danych wejściowych formularza, których obecnie nie ma, $setDirty()jak wspomniałeś.

Ta odpowiedź może się zmienić w przyszłości, ponieważ powinny one dodawać $setDirty()do danych wejściowych, wydaje się logiczne.

TheSharpieOne
źródło
3
$ setPristine () jest na poziomie pola wejściowego, ale nadal nie ma $ setDirty w 1.2.26 :-(
Sebastian
10

Jeśli masz dostęp do NgModelController (możesz uzyskać do niego dostęp tylko z dyrektywy), możesz wywołać

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
źródło
Dziękuję Ci! Dokładnie to, czego szukałem.
dreyln
10

Stworzyłem jsFiddle specjalnie dla Ciebie, które rozwiązuje ten problem. po prostu ustaw $ dirty na true, ale z $timeout 0tak działa po załadowaniu DOM.

Znajdź to tutaj: JsFiddle

$timeout(function () {
  $scope.form.uName.$dirty = true;
}, 0);
Gilad Peleg
źródło
6

To właśnie zadziałało dla mnie

$scope.form_name.field_name.$setDirty()
shakirthow
źródło
5

Funkcja pomocnicza do wykonania pracy:

function setDirtyForm(form) {
    angular.forEach(form.$error, function(type) {
        angular.forEach(type, function(field) {
            field.$setDirty();
        });
    });
    return form;
}
Rodolfo Jorge Nemer Nogueira
źródło
Hej, niestety przypadkowo odrzuciłem to. Jak to przywrócić. Mówiąc mi, że nie mogę tego zrobić bez redagowania odpowiedzi ...
smk
To działa dobrze; upvoting jako sprawdzanie „form. $ error” zapewnia, że ​​nie „brudzimy” pól, których użytkownik nie dotykał, ale które są prawidłowe.
Sam T
Dziękuję Ci! Łatwe i proste rozwiązanie. Może nie jest najszybszy, ale nie robi nic ciężkiego, więc to naprawdę nie ma znaczenia, imo. Dobra robota!
jwanglof
4

Kątowy 2

Dla każdego, kto chce zrobić to samo w Angular 2, jest to bardzo podobne, poza uzyskaniem formy

<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
źródło
3

Mała dodatkowa uwaga do odpowiedzi @ rmag. Jeśli masz puste, ale wymagane pola, które chcesz zmienić, użyj tego:

$scope.myForm.username.$setViewValue($scope.myForm.username.$viewValue !== undefined 
    ? $scope.myForm.username.$viewValue : '');
Fran Arant
źródło
To odpowiedź, która w końcu mi pomogła!
Kirk Liemohn,
-1

Nie jestem pewien, dlaczego próbujesz oznaczyć pola jako brudne, ale znalazłem się w podobnej sytuacji, ponieważ chciałem, aby błędy walidacji pojawiały się, gdy ktoś próbował przesłać nieprawidłowy formularz. Skończyło się na użyciu jQuery do usunięcia .ng-pristinetagów klas i dodania .ng-dirtytagów klas do odpowiednich pól. Na przykład:

$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
źródło
5
Biorąc pod uwagę, że już używamy AngularJS, rozwiązanie jQuery wydaje się przesadą. Na przykład wiele osób woli nie używać jQuery z AngularJS.
StevenClontz