Angular2 — свойства реактивной формы

У меня есть реактивная форма, которую я создаю для своего компонента. Существует около 5 необязательных входов выбора, которые пользователь может выбрать для использования и выбора критериев.

Я пытаюсь реализовать некоторые сообщения об ошибках, но не могу ничего понять.

<span *ngIf="importForm.invalid && importForm.touched" class="help-block text-danger">Please select one piece of data to filter by.</span>

Поскольку все поля являются параметрами, но требуется хотя бы одно, как я могу проверить, что одно из полей было touched до отображения недопустимого сообщения?

Компонент:

/**
 * Render the form in the UI to allow
 *
 * @memberof FilterSearchComponent
 */
renderForm() {
    this.importForm = this.fb.group({
        costCenter: [[]],
        area: [[]],
        silo: [[]],
        department: [[]],
        location: [[]],
        segment: [[]],
        role: [[]]
    },
        {
            validator: (formGroup: FormGroup) => {
                return this.validateFilter(formGroup);
            }
        });
}

/**
 * Checks to see that at least one of the filter
 * options have been filled out prior to searching
 * for employees.
 *
 * @param formGroup
 */
validateFilter(formgroup: FormGroup) {
    if (formgroup.controls["costCenter"].value.length ||
        formgroup.controls["area"].value.length ||
        formgroup.controls["silo"].value.length ||
        formgroup.controls["department"].value.length ||
        formgroup.controls["location"].value.length ||
        formgroup.controls["segment"].value.length ||
        formgroup.controls["role"].value.length
    ) {
        return null;
    } else {
        return { noFilterOptions: true };
    }
}

Я действительно не хочу делать оператор || для каждого из элементов управления в моем HTML, если я могу помочь.

Существуют ли какие-либо другие способы, которыми я могу увидеть, был ли затронут ЛЮБОЙ ввод в моей форме, вместо того, чтобы указывать тот, который я хочу посмотреть на индивидуальной основе?


person SBB    schedule 25.07.2017    source источник
comment
У меня нет ничего удобного, чтобы проверить это и опубликовать в качестве ответа, но FormGroup и FormControl (и, возможно, FormArray) наследуются от AbstractControl, у которого есть метод touched(). Вы должны иметь возможность вызвать этот метод для FormGroup и узнать, был ли затронут он или какой-либо из дочерних FormControls... Вы также можете использовать свойство value FormControl и перебирать значения без необходимости знать имена элементов управления формы...   -  person Sunil D.    schedule 25.07.2017
comment
Как обстояли дела с ответами, соответствовали ли они вашему требованию? :)   -  person AJT82    schedule 01.08.2017


Ответы (2)


Здесь я хотел бы удалить пользовательский валидатор, как он есть сейчас. Он будет срабатывать всякий раз, когда что-то происходит с вашей формой, которая, как я полагаю, имеет больше значений, чем просто выбор. Это будет срабатывать ненужно часто.

Вместо этого я буду слушать событие click или что-то подобное на ваш выбор. Следующий пример, вероятно, можно было бы улучшить (?), но, по крайней мере, у вас есть с чем работать, если вы решите сделать это следующим образом.

Здесь я предполагаю, что вместо использования массива для всех select в форме вы просто хотите получить одно значение, для которого подойдет один FormControl:

this.importForm = this.fb.group({
  optionals: this.fb.group({
    costCenter: [''],
    area: ['']        
  })
});

После создания формы мне нравится сохранять различные элементы управления в переменных, чтобы избежать длинного кода с путями свойств. Я бы повторил свойства объекта в группе форм optionals, сохранил их в массиве, который затем мы можем проверить, установлено ли хотя бы одно значение:

this.optionalCtrl = this.importForm.controls.optionals

В шаблоне, ну, здесь вам нужно будет установить событие клика для всех выборок отдельно...

<select formControlName="costCenter" (click)="checkOptionals()">

Затем в checkOptionals будет выполняться итерация свойств объекта в группе форм optionals и проверка того, что хотя бы одно свойство имеет значение, отличное от пустой строки. Исходя из этого, мы устанавливаем пользовательскую ошибку в группу форм или, альтернативно, очищаем ее.

checkOptionals() {
  for(let key in this.optionalCtrl.controls ) {
    if(this.optionalCtrl.controls[key].value != '') {
      this.optionalCtrl.clearValidators()
      // this.optionalCtrl.updateValueAndValidity()
      break;
    } else {
      this.optionalCtrl.setErrors({"noFilterOptions": true})
    }
  }

} }

Возможно, вам придется позвонить updateValueAndValidity после установки ошибки. Затем в шаблоне вы просто показываете эту ошибку, когда это правда:

<div *ngIf="optionalCtrl.hasError('noFilterOptions')">
  choose at least one to filter by
</div>

ДЕМО: http://plnkr.co/edit/VbtsYST0KAUqe8BRQlmt?p=preview

person AJT82    schedule 26.07.2017

То, что у вас есть, должно работать:

<span *ngIf="importForm.invalid && importForm.touched" class="help-block text-danger">Please select one piece of data to filter by.</span>

Свойство touched формы должно быть установлено, если касались любого из элементов управления в форме. Я так понимаю он не работает? Как это не работает?

Коснулся -> пользователь вошел и вышел из элемента ввода. Он ничего не говорит о том, ввел ли пользователь что-то в элемент ввода.

Если вы хотите знать, обновил ли пользователь значение одного из элементов ввода, используйте вместо этого dirty:

<span *ngIf="importForm.invalid && importForm.dirty" 
      class="help-block text-danger">
   Please select one piece of data to filter by.
</span>
person DeborahK    schedule 25.07.2017
comment
Что если вход select открывается и закрывается без выбора значения, считается ли это touched ? - person SBB; 25.07.2017
comment
Я бы предположил, что после этого пользователь покинет поле. Но вы можете запустить небольшой тест для подтверждения. - person DeborahK; 25.07.2017
comment
Странно, расширение, а затем закрытие раскрывающегося списка не вызывает этого при прикосновении. Если я выберу значение, а затем удалю значение, оно будет работать нормально. - person SBB; 25.07.2017
comment
Даже если потом уйти с поля? Интересно. Не то, что я бы предположил. Кажется, нажатие на значок раскрывающегося списка не считается входом в поле? - person DeborahK; 25.07.2017