Angular.js setzt programmgesteuert ein Formularfeld auf Dirty

105

Ich aktualisiere programmgesteuert einige Felder in meinem Formular mit einem Wert und möchte den Feldstatus auf setzen $dirty. So etwas tun wie:

$scope.myForm.username.$dirty = true; scheint nicht zu funktionieren.

Es gibt eine Methode $setPristine, mit der ich den Status des Feldes zurücksetzen kann, aber es gibt keine $setDirtyMethode?

Wie macht man das?

Ich habe diesen Beitrag https://groups.google.com/forum/#!topic/angular/NQKGAFlsln4 gesehen, aber ich kann die $setDirtyMethode nicht finden . Ich verwende Angular Version 1.1.5.

super9
quelle
Möglicherweise müssen Sie nur einen (Standard-) Wert festlegen?
Cherniv
3
Die $ setDirty-Methode ist hier dokumentiert: docs.angularjs.org/api/ng.directive:form.FormController
David Lin
2
Das scheint auf Formularebene zu sein. Ich brauche eine $setDirtyauf Feldebene.
Super9
Eine mögliche, aber ziemlich hackige Lösung hierfür wäre, herauszufinden, mit welchem ​​Ereignis-Listener-Winkel sich diese Art von Feld verbindet, und diesen Listener unmittelbar nach dem Update manuell auszulösen. </ uglyHack>
Bguiz
Ich dachte daran, die Klasse programmgesteuert zu ändern, aber es wird den Status des Formularfelds nicht in der richtigen Weise ändern, wie ich gedacht hätte ...
super9

Antworten:

51

Seit AngularJS 1.3.4 können Sie $setDirty()Felder ( Quelle ) verwenden. Für jedes fehlerhafte und als erforderlich gekennzeichnete Feld können Sie beispielsweise Folgendes tun:

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

In Ihrem Fall ist $scope.myForm.username.$setViewValue($scope.myForm.username.$viewValue);dies der Trick - es macht sowohl das Formular als auch das Feld schmutzig und fügt entsprechende CSS-Klassen hinzu.

Um ehrlich zu sein, habe ich diese Lösung in einem neuen Beitrag im Thema über den Link aus Ihrer Frage gefunden. Es hat perfekt für mich funktioniert, daher setze ich dies hier als eigenständige Antwort ein, um das Auffinden zu erleichtern.

BEARBEITEN:

Die obige Lösung funktioniert am besten für die Angular-Version bis 1.3.3. Ab 1.3.4 sollten Sie die neu verfügbar gemachte API-Methode $setDirty()von verwenden ngModel.NgModelController.

rmag
quelle
Dies schien sich für mich zwischen Angular 1.3.0-beta5 und 1.3.0 zu ändern, wobei 1.3.0 das Feld $ makellos hält, solange sich der $ viewValue nicht ändert. Was ich tun musste $scope.myForm.myField.$pristine = false; $scope.myForm.myField.$setViewValue(...). Die Antwort unten, die field.$setDirty()in Angular 1.3.4 hinzugefügt wurde, scheint die bessere Lösung zu sein
Johann
4
Vielen Dank für Ihre Nachricht, dass Sie meinen Tag "bis 1.3.3. Ab 1.3.4 sollten Sie die neu exponierte API-Methode verwenden"
Ahmed Mahmoud
Benutzer rmag, und was ist mit Winkel 2?
user5260143
17

Sie müssen manuell eingestellt $dirtyauf trueund $pristineum falsefür das Feld. Wenn die Klassen in Ihrer Eingabe angezeigt werden sollen, müssen Sie Klassen manuell zum Element hinzufügen ng-dirtyund daraus entfernen ng-pristine. Sie können dies $setDirty()auf Formularebene verwenden, um all dies auf dem Formular selbst zu tun, jedoch nicht auf den Formulareingaben. Formulareingaben verfügen derzeit nicht über die $setDirty()von Ihnen erwähnten Formulareingaben .

Diese Antwort kann sich in Zukunft ändern, da sie $setDirty()zu den Eingaben hinzugefügt werden sollte. Dies erscheint logisch.

TheSharpieOne
quelle
3
$ setPristine () ist auf Eingabefeldebene, aber immer noch kein $ setDirty in 1.2.26 :-(
Sebastian
10

Wenn Sie Zugriff auf den NgModelController haben (Sie können nur über eine Direktive darauf zugreifen), können Sie aufrufen

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
quelle
Danke dir! Genau das, wonach ich gesucht habe.
Dreyln
10

Ich habe eine jsFiddle nur für Sie erstellt, die dieses Problem löst. Setzen Sie einfach $ dirty auf true, aber mit a wird $timeout 0es ausgeführt, nachdem DOM geladen wurde.

Finden Sie es hier: JsFiddle

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

Das hat bei mir funktioniert

$scope.form_name.field_name.$setDirty()
Shakirthow
quelle
5

Eine Hilfsfunktion für die Arbeit:

function setDirtyForm(form) {
    angular.forEach(form.$error, function(type) {
        angular.forEach(type, function(field) {
            field.$setDirty();
        });
    });
    return form;
}
Rodolfo Jorge Nemer Nogueira
quelle
Hey, ich habe das leider versehentlich abgelehnt. Wie kann ich es zurücksetzen? Also sag mir, dass ich das nicht tun kann, ohne dass die Antwort bearbeitet wird.
smk
Das funktioniert gut; Das Upvoting als Überprüfung auf 'form. $ error' stellt sicher, dass wir keine Felder 'verschmutzen', die der Benutzer nicht berührt hat, die aber gültig sind.
Sam T
Danke dir! Einfache und einfache Lösung. Könnte nicht das schnellste sein, aber es macht nichts Schweres, also spielt es imo wirklich keine Rolle. Gute Arbeit!
Jwanglof
4

Winkel 2

Für alle, die dasselbe in Angular 2 tun möchten, ist es sehr ähnlich, abgesehen davon, dass sie das Formular in den Griff bekommen

<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
quelle
3

Kleine zusätzliche Anmerkung zu @ rmags Antwort. Wenn Sie leere, aber erforderliche Felder haben, die Sie verschmutzen möchten, verwenden Sie Folgendes:

$scope.myForm.username.$setViewValue($scope.myForm.username.$viewValue !== undefined 
    ? $scope.myForm.username.$viewValue : '');
Fran Arant
quelle
Dies ist die Antwort, die mir endlich geholfen hat!
Kirk Liemohn
-1

Ich bin mir nicht sicher, warum Sie versuchen, die Felder als schmutzig zu markieren, aber ich befand mich in einer ähnlichen Situation, weil ich wollte, dass Validierungsfehler angezeigt werden, wenn jemand versucht, ein ungültiges Formular einzureichen. Am Ende habe ich jQuery verwendet, um die .ng-pristineKlassen-Tags zu entfernen und .ng-dirtyden entsprechenden Feldern Klassen-Tags hinzuzufügen . Beispielsweise:

$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
quelle
5
Da wir AngularJS bereits verwenden, scheint eine jQuery-Lösung übertrieben. Viele Leute bevorzugen es beispielsweise, jQuery nicht mit AngularJS zu verwenden.
StevenClontz