Поиск / Фильтр состояния NGXS - PullRequest
0 голосов
/ 18 апреля 2019

Я новичок в 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 для отфильтрованных продуктов?

Любая помощь будет высоко ценится (особенно пример стекаблица)!

1 Ответ

1 голос
/ 22 апреля 2019

Возможно, вам будет проще, если вы смоделируете свое состояние таким образом, захватив список основных продуктов и текст, введенный в текстовое поле поиска:

export interface ProductsStateModel {
  products: Product[];
  filterText: string; // Your SKU value that is entered
} 

.. Затем в вашем штате используйте селектор для проецирования отфильтрованного списка, который вы действительно хотите отобразить в пользовательском интерфейсе (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 });
   }
..

}

В пользовательском интерфейсе вы можете в своем шаблоне подписаться на селектор, то есть в products.component.ts использовать @Select(ProductsState.filteredProducts) products$.

Когда текст поиска изменяется, вы можете отправить действие в хранилище, чтобы обновить эту строку в состоянии, т.е. store.dispatch(new ProductSkuEntered({ skuText: enteredText })); Затем селектор NGXS автоматически обновит ваш список «FilterProducts», чтобы отобразить только те из них, которые соответствуют тексту.

Также приятно подключить debounceTime к изменению текста, чтобы вы фильтровали только тогда, когда пользователь прекратил печатать. то есть отправка ProductSkuEntered только после дебалюра.

Примечание: я вижу, что вы используете плагин форм NGXS - у меня нет опыта работы с этим плагином, но он не требуется для этого сценария (хотя вы можете использовать его в другом месте).

...