web-dev-qa-db-fra.com

Comment implémenter un temps d'anti-rebond dans un événement keyup dans Angular 6

Je crée une application angulaire qui recherche les étudiants à partir de l'API. Cela fonctionne bien, mais il appelle l'API chaque fois qu'une valeur d'entrée est modifiée. J'ai fait une recherche pour laquelle j'ai besoin de quelque chose appelé «rebond», mais je ne sais pas comment l'implémenter dans mon application.

App.component.html

    <div class="container">
  <h1 class="mt-5 mb-5 text-center">Student</h1>
<div class="form-group">
  <input  class="form-control form-control-lg" type="text" [(ngModel)]=q (keyup)=search() placeholder="Search student by id or firstname or lastname">
</div>
 <hr>
 <table class="table table-striped mt-5">
    <thead class="thead-dark">
      <tr>
        <th scope="col" class="text-center" style="width: 10%;">ID</th>
        <th scope="col" class="text-center" style="width: 30%;">Name</th>
       <th scope="col" style="width: 30%;">E-mail</th>
        <th scope="col" style="width: 30%;">Phone</th> 
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let result of results">
        <th scope="row">{{result.stu_id}}</th>
        <td>{{result.stu_fname}} {{result.stu_lname}}</td>
         <td>{{result.stu_email}}</td>
        <td>{{result.stu_phonenumber}}</td> 
      </tr>
    </tbody>
  </table>
</div>

App.component.ts

import { Component} from '@angular/core';
import { Http,Response } from '@angular/http';
import { Subject, Observable } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent  {


  results;
  q = '';

  constructor(private http:Http) {


  }


  search() {
    this.http.get("https://www.example.com/search/?q="+this.q)
    .subscribe(
      (res:Response) => {
          const studentResult = res.json();
          console.log(studentResult);
          if(studentResult.success) {
            this.results = studentResult.data;
          } else {
            this.results = [];
          }
      }
    )
  }
}

Capture d'écran Screenshot

J'ai essayé quelque chose comme ça mais c'est l'erreur La propriété debounceTime n'existe pas sur le type Subject <{}>

  mySubject = new Subject();
  constructor(private http:Http)  {
    this.mySubject
    .debounceTime(5000)
    .subscribe(val => {
      //do what you want
    });
  }

et cela ne fonctionne pas non plus. La propriété 'fromEvent' n'existe pas sur le type 'typeof Observable' 

    Observable.fromEvent<KeyboardEvent>(this.getNativeElement(this.term), 'keyup')

Alors, quelle est la bonne façon de mettre en œuvre cela? 

Je vous remercie.

13
user6770140

Dans le composant, vous pouvez faire quelque chose comme ça. Créer RxJS Subject, dans la méthode search qui est appelée le keyup événement, faites .next() sur cette Subject que vous avez créée Alors subscribe dans ngOnInit() sera debounce pendant 1 seconde, comme dans le code ci-dessous.

searchTextChanged = new Subject<string>();
constructor(private http:Http) {

}


ngOnInit(): void {
    this.subscription = this.searchTextChanged
        .debounceTime(1000)
        .distinctUntilChanged()
        .mergeMap(search => this.getValues())
        .subscribe(() => { });
}

getValues() {
    return this.http.get("https://www.example.com/search/?q="+this.q)
    .map(
      (res:Response) => {
          const studentResult = res.json();
          console.log(studentResult);
          if(studentResult.success) {
            this.results = studentResult.data;
          } else {
            this.results = [];
          }
      }
    )
}

search($event) {
    this.searchTextChanged.next($event.target.value);
}

Rxjs v6 comporte plusieurs modifications importantes, notamment la simplification des points d'importation pour les opérateurs. Essayez d’installer rxjs-compat, qui rajoute ces chemins d’importation jusqu’à ce que le code soit migré.

Importez les opérateurs nécessaires à partir de RxJS. Celles ci-dessous sont pour RxJS 5.x

