首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >@ngrx 4如何过滤当前加载的数据

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

Stack Overflow用户
提问于 2017-11-09 00:11:55
回答 2查看 7.8K关注 0票数 7

我正在工作一个新的角4加上@ngrx 4项目。

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

例如,所有联系人信息都已加载到组件中。联系人列表将被筛选出与搜索文本匹配的联系人名称。

请看截图

由于数据在存储中存在,所以我不希望再次调用web服务。

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-11-09 13:09:11

您可以按照这个流程搜索已经获取的内容需要的内容:

在输入中使用类似于'(input)'='searchInputChange$.next(search)'的内容。因此,每次用户改变输入,都会触发我们的研究。

然后,在组件上,在构造函数上,每次searchInputChange$更改时,我们都会触发一个新的SearchAction。然后,我们将更改我们过滤的内容在还原剂和结果将插入到contents$。在ngOnInit上,我们只是第一次从api加载数据。

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

代码语言:javascript
复制
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());
    }

}

然后,我们将有我们的SearchActionsLoad是在我们组件的init上触发的,从api中获取一些内容。LoadSuccess是根据load操作的效果发出的,目的是用获取的数据填充还原器并在我们的第一个组件中显示它,这有一个内容数组的有效负载。Search将在我们的输入字段更改时触发,这将有一个包含搜索字符串的字符串有效负载。

代码语言:javascript
复制
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中获取内容:

代码语言:javascript
复制
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,使其只包含具有content.titlecontents,包括搜索的字符串。

代码语言:javascript
复制
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将自动更新组件中的内容。

票数 5
EN

Stack Overflow用户

发布于 2017-11-09 11:25:18

ngrx存储是存储数据的一部分。ngrx存储是可观察的,所以您的应用程序流是

容器->组件

容器包装组件,它将从存储中选择数据。示例:

代码语言:javascript
复制
const contacts$: Observable<contact> = this.store.pluck('contacts');

//*联系美元,因为美元是可观察的公约*//

组件-数据可视化组件,数据将作为输入()。示例:

代码语言:javascript
复制
Input() contacts: Array<contact>;

这个约定称为SmartComponent(容器)和DumbComponent(组件)

现在,对于数据转换/映射,您可以使用反应性方法(Rxjs)或函数式编程或您想要的任何东西,但它与ngrx无关,因为在您的联系人组件中,数据是现有的。

场景的演示:

contacts.container.ts

代码语言:javascript
复制
@Component({
    selector: 'contacts-container',
    template: `
    <contacts-list [contacts]="contacts$ | async"></contacts-list>
    `
})

export class ContactsContainer {
    contacts$: Observable<[]contact> = this.store.pluck('contacts');
    constructor(
        private store: Store<applicationState>
    ) { }
}

contact-list.component.ts

代码语言:javascript
复制
@Component({
    selector: 'contacts-list',
    template: `
        <input type="text" placeholder="write query" #query>
        <ul>
            <li *ngFor="contact of contacts | searchPipe: query.target.value">
            </li>
        </ul
    `
})

export class ContactsListComponent {
    contcats: Array<contact> = [];
    constructor() { }

}

我使用searchPipe进行数据转换(自定义管道),但仅作为数据转换的示例,您可以进行其他转换。

祝好运!

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47191872

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档