Angular @for 确认列表中的更改

问题描述 投票:0回答:1

我正在使用 Angular 17 编写一个电子商务应用程序。

我有一个产品列表,我在我的一个 HTML 组件文件中使用来自 Angular/core 的 @for 块进行迭代。

这是我的代码的过于简化的版本:

@for(product of products; track product){
  <h3>{{product.name}}</h3>
  <span>{{product.price}}</span>
}

我的问题是产品列表可能会因用户输入(通过产品过滤)而发生变化。

如何更改 @for 的 HTML,以便留意列表更改并自动同步,而无需刷新页面?

到目前为止我只找到了有关使用 ngFor 的信息,但我真的很想使用新的 @for 块。

angular web frontend web-frontend angular17
1个回答
0
投票

我们可以使用

fromEvent
和一个存储原始值和 rxjs 流的方法,我们使用
input
监听事件
fromEvent
,然后使用
map
来使用
filter
数组修改值方法,最后我们返回值。
fromEvent
最初不会被触发,所以我们使用
merge
of
来触发整个数组的初始值!

了解此处使用的 RXJS 运算符的最佳资源!

import { Component, ElementRef, ViewChild } from '@angular/core';
import { CommonModule } from '@angular/common';
import { bootstrapApplication } from '@angular/platform-browser';
import { fromEvent, merge, Observable, of } from 'rxjs';
import {
  map,
  debounceTime,
} from 'rxjs/operators';
import 'zone.js';
export interface Product {
  name: string;
  price: number;
}
@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule],
  template: `
    <input type="text" #search/>
    @for(product of products | async; track product){
  <h3>{{product.name}}</h3>
  <span>{{product.price}}</span>
}
  `,
})
export class App {
  @ViewChild('search') search!: ElementRef<HTMLInputElement>;
  name = 'Angular';
  searchStr = '';
  products!: Observable<Product[]>;
  productsOriginal: Product[] = [
    { name: 'test1', price: 12 },
    { name: 'testxcvbxcv2', price: 13 },
    { name: 'xcvb', price: 14 },
    { name: 'wert', price: 15 },
    { name: 'sadfasdf', price: 161 },
    { name: 'asdfasdf', price: 18 },
    { name: 'asdf', price: 119 },
  ];

  ngAfterViewInit() {
    // if you are going to change the values of product inside the ngFor
    // we need to clone productsOriginal, since updating products might modify
    // productsOriginal
    const products = structuredClone(this.productsOriginal);
    this.products = merge(
      // set the initial value of the products array
      of(products),
      // subscribe to key strokes on search
      fromEvent(this.search.nativeElement, 'input').pipe(
        debounceTime(500), // prevent event from firing multiple times, take only event with 500ms gap
        map((event: any) => {
          // get the input search value
          const searchKey = event?.target?.value;
          // filter the array if it includes the value and return it!
          return this.productsOriginal.filter((product: Product) =>
            product.name.includes(searchKey)
          );
        })
      )
    );
  }
}

bootstrapApplication(App);

Stackblitz Demo

© www.soinside.com 2019 - 2024. All rights reserved.