如何完成 angular observable before value changes 检查?
How to finish angular observable before value changes check?
我正在创建类似于 Angular 自动完成的搜索栏,但我无法及时获取我的数组。
import { Component, OnInit } from '@angular/core';
import { IngredientService } from '../ingredients-shared/ingredient-service.service';
import { Ingredient } from '../ingredients-models/ingredient';
import { FormControl } from '@angular/forms';
import { Observable } from 'rxjs';
import {map, startWith} from 'rxjs/operators';
@Component({
selector: 'app-list-ingredients',
templateUrl: './list-ingredients.component.html',
styleUrls: ['./list-ingredients.component.css']
})
export class ListIngredientsComponent implements OnInit {
options: string[] = ['Angular', 'React', 'Vue'];
mylist: Ingredient[];
myControl = new FormControl();
filteredOptions: Observable<Ingredient[]>;
constructor(public ingredientService: IngredientService) { }
ngOnInit() {
this.ingredientService.getAllIngredients().subscribe( (ingredients: Ingredient[]) => {
this.mylist = ingredients
});
this.filteredOptions = this.myControl.valueChanges.pipe(
startWith(''),
map(
value =>
this._filter(value))
);
}
private _filter(value: string): Ingredient[] {
console.log(value)
const filterValue = value.toLowerCase();
return this.mylist.filter(ingredient => ingredient.ingredient_name.toLowerCase().includes(filterValue));
}
displayIngredientName(subject: Ingredient){
return subject ? subject.ingredient_name : undefined
}
}
如您所见,我需要先填充 mylist,然后再检查表单中的值更改,但我不知道如何提前完成。
我尝试使用 async/await 但我不想在 ngOnInit 中使用异步。我还在订阅中插入了表单更改,但当然这只会发生一次,所以它不会起作用。
有什么建议吗?谢谢
编辑:这是 HTML:
<form>
<mat-form-field>
<input type="text" matInput [matAutocomplete]="auto" [formControl]="myControl"/>
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayIngredientName">
<mat-option *ngFor="let ingredient of filteredList$ | async" [value]="ingredient" >
{{ingredient.ingredient_name}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</form>
您需要将两个 observable 组合成单个流,因为它们相互依赖。用户可以在加载数据之前开始键入,在加载数据之前输入的方法搜索值将被忽略。
你可以这样实现:
const ingredients$ = this.ingredientService.getAllIngredients();
const searchValues$ = this.myControl.valueChanges.pipe(startWith(''), map(val => val.toLowerCase()));
const filteredList$ = combineLatest(ingredients$, searchValues$)
.pipe(map(([list, searchVal]) => list.filter(item => item.ingredient_name.toLowerCase().includes(searchVal))));
然后只需在模板中使用异步管道即可。并且不要忘记 OnPush 变化检测。使用 debounceTime 来限制快速输入的搜索操作也是个好主意。
我正在创建类似于 Angular 自动完成的搜索栏,但我无法及时获取我的数组。
import { Component, OnInit } from '@angular/core';
import { IngredientService } from '../ingredients-shared/ingredient-service.service';
import { Ingredient } from '../ingredients-models/ingredient';
import { FormControl } from '@angular/forms';
import { Observable } from 'rxjs';
import {map, startWith} from 'rxjs/operators';
@Component({
selector: 'app-list-ingredients',
templateUrl: './list-ingredients.component.html',
styleUrls: ['./list-ingredients.component.css']
})
export class ListIngredientsComponent implements OnInit {
options: string[] = ['Angular', 'React', 'Vue'];
mylist: Ingredient[];
myControl = new FormControl();
filteredOptions: Observable<Ingredient[]>;
constructor(public ingredientService: IngredientService) { }
ngOnInit() {
this.ingredientService.getAllIngredients().subscribe( (ingredients: Ingredient[]) => {
this.mylist = ingredients
});
this.filteredOptions = this.myControl.valueChanges.pipe(
startWith(''),
map(
value =>
this._filter(value))
);
}
private _filter(value: string): Ingredient[] {
console.log(value)
const filterValue = value.toLowerCase();
return this.mylist.filter(ingredient => ingredient.ingredient_name.toLowerCase().includes(filterValue));
}
displayIngredientName(subject: Ingredient){
return subject ? subject.ingredient_name : undefined
}
}
如您所见,我需要先填充 mylist,然后再检查表单中的值更改,但我不知道如何提前完成。
我尝试使用 async/await 但我不想在 ngOnInit 中使用异步。我还在订阅中插入了表单更改,但当然这只会发生一次,所以它不会起作用。
有什么建议吗?谢谢
编辑:这是 HTML:
<form>
<mat-form-field>
<input type="text" matInput [matAutocomplete]="auto" [formControl]="myControl"/>
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayIngredientName">
<mat-option *ngFor="let ingredient of filteredList$ | async" [value]="ingredient" >
{{ingredient.ingredient_name}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</form>
您需要将两个 observable 组合成单个流,因为它们相互依赖。用户可以在加载数据之前开始键入,在加载数据之前输入的方法搜索值将被忽略。
你可以这样实现:
const ingredients$ = this.ingredientService.getAllIngredients();
const searchValues$ = this.myControl.valueChanges.pipe(startWith(''), map(val => val.toLowerCase()));
const filteredList$ = combineLatest(ingredients$, searchValues$)
.pipe(map(([list, searchVal]) => list.filter(item => item.ingredient_name.toLowerCase().includes(searchVal))));
然后只需在模板中使用异步管道即可。并且不要忘记 OnPush 变化检测。使用 debounceTime 来限制快速输入的搜索操作也是个好主意。