0

I want to send passwordAvailable request to server after sometime (3seconds) when the user starts typing. But it gets sent anyways. I have set debounceTime to 3 seconds, still nothing. This is my validator

validate = (control: AbstractControl): Observable<ValidationErrors> | null => {
        const value = control.value;

        return this.authService.passwordAvailable(value, this._username).pipe(
            debounceTime(3000),
            tap(
                ()=>console.log('hi')
            ),
            map(value => {        
            if (value == 'true') {
                return null;
            }

            return { matchNotFound: true };
            })
            
        );
    }

My Component.ts

constructor(private fb: FormBuilder,
    private authService: AuthService,
    private passwordValidators: PasswordValidators,
    ) {}

ngOnInit(): void {

    this.passwordValidators.setUsername(this.username);

    this.changePassForm = this.fb.group({
      oldPassword : [this.password, 
        Validators.required, 
        this.passwordValidators.validate
      ]
    });
    
  }

My Service

passwordAvailable(password: string, username: string): Observable<any>{
    let data = {password: password, username: username};
    return this.http.get<any>('url:check-password',{params: data});
  }

the service returns string as (true or false)

Please Help, thanks in advance

I even tried, using valueChanges, but service isnt even getting called here, this is what i tried

return control.valueChanges.pipe(
            debounceTime(3000),
            tap(()=>console.log('hi')),
            map((val) => {return this.authService.passwordAvailable(val, this._username)}),
            map((v: any) => {
                if (v == 'true') {
                    return null;
                }
    
                return { matchNotFound: true };
            })
        )
Shah Rukh
  • 291
  • 1
  • 10

2 Answers2

0

I changed the code to

return timer(3000).pipe(
            switchMap(() => {
                return this.authService.passwordAvailable(value, this._username).pipe(
                    tap(
                        ()=>console.log('hi')
                    ),
                    map(value => {        
                    if (value == 'true') {
                        return null;
                    }
        
                    return { matchNotFound: true };
                    })
                    
                );
            })
        )

Now api is getting hit after 3 seconds.

With DebounceTime, i tried changing it to

return control.valueChanges.pipe(
            debounceTime(2000),
            switchMap(value=>{
                return this.authService.passwordAvailable(value, this._username).pipe(
                    map(value => {        
                    if (value == 'true') {
                        return null;
                    }
        
                    return { matchNotFound: true };
                    })
                    
                );
            })
        )

But still no request sent, so timer was the only option left

Shah Rukh
  • 291
  • 1
  • 10
  • 1
    The debounceTime should be before the call to the httpclient. Problem with the http call is, is that it is a so called cold observable. Every time you call it you get a new observable instead of a reusable one. That's why the answer in the other comment shows the debounceTime being piped before the http call. – Silvermind Mar 28 '21 at 19:12
0

should be simply

this.control.valueChanges.pipe(
      debounceTime(300),
      switchMap(value=>{
        return this.authService.passwordAvailable(value, this._username)
      })
      ).subscribe(res=>{console.log(res)})

That's. you observer the control changes, but only emit a value if pass 300 miliseconds -debounceTime(300)-. But you don't want the result of change, you want return the value of the service.passwordAvailable -switchMap-

Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • I tried it and edited my own answer, but it still doesn't works, no request sent (unsubscribes) – Shah Rukh Mar 29 '21 at 07:55
  • remember you need create the subscription **after** you create the FormControl -if you has a FormGroup after create the formGroup and use `this.myForm.get('search').valueChanges.pipe(...)` – Eliseo Mar 29 '21 at 11:59