我正在工作一个新的角4加上@ngrx 4项目。
我希望对加载的数据有一个搜索功能。
例如,所有联系人信息都已加载到组件中。联系人列表将被筛选出与搜索文本匹配的联系人名称。
由于数据在存储中存在,所以我不希望再次调用web服务。
任何想法或演示代码将不胜感激。
发布于 2017-11-09 13:09:11
您可以按照这个流程搜索已经获取的内容需要的内容:
在输入中使用类似于'(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());
}
}然后,我们将有我们的SearchActions。Load是在我们组件的init上触发的,从api中获取一些内容。LoadSuccess是根据load操作的效果发出的,目的是用获取的数据填充还原器并在我们的第一个组件中显示它,这有一个内容数组的有效负载。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;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) { }
}当我们成功地从api和Search操作中获取内容时,SearchReducer将处理LoadSuccess,该操作将过滤获取的内容,仅返回内容的title参数中包含搜索字符串的内容。我们首先将获取的内容保存在contents和searchedContents中。然后,在搜索时,我们将更新searchedContents,使其只包含具有content.title的contents,包括搜索的字符串。
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将自动更新组件中的内容。
发布于 2017-11-09 11:25:18
ngrx存储是存储数据的一部分。ngrx存储是可观察的,所以您的应用程序流是
容器->组件
容器包装组件,它将从存储中选择数据。示例:
const contacts$: Observable<contact> = this.store.pluck('contacts');//*联系美元,因为美元是可观察的公约*//
组件-数据可视化组件,数据将作为输入()。示例:
Input() contacts: Array<contact>;这个约定称为SmartComponent(容器)和DumbComponent(组件)
现在,对于数据转换/映射,您可以使用反应性方法(Rxjs)或函数式编程或您想要的任何东西,但它与ngrx无关,因为在您的联系人组件中,数据是现有的。
场景的演示:
contacts.container.ts
@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
@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进行数据转换(自定义管道),但仅作为数据转换的示例,您可以进行其他转换。
祝好运!
https://stackoverflow.com/questions/47191872
复制相似问题