Angular 2: итерация по элементам управления реактивной формы

97

Я хотел бы, чтобы markAsDirtyвсе элементы управления внутри файла FormGroup.

Маркос Дж. К. Кичел
источник

Ответы:

199

Выяснилось, что Object.keysсправится с этим ..

    Object.keys(this.form.controls).forEach(key => {
      this.form.get(key).markAsDirty();
    });

Для Angular 8+ используйте следующее (на основе ответа Микеланджело):

    Object.keys(this.form.controls).forEach(key => {
      this.form.controls[key].markAsDirty();
    });
Маркос Дж. К. Кичел
источник
2
Когда я использую эту функцию в onSubmit, я получаю сообщение об ошибке. Cannot invoke an expression whose type lacks a call signature. Type 'AbstractControl' has no compatible call signatures.Кто-нибудь знает, почему?
maidi
1
Object.keys (this.registerForm.controls) .forEach (ключ => {this.registerForm.controls [ключ] .markAsDirty ();});
Foad
Когда я пробую Object.keys или даже "for in", я ничего не получаю. Тем не менее, если я console.log (form.controls), я могу ВИДЕТЬ все различные элементы управления формы, содержащиеся в объекте. Я сбит с толку.
Джейк Шейксуорт
Используя Angular 5, markAsDirty () / markAsTouched () не рекурсивно попадает ни в какие подгруппы форм. Я разбил приведенный выше код на рекурсивную функцию и вызвал ее в любых подгруппах форм. Работает лучше с текущим проектом пользовательского интерфейса Angular Material, если пользователь никогда не касается обязательного элемента, я вызываю его, когда пользователь пытается отправить форму, чтобы отметить любой в этой точке.
Роберт
3
Спасибо, что прочитали мой пост и обновили свой ответ. Официальные документы также устарели, поэтому мне пришлось выяснить это, печатая каждую строку ...
Микеланджело
56

Как бы то ни было, есть другой способ сделать это без использования магии Object.keys (...) :

for (const field in this.form.controls) { // 'field' is a string

  const control = this.form.get(field); // 'control' is a FormControl  

}
Ливиу Илеа
источник
как получить индекс цикла?
SVK
1
Для тех, кто использует TSLint, код работает, но TSLint жалуется, что «операторы for (... in ...) должны фильтроваться с помощью оператора if (forin)».
Йеннифер
1
указывает tslint, цитата из документации JavaScript для оператора for ... in stackoverflow.com/questions/40770425/…
Эгле Крейвайт
41

Принятый ответ верен для плоской конструкции, но не полностью отвечает на исходный вопрос. Веб-страница может потребовать вложенных FormGroups и FormArrays, и мы должны учитывать это, чтобы создать надежное решение.

public markControlsDirty(group: FormGroup | FormArray): void {
    Object.keys(group.controls).forEach((key: string) => {
        const abstractControl = group.controls[key];

        if (abstractControl instanceof FormGroup || abstractControl instanceof FormArray) {
            this.markControlsDirty(abstractControl);
        } else {
            abstractControl.markAsDirty();
        }
    });
}
Кинан Диггс
источник
instanceofвсегда будет работать после преобразования с помощью Typescript?
the-notable
@ the-notable instanceofне является ключевым словом, специфичным для TypeScript ( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ). И classтип данных тоже.
Кинан Диггс
8

Используя ответ @Marcos, я создал функцию, которую можно вызвать с передачей formGroup в качестве параметра, и она помечает все дочерние элементы управления formGroup как грязные, просто чтобы сделать их пригодными для использования из большего количества мест вокруг кода, например, поместив их внутри службы.

public touchAllFormFields(formGroup: FormGroup): void {
    Object.keys(formGroup.controls).forEach((key) => {
        formGroup.get(key).markAsDirty();
    });
}

Надеюсь, это поможет ;)

Хьюго
источник
Отлично! Добавлен в службу вместе с аналогичными функциями для clearValidators, untouch и т. Д. Может потребоваться добавить рекурсивную проверку для вложенных элементов управления, но пока это работает. Благодарность!
mc01
6

Похоже, эта get функция больше не работает для получения определенных значений в вашей форме в Angular 8, поэтому я решил ее на основе ответа @Liviu Ilea.

for (const field in this.myForm.controls) { // 'field' is a string
  console.log(this.myForm.controls[field].value);
}
Микеланджело
источник
Ты уверен? В документе API уже есть метод get для абстрактного элемента управления ( angular.io/api/forms/AbstractControl#get ). Я еще не перешел. Теперь я напуган (⊙_ ◎)
Алан Гросс
@AlanGrosz Да, я тоже это видел, когда переписывал его, но даже при печати всех строк в консоли я не мог найти никакого метода get для объекта. Думаю, документация уже позади. Удачной миграции!
Микеланджело
Я не думаю, что они удалили его, поработайте
Laszlo Sarvold
4

Это то, что у меня работает

private markFormGroupTouched(formGroup: FormGroup) {
  Object.keys(formGroup.controls).forEach((key) => {
    const control = formGroup.controls[key];
    control.markAsDirty();
    if ((control instanceof FormGroup)) {
      this.markFormGroupTouched(control);
    }
  });
}
оми-рыба
источник
1

Я создаю эту функцию, чтобы сделать это * У меня есть элемент управления с именем «порядок» и передаю ему индекс.

{"conditionGroups": [
   {
     "order": null,
     "conditions": []
   }
  ]
}


updateFormData() {
    const control = <FormArray>this.form.controls['conditionGroups'];  
    control.value.map((x,index)=>{
    x.order = index; 
 })
Жоау Маркос Сантос Тейшейра
источник