Angular реактивные формы - проверка на размытие, но обновление модели при наборе - PullRequest
0 голосов
/ 01 апреля 2020

У меня есть ситуация с использованием реактивных форм и вводимого текста.

Мне нужно:

  1. в качестве пользовательских типов, предложить список, основанный на том, что было напечатано (I ' m используя ngx bootstrap typeahead);
  2. проверяет поле ввода только тогда, когда пользователь теряет фокус ввода.

Чтобы выполнить проверку ввода только тогда, когда пользователь покидает В поле ввода я добавил "updateOn: 'blur" "к параметрам проверки. Проблема заключается в том, что это влияет не только на то, когда выполняется проверка, но также и на то, когда модель будет обновлена. При 'размытии' модель обновляется только тогда, когда пользователь оставляет введенный текст, и, как следствие, список предложений не работает как пользовательские типы, как это должно быть, потому что модель не обновляется.

Я добавил пример в stackblitz .

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

Спасибо .

Ответы [ 2 ]

1 голос
/ 01 апреля 2020

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

custom-input.component.ts

@Component({
  selector: 'app-custom-input',
  template: `
    <p>
      custom input: 
      <input
        #i
        (input)="onChangeFn($event.target.value)" 
        (blur)="onTouchedFn()"
        type="text"
        [formControl]="input"
      >
    </p>

    <p>
    inner input value: {{ i.value }}
    </p>
  `,
  providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: CustomInputComponent, multi: true, } ]
})
export class CustomInputComponent implements OnInit, ControlValueAccessor {
  input: FormControl;
  onTouchedFn: Function;
  onChangeFn: Function;

  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.input = this.fb.control('');
  }

  registerOnChange (fn) {
    this.onChangeFn = fn;
  }

  registerOnTouched (fn) {
    this.onTouchedFn = fn;
  }

  writeValue (v) { this.input.setValue(v); }
}

parent.component.ts

  specialInput = new FormControl('', { updateOn: 'blur', validators: Validators.required });

parent.component. html

<app-custom-input [formControl]="specialInput"></app-custom-input>

<p>
  Special input validation status: {{ specialInput.valid || 'false' }}
</p>

Вы можете думать о своих элементах управления формой как о tree структура:

FG - FormGroup; FC - FormControl

    FG
 /  |  \
FC  FC  FC

В вашем случае, когда FC изменил свое значение (например, из-за ввода пользователя), все его потомки (в данном случае FG, но в сложный пример, их может быть и больше), а также придется обновлять независимо от их значения updateOn.

Следуя этому подходу, это дерево теперь будет выглядеть так (при условии, что последний FC построен следующим образом):

    FG
 /  |  \_________
FC  FC | FC      |
       |   \     |
       |    FC <-- the `input` elem. in the custom component
       |_________|

В результате значение будет обновляться onChange во внутреннем FC и onBlur в external FC.

StackBlitz .

Кроме того, если вы хотите узнать больше о формах, я рекомендую проверить эта статья .

0 голосов
/ 02 апреля 2020

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

При создании формы я больше не добавляю валидатор и добавил выполняемую функцию в случае размытия, которые добавляют валидатор в FormControl, проверяют и удаляют валидатор;

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

Итак, это будет создание формы:

const myInput = new FormControl('', validators: Validators.required })

Это html

<input type="text" (blur)="validate()" formControlName="myInput">

И это функция проверки

  validate(): void {
    this.myInput.setAsyncValidators(this.myAsyncValidator());
    this.myInput.updateValueAndValidity();
    this.myInput.clearAsyncValidators();
  }
...