@ngrx 4 如何过滤当前加载的数据

Wad*_*REN 7 ngrx

我正在开发一个新的 angular 4 plus @ngrx 4 项目。

我希望对加载的数据具有搜索功能。

例如,所有联系人信息都已加载到组件中。联系人列表将过滤与搜索文本匹配的联系人姓名。

请看截图

由于数据存在于商店中,我不想再次调用 web api 服务。

任何想法或演示代码将不胜感激。

And*_*M16 5

您可以按照此流程在已获取的内容上搜索您需要的内容:

'(input)'='searchInputChange$.next(search)'在您的输入中使用类似的东西。因此,每次用户更改输入时,都会触发我们的研究。

然后,在您的组件上,在构造函数上,每次searchInputChange$更改时,我们都会触发一个新的SearchAction. 然后,我们将更改减速器上的过滤内容,并将结果插入到contents$. 在ngOnInit我们刚刚加载从API数据的第一次。

我正在使用一个名为 的模型Content,只是一个例子,它有一个字符串参数title。我们将使用此字段根据搜索输入过滤我们的内容。

import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { Subject } from 'rxjs/Subject';
import {of} from 'rxjs/observable/of';

/** ngrx **/
import {AppState} from '../../app-state.interface';
import * as searchActions from './actions/search.actions';

/** App Models **/
import { Content } from './models/content.model';

export class SearchComponent implements OnInit {

    searchInputChange$ = new Subject<string>();
    contents$: Observable<Array<Content>>;

    constructor(private _store: Store<AppState>) {
      this.searchInputChange$
        .switchMap((text: string) => of(text))
        .subscribe((text: string) => this._store.dispatch(new searchActions.SearchAction(text)));
      this.contents$ = this._store.select(getSearchedContents);
    }

    ngOnInit() {
        this._store.dispatch(new searchActions.LoadAction());
    }

}
Run Code Online (Sandbox Code Playgroud)

然后,我们将拥有我们的SearchActions. Load在我们组件的初始化时触发,从 api 中获取一些内容。LoadSuccess在加载操作的效果上发出,以便用获取的数据填充我们的减速器并将其显示在我们的第一个组件中,它具有内容数组的有效负载。Search将在我们的输入字段更改时触发,这将有一个包含搜索字符串的字符串负载。

import { Action } from '@ngrx/store';

/** App Models **/
import { Content } from '../models/content.model';

export const LOAD = '[Search] Load';
export const LOAD_SUCCESS = '[Search] Load Success';
export const SEARCH = '[Search] Search';

export class LoadAction implements Action {
  readonly type = LOAD;
  constructor() { }
}

export class LoadActionSuccess implements Action {
  readonly type = LOAD_SUCCESS;
  constructor(public payload: Content[]) { }
}

export class SearchAction implements Action {
  readonly type =  SEARCH;
  constructor(public payload: string) {}
}

export type All
  = LoadAction
  | LoadActionSuccess
  | SearchAction;
Run Code Online (Sandbox Code Playgroud)

SearchEffect只会从 api 中获取内容:

import { Injectable } from '@angular/core';
import { Actions, Effect } from '@ngrx/effects';

/** rxjs **/
import {of} from 'rxjs/observable/of';
import {map} from 'rxjs/operators/map';
import {mergeMap} from 'rxjs/operators/mergeMap';
import {catchError} from 'rxjs/operators/catchError';

/** ngrx **/
import * as searchActions from '../actions/search.actions';

/** App Services **/
import { SomeService } from '../services/some.service';

/** App Model **/
import {Content} from '../models/content.model';

@Injectable()
export class SearchEffects {

  @Effect() load$ = this.actions$
    .ofType(searchActions.LOAD)
      .pipe(
        mergeMap(() => {
          return this.someService.getContentsFromApi()
            .pipe(
              map((contents: Content[]) => {
                return new searchActions.LoadActionSuccess(contents);
              }),
              catchError(() => {
                // do something
              })
            );
        })
    )
  ;

  constructor(private someService: SomeService, private actions$: Actions) { }
}
Run Code Online (Sandbox Code Playgroud)

SearchReducerLoadSuccess在我们成功从 api 和Searchaction获取内容时进行处理,该操作将过滤我们获取的内容以仅返回包含内容title参数中的搜索字符串的内容。我们将首先获取的内容保存在contents和 中searchedContents。然后,在搜索,我们将更新searchedContents只包含contents已经content.title包括搜索到的字符串。

import { isEmpty } from 'lodash';

/** ngrx **/
import {createFeatureSelector} from '@ngrx/store';
import {createSelector} from '@ngrx/store';

/** App Models **/
import { Content } from '../models/content.model';

/** ngrx **/
import * as searchActions from '../actions/search.actions';

export type Action = searchActions.All;

export interface SearchsState {
  contents: Content[];
  searchedContents: Content[];
}

export const initialState: SearchsState = {
  contents: [],
  searchedContents: []
};

/ -------------------------------------------------------------------
// Selectors
// -------------------------------------------------------------------
export const selectContents      = createFeatureSelector<SearchsState>('search');
export const getSearchedContents = createSelector(selectContents, (state: searchedContents) => {
  return state.searchedContents;
});

export function contentsReducer(state: searchedContents = initialState, action: Action): searchedContents {
  switch (action.type) {
    case contentsActions.LOAD_SUCCESS:
      const loadContents = action.payload.map(content => new Content(content));
      return {
               contents: loadContents,
               searchedContents: loadContents
      };
    case contentsActions.SEARCH:
      const keywordContents = isEmpty(action.payload) ? state.contents :
          state.contents.filter(content => content.title.includes(action.payload));
      return {
               contents : state.contents,
               searchedContents : keywordContents
      };
    default: {
      return state;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

因此,更新searchedContents将自动更新我们组件中的内容。