简体   繁体   English

如何在值更改检查之前完成角度可观察?

[英]How to finish angular observable before value changes check?

I am creating a search bar similar to Angular Autocomplete but I can't get my array in time.我正在创建一个类似于 Angular Autocomplete 的搜索栏,但我无法及时获取我的数组。

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
  }

}

As you can see I need to populate mylist before checking for value changes in the form and I can't figure out how to finish beforehand.如您所见,我需要在检查表单中的值更改之前填充 mylist,但我无法事先弄清楚如何完成。

I tried using async/await but I don't wanna use async in ngOnInit.我尝试使用 async/await,但我不想在 ngOnInit 中使用 async。 I have also inserted the form changes inside the subscribe but of course that only happens once so it would not work.我还在订阅中插入了表单更改,但当然这只发生一次,所以它不起作用。

Any advice?有什么建议吗? Thanks谢谢

Edit: This is the HTML:编辑:这是 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>

You need to combine both observables into single stream, since they depends on each other.您需要将两个 observable 组合成单个流,因为它们相互依赖。 User can start typing before data is loaded, with your approach search values entered before data is loaded will be ignored.用户可以在加载数据之前开始输入,在加载数据之前输入的方法搜索值将被忽略。

You could achieve it like this:你可以这样实现:

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))));

Then just use async pipe in your template.然后只需在模板中使用异步管道。 And don't forget OnPush change detection.并且不要忘记 OnPush 更改检测。 It is also good idea to use debounceTime, to limit search operations on fast typing.使用 debounceTime 来限制快速输入的搜索操作也是一个好主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM