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 = [];
}
}
)
}
}
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.
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";
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 = [];
}
}
)
}
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.
});
}
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);
});
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.