Как я могу получить валидаторы напрямую из formControl?

введите здесь описание изображения

введите здесь описание изображения

введите здесь описание изображения

У меня есть поле электронной почты, и я добавил два валидатора (обязательно, электронная почта), я хочу проверить статус проверки на input event, чтобы вызвать API, проверьте дозу члена моей системы, когда он действителен, если это invalid, не вызывайте API и не показывать сообщение об ошибке на странице.

Я покажу сообщение об ошибке в событии размытия (ввод электронной почты focusOut), сначала я использовал formControl.validator(formControl) для запуска валидаторов и проверки formControl.valid, я получил действительный статус успешно, но на странице будет отображаться сообщение об ошибке, потому что я подписался statsuChange чтобы показать сообщение об ошибке, когда статус равно invalid.

в настоящее время я сохраняю валидаторы в переменной и перехожу к initEmailChaingeEvent(), чтобы проверить статус проверки без события statusChange. Это может работать, но я думаю, что это не очень хороший способ, вот пример моей реализации:

живой пример

export class AppComponent {
  public sampleForm: FormGroup;

  @ViewChild('emailElm')
  emailElm: ElementRef;

  ngOnInit() {
    this.initForm();
  }

  initForm() {
    const emailValidtors = [
      Validators.required,
      Validators.email
    ]

    const emailFC = new FormControl(null, {
      validators: emailValidtors,
      updateOn: 'blur'
    });
    //
    this.sampleForm = new FormGroup({
      'email': emailFC
    });
    //
    this.initEmailChaingeEvent({
      emailFC: emailFC,
      validtors: emailValidtors
    });
    //
    this.sampleForm.valueChanges.subscribe((val) => {
      console.log('_blue event:valueChanges', val)
    });
    //
    this.initShowErrorMsgEvent({
      fc: emailFC
    });
  }

  private initEmailChaingeEvent(arg: {
    emailFC: FormControl,
    validtors: any[]
  }) {
    fromEvent(this.emailElm.nativeElement, 'input')
      .pipe(debounceTime(500))
      .subscribe((event: Event) => {
        const currentEmail = (event.target as HTMLInputElement).value;
        // check is valid
        // **quention** : how can I get validtors from fromcontrol self 
        // if I use  arg.emailFC.validator(arg.emailFC) to ehcek status , it will trigger oberservable in initShowErrorMsgEvent(),
        //  but I just want to got valid result , I don't want to show error msg on UI at this time

        for (const validator of arg.validtors) {
          const inValid = validator(arg.emailFC);
          if (inValid) {
            console.log('input event:invalid', currentEmail);
            return;
          }
        }
        // **do sometheng when all valid**
        console.log('input event:call API , email:',currentEmail );
      });
  }

  private initShowErrorMsgEvent(arg: {
    fc: FormControl,
  }) {
    arg.fc.statusChanges
      .subscribe((status) => {
        // console.log('status' , status);
        if (status === 'INVALID') {
          // show error msg....
          console.log('_show error msg by antoher component');
        }
      });
  }
}
<form [formGroup]="sampleForm">
  <input formControlName="email" #emailElm >
</form>


person Chunbin Li    schedule 01.06.2018    source источник
comment
Я обновил свой вопрос, я проверяю входное значение в событии ввода и показываю сообщение об ошибке в событии размытия, потому что я был установлен updateOn:blur' в FormControl, .valid или .invalid не будет запускаться в событии ввода   -  person Chunbin Li    schedule 01.06.2018
comment
Таким образом, вы хотите отправить форму в API, когда форма действительна автоматически?   -  person Andrew Junior Howard    schedule 04.06.2018
comment
когда поле электронной почты действительно, я хочу отправить его в API, чтобы проверить, является ли он членом моей системы   -  person Chunbin Li    schedule 04.06.2018
comment
Итак, вопрос в том, как сделать проверку электронной почты? Или просто отправить форму, когда она станет действительной?   -  person Andrew Junior Howard    schedule 04.06.2018
comment
когда пользователь вводит свой адрес электронной почты => проверьте с помощью моей проверки formcontrol => вызовите API, чтобы проверить дозу члена, если он действителен   -  person Chunbin Li    schedule 04.06.2018


Ответы (3)


Вы слишком усложнили задачу. Во-первых, объявите свою форму и управляйте валидаторами. Если вы составляете валидатор из списка валидаторов, они будут проверяться в порядке определения. Итак, сначала требуемый, затем «действительный адрес электронной почты», и, наконец, ваш пользовательский валидатор проверит, является ли он уникальным.

 ....
 this.emailForm = this.fb.group({
       emailAddress: [null, Validators.compose([Validators.required, Validators.email, uniqueEmailValidator()])]
 });
 ...

