Angular.js программно устанавливает грязное поле формы

105

Я программно обновить некоторые поля на моей форме со значением , и я хотел бы установить состояние поля в $dirty. Сделать что-то вроде:

$scope.myForm.username.$dirty = true; похоже, не работает.

Есть метод, $setPristineкоторый я могу использовать для сброса состояния поля, но его нет $setDirty?

Так как же это сделать?

Я видел этот пост https://groups.google.com/forum/#!topic/angular/NQKGAFlsln4, но не могу найти $setDirtyметод. Я использую Angular версию 1.1.5.

super9
источник
может быть вам просто нужно установить какое-то (по умолчанию) значение?
Чернов
3
Метод $ setDirty задокументирован здесь: docs.angularjs.org/api/ng.directive:form.FormController
Дэвид Лин
2
Кажется, на уровне формы. Мне нужен $setDirtyполевой уровень.
super9 06
здесь нет ничего невозможного, но одним из возможных, но довольно хакерских решений было бы выяснить, какой прослушиватель событий angular использует для привязки к этому типу поля, и запустить этот прослушиватель вручную сразу после обновления. </uglyHack>
bguiz 06
Я думал о программном изменении класса, но это не изменит состояние поля формы
должным

Ответы:

51

Начиная с AngularJS 1.3.4 вы можете использовать $setDirty()поля ( источник ). Например, для каждого поля с ошибкой, помеченного как обязательное, вы можете сделать следующее:

angular.forEach($scope.form.$error.required, function(field) {
    field.$setDirty();
});
Матеуш Расиньски
источник
87

В вашем случае $scope.myForm.username.$setViewValue($scope.myForm.username.$viewValue);трюк делает свое дело - он загрязняет форму и поле и добавляет соответствующие классы CSS.

Если честно, я нашел это решение в новом посте в теме по ссылке из вашего вопроса. У меня это сработало отлично, поэтому я помещаю это здесь как отдельный ответ, чтобы его было легче найти.

РЕДАКТИРОВАТЬ:

Вышеупомянутое решение лучше всего подходит для версии Angular до 1.3.3. Начиная с 1.3.4 вы должны использовать недавно открытый метод API $setDirty()из ngModel.NgModelController.

rmag
источник
Мне показалось, что это изменилось между Angular 1.3.0-beta5 и 1.3.0, где 1.3.0 сохраняет поле $ нетронутым, пока $ viewValue не изменилось. Я должен был сделать $scope.myForm.myField.$pristine = false; $scope.myForm.myField.$setViewValue(...). Похоже, что ответ ниже, в котором говорится, что field.$setDirty()было добавлено в Angular 1.3.4, будет лучшим решением
Иоганн
4
Спасибо за вашу заметку, вы спасли мне день «до 1.3.3. Начиная с 1.3.4 вы должны использовать недавно открытый метод API»
Ахмед Махмуд
user rmag, а как насчет angular 2?
user5260143
17

вам придется вручную установить $dirtyзначение trueи $pristineзначение falseдля поля. Если вы хотите, чтобы классы отображались на вашем вводе, вам придется вручную добавлять ng-dirtyи удалять ng-pristineклассы из элемента. Вы можете использовать $setDirty()на уровне формы, чтобы сделать все это в самой форме, но не на входах формы, входы формы в настоящее время не имеют, $setDirty()как вы упомянули.

Этот ответ может измениться в будущем, поскольку они должны добавляться $setDirty()к входным данным, что кажется логичным.

TheSharpieOne
источник
3
$ setPristine () находится на уровне поля ввода, но по-прежнему отсутствует $ setDirty в 1.2.26 :-(
Себастьян
10

Если у вас есть доступ к NgModelController (вы можете получить доступ к нему только из директивы), вы можете вызвать

ngModel.$setViewValue("your new view value");
// or to keep the view value the same and just change it to dirty
ngModel.$setViewValue(ngModel.$viewValue);
Маршалл Брекка
источник
Спасибо! Именно то, что я искал.
dreyln
10

Специально для вас создан jsFiddle, который решает эту проблему. просто установите для $ dirty значение true, но $timeout 0так, чтобы он запускался после загрузки DOM.

Найдите здесь: JsFiddle

$timeout(function () {
  $scope.form.uName.$dirty = true;
}, 0);
Гилад Пелег
источник
6

Это то, что сработало для меня

$scope.form_name.field_name.$setDirty()
Shakirthow
источник
5

Вспомогательная функция для выполнения работы:

function setDirtyForm(form) {
    angular.forEach(form.$error, function(type) {
        angular.forEach(type, function(field) {
            field.$setDirty();
        });
    });
    return form;
}
Родольфо Хорхе Немер Ногейра
источник
Привет, я, к сожалению, случайно проголосовал против. Как мне отменить это. Так что говоря мне, что я не могу сделать это без редактирования ответа ..
smk
Это хорошо работает; Голосование за как проверку для 'form. $ error' гарантирует, что мы не «искажаем» поля, которые пользователь не касался, но которые действительны.
Sam T
Спасибо! Легкое и простое решение. Может быть, не самый быстрый, но он не делает ничего тяжелого, так что на самом деле это не имеет значения. Хорошая работа!
jwanglof
4

Угловой 2

Для всех, кто хочет сделать то же самое в Angular 2, он очень похож, кроме получения формы

<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
источник
3

Небольшое примечание к ответу @rmag. Если у вас есть пустые, но обязательные поля, которые вы хотите испортить, используйте это:

$scope.myForm.username.$setViewValue($scope.myForm.username.$viewValue !== undefined 
    ? $scope.myForm.username.$viewValue : '');
Фрэн Арант
источник
Это ответ, который мне наконец помог!
Kirk Liemohn
-1

Я не совсем уверен, почему вы пытаетесь пометить поля как грязные, но я оказался в аналогичной ситуации, потому что хотел, чтобы ошибки проверки появлялись, когда кто-то пытался отправить недопустимую форму. В итоге я использовал jQuery для удаления .ng-pristineтегов классов и добавления .ng-dirtyтегов классов в соответствующие поля. Например:

$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();
    }
}
Бен Гарольд
источник
5
Учитывая, что мы уже используем AngularJS, решение jQuery кажется излишним. Многие люди, например, предпочитают не использовать jQuery с AngularJS.
StevenClontz