@ngrx 4如何过滤当前加载的数据 [英] @ngrx 4 how to filter current loaded data

查看:52
本文介绍了@ngrx 4如何过滤当前加载的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am working on a new angular 4 plus @ngrx 4 project.

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

I wish to have a searching function on the loaded data.

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

For example, all the contacts info have been loaded in the component. The contacts list will be filtered which contact name matched with the search text.

请参阅屏幕截图

由于数据存储在商店中,因此我不想再次调用Web api服务.

As the data is existed in store and I do not wish to call web api service again.

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

Any idea or demo code would be appreciated.

推荐答案

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

You can follow this flow to search what you need on already fetched content:

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

Use something like '(input)'='searchInputChange$.next(search)' in your input. So, each time the user changes the input, it will trigger our research.

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

Then, on your component, on the constructor, each time searchInputChange$ changes, we trigger a new SearchAction. Then, we will change our filtered contents on the reducers and the result will be inserted into contents$. On ngOnInit we just load the data from api the first time.

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

I'm using a model called Content, just an example, that has a string parameter title. We will use this field to filter our contents based on the search input.

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

}

然后,我们将得到我们的SearchActions. Load在组件的init上触发,从api中获取一些内容. LoadSuccess是在load动作的作用下发出的,以便用获取的数据填充我们的reducer并将其显示在我们的第一个组件中,它具有内容数组的有效负载. Search将在我们更改输入字段时触发,其中将包含包含搜索字符串的字符串有效载荷.

Then, we'll have our SearchActions. Load is triggered on the init of our component, fetches some contents from api. LoadSuccess is emitted on the effect of the load action in order to populate our reducer with fetched data and show it in our first component, this has a payload of an array of contents. Search will be triggered on change of our input field, this will have a string payload containing the search string.

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;

SearchEffect ,它将仅从api中获取内容:

SearchEffect that will just fetch contents from 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) { }
}

当我们成功地从api和Search动作中获取内容时,

SearchReducer 将处理LoadSuccess,该动作将过滤获取的内容,以仅返回内容title参数中包含搜索字符串的内容.我们将首先提取的内容保存在contentssearchedContents中.然后,在搜索时,我们将更新searchedContents以仅包含contents,其中content.title包括搜索到的字符串.

SearchReducer will handle LoadSuccess when we successfully fetch contents from api and Search action that will filter our fetched contents to return only the ones containing our search string inside content's title parameter. We save first fetched contents in both of contents and searchedContents. Then, on search, we will update searchedContents to contain only contents having content.title including the searched string.

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

因此,更新searchedContents将自动更新组件中的内容.

So, updating searchedContents will automatically update the contents in our component.

这篇关于@ngrx 4如何过滤当前加载的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