How to use debounceTime in an angular component?

前端 未结 2 1135
深忆病人
深忆病人 2020-12-19 12:30

My requirement is to perform reactive form field validations in such a way that the error messages are displayed only after the user stops typing.

How can I accompli

相关标签:
2条回答
  • 2020-12-19 12:50

    The (or at least a) way to get this to work is to dynamically remove and add your validators as you go.

    On your input(s), use a keydown binding that will strip away validators when the user starts to type, and a keyup binding that will run through a debounceTime pipe and then reapply the validators (but only after the specified debounce time has passed).

    Code here:

    import { Component, OnInit } from '@angular/core';
    import { FormBuilder, FormGroup, Validators } from '@angular/forms';
    import { Subject } from 'rxjs';
    import { debounceTime } from 'rxjs/operators';
    
    @Component({
      selector: 'form-component',
      template: `
        <form [formGroup]="formGroup">
          <input type="text" formControlName="name" (keyup)="onKeyUp()" (keydown)="onKeyDown()" [ngClass]="{ 'invalid': formGroup.controls.name.invalid }">
        </form>
      `,
      styles: [
        '.invalid { border-color: red; color: red; }'
      ]
    })
    export class FormComponent implements OnInit {
    
      formGroup: FormGroup;
      subject: Subject<any> = new Subject();
    
      constructor(private formBuilder: FormBuilder) {}
    
      ngOnInit(): void {
        this.formGroup = this.formBuilder.group({
          name: [ '' ]
        });
    
        // Subscribe to the subject, which is triggered with each keyup
        // When the debounce time has passed, we add a validator and update the form control to check validity
        this.subject
          .pipe(debounceTime(500))
          .subscribe(() => {
              this.formGroup.controls.name.setValidators([ Validators.minLength(5) ]);
              this.formGroup.controls.name.updateValueAndValidity();
            }
          );
      }
    
      onKeyUp(): void {
        this.subject.next();
      }
    
      onKeyDown(): void {
        // When the user starts to type, remove the validator
        this.formGroup.controls.name.clearValidators();
      }
    
    }
    

    And StackBlitz here: https://stackblitz.com/edit/debounce-validator

    0 讨论(0)
  • 2020-12-19 13:11

    debounceTime waits for the time period mentioned and then calls the subscribe method. e.g; debounceTime(1000) will wait for 1 second. It is implemented through pipes.

    this can be added to any subscribe method. Following is the working example

    import { Component, OnInit } from '@angular/core';
    import { Validators, AbstractControl } from '@angular/forms';
    import { debounceTime } from 'rxjs/operators';
    
    // dynamic forms
    import { FormGroup, FormControl, FormBuilder } from '@angular/forms';
    
    
    @Component({
        selector: 'app-customer-form',
        templateUrl: './customer-form.component.html',
    })
    export class CustomerFormComponent implements OnInit {
    
        emailMessage : string;
    
        private validationMessages = {
            required: "Email field is required",
            email: "Please enter a valid Email"
        }
    
        customerForm: FormGroup;
    
        customer = new Customer();
    
        constructor(private fb: FormBuilder) { }
    
        ngOnInit() {
            this.customerForm = this.fb.group({
                emailAddress: ['',
                    [
                        Validators.required,
                        Validators.email
                    ]
                ]
            })
    
            const emailControl = this.customerForm.get('emailAddress');
            emailControl.valueChanges.pipe( debounceTime(1000) ).subscribe(
                value => this.setEmailMessage(emailControl)
            )
        }
    
        setEmailMessage( c: AbstractControl ) : void {
            this.emailMessage = '';
    
            if ( (c.touched || c.dirty) && c.errors ) {
                this.emailMessage = Object.keys(c.errors).map( key => this.validationMessages[key]).join(' ');
            }
    
        }
    
    }
    

    in your template

    <input 
        class="form-control"
        id="emailId" type="email"
        placeholder="Email (required)"
        formControlName="emailAddress"
        [ngClass]="{ 'is-invalid': emailMessage }"/>
        <span class="invalid-feedback">
        {{ emailMessage }}
        </span>
    
    0 讨论(0)
提交回复
热议问题