Затем вы создаете свой собственный валидатор для проверки электронной почты пользователя с помощью API. Дополнительная информация о пользовательских валидаторах: документы Angular

function uniqueEmailValidator(){
    ...
}
person Zsolt Tolvaly    schedule 07.06.2018
comment
предотвращает ли это решение запуск StatusChange для отображения сообщений об ошибках проверки? - person Chunbin Li; 07.06.2018
comment
Валидаторы проверяются в порядке определения, и следующий валидатор не проверяется, если текущий не работает. Первый раз. валидаторы проверяются на «размытие», если возникает ошибка, то при каждом нажатии клавиши. - person Zsolt Tolvaly; 08.06.2018
comment
Я создаю живой пример для этого решения, но оно не работает, что вы говорите: the validators checked in order of definition. я пытаюсь найти проверенный порядок в исходный код angular, но я так и не получил ничего. Мой код примера неверен? - person Chunbin Li; 09.06.2018
comment
Я опубликую рабочий пример позже на этой неделе. В последнее время у меня было много на голове, извините! - person Zsolt Tolvaly; 13.06.2018

Здесь многое происходит, над чем нужно поработать. Во-первых, я бы подписался на изменения formValue элемента управления вместо использования Observable для собственного элемента.

this.sampleForm.get('email').valueChanges.subscribe((event) => {
    // CODE IN HERE
}

ValueChanges — это свойство в formControl, которое создает событие при изменении значения. https://angular.io/api/forms/AbstractControl

Затем, чтобы получить доступ к валидаторам, вы можете просто проверить элемент управления формой, если он действителен.

this.sampleForm.get('email').valid();

Если какой-либо валидатор недействителен, это будет ложью, если все валидаторы действительны, это будет правда.

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

Судя по вашему комментарию, вам нужен канал debounceTime:

this.sampleForm.get('email').valueChanges
.pipe(debounceTime(500), distinctUntilChanged())
.subscribe((event) => {
    if (this.sampleForm.get('email').valid) {
         // Your API logic here
    }
}

DebounceTime в основном задерживает обработку события и отбрасывает все ожидающие события в очереди.

debounceTime задерживает значения, испускаемые исходным Observable, но отбрасывает предыдущие ожидающие отложенные выбросы, если новое значение поступает в исходный Observable. http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-debounceTime

person hugmungus    schedule 05.06.2018
comment
ответ хороший, но время триггера мне не нужно, как я уже говорил, я установил, что синее событие испускает valueChanges, но я хочу получить действительный результат для входного события и не запускать statusChange, потому что я не хочу показать сообщение об ошибке, если оно недействительно - person Chunbin Li; 05.06.2018
comment
@ChunbinLi: я не совсем понимаю, что вы говорите, поэтому прошу прощения, если говорю не то. Вам не нужно отображать сообщение об ошибке, и вам не нужно предпринимать какие-либо действия, пока элемент управления не станет действительным. Похоже, что вы ищете в своем комментарии канал debounceTime, я обновил свой ответ с учетом этой логики. - person hugmungus; 05.06.2018
comment
Я добавил изображение, чтобы описать его, у меня есть два события (размытие, ввод) в поле электронной почты, debounceTime не может проверить и не показывать сообщение в функции initEmailChaingeEvent() - person Chunbin Li; 06.06.2018
comment
@ChunbinLi, почему вы используете здесь onBlur, есть ли какая-то особая причина? - person hugmungus; 06.06.2018
comment
менеджер проекта хочет показать ошибку при переходе к другим полям, чтобы улучшить взаимодействие с пользователем - person Chunbin Li; 06.06.2018
comment
@ChunbinLi Я понимаю проблему, которую ты пытаешься решить, но не твой подход. Есть ли причина использовать onBlur вместо formChanges? - person hugmungus; 06.06.2018
comment
как использовать formChanges вместо OnBlur? - person Chunbin Li; 07.06.2018
comment
@ChunbinLi извините, я имел в виду подписку на valueChanges - person hugmungus; 07.06.2018
comment
Я установил updateOn: blue для formControl, поэтому valueChanges будет запускаться синим событием. - person Chunbin Li; 07.06.2018

спасибо, все дали мне больше идей, я исправил это с помощью свойства formControl, это мое измененное список:

  • только передавать значение валидаторам избегать триггера statusChange эмиттер

живой пример

private initEmailChaingeEvent(arg:{
   emailFC : FormControl,
   ....
}) {
  ...
  const inValid = arg.emailFC.validator({
      value: currentEmail
    }
    as any);
  ....
}

person Chunbin Li    schedule 11.06.2018