Angular.js définissant par programme un champ de formulaire sur dirty

105

Je mets à jour par programme certains des champs de mon formulaire avec une valeur et je voudrais définir l'état du champ sur $dirty. Faire quelque chose comme:

$scope.myForm.username.$dirty = true; ne semble pas fonctionner.

Il existe une méthode $setPristineque je peux utiliser pour réinitialiser l'état du champ mais il n'y a pas de $setDirtyméthode?

Alors, comment s'y prend-on?

J'ai vu ce post https://groups.google.com/forum/#!topic/angular/NQKGAFlsln4 mais je n'arrive pas à trouver la $setDirtyméthode. J'utilise la version Angular 1.1.5.

super9
la source
peut-être avez-vous juste besoin de définir une valeur (par défaut)?
Cherniv
3
La méthode $ setDirty est documentée ici: docs.angularjs.org/api/ng.directive:form.FormController
David Lin
2
Le semble être au niveau de la forme. J'ai besoin d'un $setDirtysur le terrain.
super9
aller sur une branche ici, mais une solution possible, mais plutôt hacky, à cela serait de découvrir quel écouteur d'événement angular utilise pour se lier à ce type de champ, et de déclencher cet auditeur manuellement immédiatement après la mise à jour. </uglyHack>
bguiz
Je pensais changer la classe par programme mais cela ne changera pas l'état du champ de formulaire de la manière correcte que j'aurais pensé ...
super9

Réponses:

51

Depuis AngularJS 1.3.4, vous pouvez utiliser $setDirty()sur les champs ( source ). Par exemple, pour chaque champ avec erreur et marqué comme requis, vous pouvez effectuer les opérations suivantes:

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

Dans votre cas, $scope.myForm.username.$setViewValue($scope.myForm.username.$viewValue);fait l'affaire - cela rend le formulaire et le champ sales et ajoute les classes CSS appropriées.

Pour être honnête, j'ai trouvé cette solution dans un nouveau post dans le sujet à partir du lien de votre question. Cela a parfaitement fonctionné pour moi, donc je mets cela ici comme une réponse autonome pour faciliter la recherche.

ÉDITER:

La solution ci-dessus fonctionne mieux pour la version angulaire jusqu'à 1.3.3. À partir de la version 1.3.4, vous devez utiliser la méthode API nouvellement exposée $setDirty()de ngModel.NgModelController.

rmag
la source
Cela a semblé changer pour moi entre Angular 1.3.0-beta5 et 1.3.0, où 1.3.0 garde le champ $ pristine tant que $ viewValue n'a pas changé. Je devais faire $scope.myForm.myField.$pristine = false; $scope.myForm.myField.$setViewValue(...). On dirait que la réponse ci-dessous indiquant que cela a field.$setDirty()été ajouté dans Angular 1.3.4 sera la meilleure solution
Johann
4
Merci pour votre note que vous avez sauvé ma journée "jusqu'à 1.3.3. À partir de 1.3.4, vous devriez utiliser la méthode API nouvellement exposée"
Ahmed Mahmoud
utilisateur rmag, et qu'en est-il angulaire 2?
user5260143
17

vous devrez définir manuellement $dirtysur trueet $pristinesur falsepour le champ. Si vous voulez que les classes apparaissent sur votre entrée, vous devrez ajouter ng-dirtyet supprimer manuellement des ng-pristineclasses de l'élément. Vous pouvez utiliser $setDirty()au niveau du formulaire pour faire tout cela sur le formulaire lui-même, mais pas les entrées de formulaire, les entrées de formulaire n'ont pas actuellement $setDirty()comme vous l'avez mentionné.

Cette réponse peut changer dans le futur car ils devraient s'ajouter $setDirty()aux entrées, semble logique.

TheSharpieOne
la source
3
$ setPristine () est au niveau du champ d'entrée mais toujours pas de $ setDirty en 1.2.26 :-(
Sebastian
10

Si vous avez accès au NgModelController (vous ne pouvez y accéder qu'à partir d'une directive), vous pouvez appeler

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
la source
Je vous remercie! Exactement ce que je cherchais.
dreyln
10

Faites un jsFiddle juste pour vous qui résout ce problème. définissez simplement $ dirty sur true, mais avec un $timeout 0so il s'exécute après le chargement du DOM.

Trouvez-le ici: JsFiddle

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

C'est ce qui a fonctionné pour moi

$scope.form_name.field_name.$setDirty()
shakirthow
la source
5

Une fonction d'assistance pour faire le travail:

function setDirtyForm(form) {
    angular.forEach(form.$error, function(type) {
        angular.forEach(type, function(field) {
            field.$setDirty();
        });
    });
    return form;
}
Rodolfo Jorge Nemer Nogueira
la source
Hé, j'ai malheureusement voté à la baisse par accident. Comment puis-je le rétablir. Alors en me disant que je ne peux pas faire cela sans que la réponse ne soit modifiée ..
smk
Cela fonctionne bien; upvoting comme vérification de «form. $ error» garantit que nous ne «salissons» pas les champs que l'utilisateur n'a pas touchés, mais qui sont valides.
Sam T
Je vous remercie! Solution simple et simple. Ce n'est peut-être pas le plus rapide, mais il ne fait rien de lourd donc ça n'a vraiment pas d'importance pour moi. Bon travail!
jwanglof
4

Angulaire 2

Pour tous ceux qui cherchent à faire la même chose dans Angular 2, c'est très similaire, mis à part la prise en main du formulaire

<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
la source
3

Petite note supplémentaire à la réponse de @ rmag. Si vous avez des champs vides mais obligatoires que vous souhaitez modifier, utilisez ceci:

$scope.myForm.username.$setViewValue($scope.myForm.username.$viewValue !== undefined 
    ? $scope.myForm.username.$viewValue : '');
Fran Arant
la source
C'est la réponse qui m'a finalement aidé!
Kirk Liemohn le
-1

Je ne sais pas exactement pourquoi vous essayez de marquer les champs comme sales, mais je me suis retrouvé dans une situation similaire parce que je voulais que des erreurs de validation apparaissent lorsque quelqu'un a tenté de soumettre un formulaire invalide. J'ai fini par utiliser jQuery pour supprimer les .ng-pristinebalises de classe et ajouter .ng-dirtydes balises de classe aux champs appropriés. Par exemple:

$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
la source
5
Étant donné que nous utilisons déjà AngularJS, une solution jQuery semble exagérée. De nombreuses personnes préfèrent ne pas utiliser jQuery avec AngularJS, par exemple.
StevenClontz