import { Subject } from "rxjs/Subject";
import "rxjs/add/operator/debounceTime";
import "rxjs/add/operator/distinctUntilChanged";
import { Observable } from "rxjs/Observable";
import "rxjs/add/operator/mergeMap";
6

Si vous utilisez angular 6 et rxjs 6, essayez ceci:
Notez le .pipe(debounceTime(1000)) avant votre subscribe 

import { debounceTime } from 'rxjs/operators';


search() {
    this.http.get("https://www.example.com/search/?q="+this.q)
    .pipe(debounceTime(1000))
    .subscribe(
      (res:Response) => {
          const studentResult = res.json();
          console.log(studentResult);
          if(studentResult.success) {
            this.results = studentResult.data;
          } else {
            this.results = [];
          }
      }
    )
  }
2
Nadhir Falta

Vous pouvez aussi utiliser angular formControls pour lier le champ de recherche 

<input  class="form-control form-control-lg" 
type="text" [formControl]="searchField"
placeholder="Search student by id or firstname or lastname">

et utilisez valueChanges observable sur notre champ de recherche pour réagir aux modifications du champ de recherche de votre App.component.ts fichier.

searchField: FormControl; 

ngOnInit() {
    this.searchField.valueChanges
      .debounceTime(5000) 
      .subscribe(term => {
    // call your service endpoint.
      });
}

vous pouvez éventuellement utiliser distinctUntilChanged (qui ne publie dans son flux de sortie que si la valeur publiée est différente de la précédente)

searchField: FormControl; 

ngOnInit() {
    this.searchField.valueChanges
      .debounceTime(5000) 
     .distinctUntilChanged()
     .subscribe(term => {
            // call your service endpoint.
      });
}
2
Jayampathy Wijesena

Pour tous ceux qui rencontrent cela dans une version plus récente de angular (et rxjs).

Le nouveau Rxjs a des opérateurs canalisables et ils peuvent être utilisés comme ceci (à partir du code de réponses accepté)

ngOnInit() {
 this.subscription = this.searchTextChanged.pipe(
   debounceTime(1000),
   distinctUntilChanged(),
   mergeMap(search => this.getValues())
  ).subscribe((res) => {
    console.log(res);
  });
1
Pautomagi

user.component.html

   <input type="text" #userNameRef class="form-control"  name="userName" >  <!-- template-driven -->
 <form [formGroup]="regiForm"> 
      email: <input formControlName="emailId"> <!-- formControl -->
    </form>

user.component.ts

       import { fromEvent } from 'rxjs';
       import { switchMap,debounceTime, map } from 'rxjs/operators';


        @Component({
          selector: 'app-user',
          templateUrl: './user.component.html',
          styleUrls: ['./user.component.css']
        })
        export class UserComponent implements OnInit {

          constructor(private userService : UserService) { }


             @ViewChild('userNameRef') userNameRef : ElementRef;

             emailId = new FormControl(); 
   regiForm: FormGroup = this.formBuilder.group({
      emailId: this.bookId
   });   

             ngOnInit() {

                    fromEvent(this.userNameRef.nativeElement,"keyup").pipe(
                    debounceTime(3000),
                    map((userName : any) =>userName.target.value )
                  ).subscribe(res =>{
                    console.log("User Name is :"+ res);

                  } );
    //--------------For HTTP Call------------------

                  fromEvent(this.userNameRef.nativeElement,"keyup").pipe(
                    debounceTime(3000),
                    switchMap((userName : any) =>{
                   return this.userService.search(userName.target.value)
                 })
                  ).subscribe(res =>{
                    console.log("User Name is :"+ res);

                  } );



----------
                // For formControl 

                  this.emailId.valueChanges.pipe(
                  debounceTime(3000),
                  switchMap(emailid => {
                         console.log(emailid);
                        return this.userService.search(emailid);
                        })
                         ).subscribe(res => {
                               console.log(res);
                                    });


            }

* Remarque: assurez-vous que votre élément d'entrée n'est pas présent dans ngIf Block.

0
SHIVA