搜索/过滤状态 NGXS
Search / Filter State NGXS
我是 NGXS 的新手,正在尝试将其集成到一个小项目中。唯一的问题是没有很好的状态搜索/过滤示例。
我的应用从后端获取产品列表 API。它在页面上按 SKU 显示它们。我希望用户能够在输入字段中输入 SKU,并让列表在用户输入时自动过滤产品。
products.state.ts:
@Selector()
static getProductList(state: ProductStateModel) {
return state.products;
}
@Selector()
static prodFilter(searchObj: any[]) {
// something needs to happen here in order to filter state
}
products.component.ts:
@Select(ProductState.getProductList) products: Observable<Product[]>;
filterForm = this.fb.group({ sku: null });
constructor( private store: Store, private fb: FormBuilder ) { }
ngOnInit() {
this.store.dispatch( new GetProducts() );
}
//something in here (ngOnInit? ngOnChanges?) to pass (cloned??) product state into selector??
products.component.html:
<form
[formGroup]='filterForm'
novalidate
ngxsForm='products.filterForm'
(ngSubmit)='onSubmit()'
>
<input type='number' formControlName='sku' />
<button type='submit'>Submit</button>
</form>
<mat-accordion class='product-accordion'>
<mat-expansion-panel *ngFor='let product of products | async'>
<mat-expansion-panel-header>
SKU: {{ product.sku }}
</mat-expansion-panel-header>
<p>${{ product.price }}</p>
<p>{{ product.description }}</p>
</mat-expansion-panel>
</mat-accordion>
我有很多问题。我相信我不应该直接改变产品状态,所以我会克隆它吗? HTML 输出会改变吗?我应该为过滤后的产品创建一个新的 state.ts 文件吗?
非常感谢任何帮助(尤其是 stackblitz 示例)!
如果您像这样对您的州建模,捕获基本产品列表和在搜索文本框中输入的文本,您可能会发现这更容易:
export interface ProductsStateModel {
products: Product[];
filterText: string; // Your SKU value that is entered
}
.. 然后在您的状态下,使用选择器投射出您实际想要显示在 UI (filteredProducts
).
上的筛选列表
@State<ProductsStateModel>({
name: 'products'
})
export class ProductsState {
@Selector()
static filteredProducts(state: ProductsStateModel) {
return state.products.filter(p => p.sku === state.filterText);
}
@Action(ProductSkuEntered)
updateFilter({patchState}: StateContext<ProductStateModel>, {payload}: ProductSkuEntered) {
patchState({ filterText: payload.skuText });
}
..
}
在 UI 中,您可以在模板中订阅选择器,即在 products.component.ts
中使用 @Select(ProductsState.filteredProducts) products$
.
当搜索文本发生变化时,您可以向商店发送一个操作以更新状态中的字符串,即 store.dispatch(new ProductSkuEntered({ skuText: enteredText }));
然后,NGXS 选择器将自动更新您的“filteredProducts”列表,以仅显示与文本匹配的产品。
将 debounceTime
连接到文本更改也很好,这样您就可以仅在用户停止输入时进行过滤。即仅在去抖后发送 ProductSkuEntered
。
注意:我看到您正在使用 NGXS 表单插件 - 我没有使用该插件的经验,但这种情况不需要它(尽管您可能在其他地方使用它)。
我是 NGXS 的新手,正在尝试将其集成到一个小项目中。唯一的问题是没有很好的状态搜索/过滤示例。
我的应用从后端获取产品列表 API。它在页面上按 SKU 显示它们。我希望用户能够在输入字段中输入 SKU,并让列表在用户输入时自动过滤产品。
products.state.ts:
@Selector()
static getProductList(state: ProductStateModel) {
return state.products;
}
@Selector()
static prodFilter(searchObj: any[]) {
// something needs to happen here in order to filter state
}
products.component.ts:
@Select(ProductState.getProductList) products: Observable<Product[]>;
filterForm = this.fb.group({ sku: null });
constructor( private store: Store, private fb: FormBuilder ) { }
ngOnInit() {
this.store.dispatch( new GetProducts() );
}
//something in here (ngOnInit? ngOnChanges?) to pass (cloned??) product state into selector??
products.component.html:
<form
[formGroup]='filterForm'
novalidate
ngxsForm='products.filterForm'
(ngSubmit)='onSubmit()'
>
<input type='number' formControlName='sku' />
<button type='submit'>Submit</button>
</form>
<mat-accordion class='product-accordion'>
<mat-expansion-panel *ngFor='let product of products | async'>
<mat-expansion-panel-header>
SKU: {{ product.sku }}
</mat-expansion-panel-header>
<p>${{ product.price }}</p>
<p>{{ product.description }}</p>
</mat-expansion-panel>
</mat-accordion>
我有很多问题。我相信我不应该直接改变产品状态,所以我会克隆它吗? HTML 输出会改变吗?我应该为过滤后的产品创建一个新的 state.ts 文件吗?
非常感谢任何帮助(尤其是 stackblitz 示例)!
如果您像这样对您的州建模,捕获基本产品列表和在搜索文本框中输入的文本,您可能会发现这更容易:
export interface ProductsStateModel {
products: Product[];
filterText: string; // Your SKU value that is entered
}
.. 然后在您的状态下,使用选择器投射出您实际想要显示在 UI (filteredProducts
).
@State<ProductsStateModel>({
name: 'products'
})
export class ProductsState {
@Selector()
static filteredProducts(state: ProductsStateModel) {
return state.products.filter(p => p.sku === state.filterText);
}
@Action(ProductSkuEntered)
updateFilter({patchState}: StateContext<ProductStateModel>, {payload}: ProductSkuEntered) {
patchState({ filterText: payload.skuText });
}
..
}
在 UI 中,您可以在模板中订阅选择器,即在 products.component.ts
中使用 @Select(ProductsState.filteredProducts) products$
.
当搜索文本发生变化时,您可以向商店发送一个操作以更新状态中的字符串,即 store.dispatch(new ProductSkuEntered({ skuText: enteredText }));
然后,NGXS 选择器将自动更新您的“filteredProducts”列表,以仅显示与文本匹配的产品。
将 debounceTime
连接到文本更改也很好,这样您就可以仅在用户停止输入时进行过滤。即仅在去抖后发送 ProductSkuEntered
。
注意:我看到您正在使用 NGXS 表单插件 - 我没有使用该插件的经验,但这种情况不需要它(尽管您可能在其他地方使用它)。