У меня есть угловое приложение, которое я использую с помощью ngrx и эффектов.На одном маршруте у меня есть список предупреждений, которые я получаю из REST API.Это делается путем вызова конечной точки / alerts, вызываемой в ngOnit через эффект.Однако теперь я хочу, чтобы над списком предупреждений в таблице было несколько фильтров: фильтр по статусу, фильтр по уполномоченному, созданный до, созданный после и т. Д. Итак, в принципе, каков наилучший подход для добавления фильтров в таблицы и обновления существующего набора объектов?с отфильтрованными?Мой первоначальный подход, подробно описанный ниже, возвращает отфильтрованные оповещения, но список оповещений всегда отображает исходный полный набор оповещений, а не отфильтрованные.
Так что при выбранном изменении ...
select.filter.html:
<div class="m-b-2">
<label>Status:</label>
<div class="ncc-select ncc-select-inline">
<select id="nccSelect" class="form-control" #status (change)="statusType(status.value)">
<option value="">All</option>
<option value="open">Open</option>
<option value="ticketed">Ticketed</option>
<option value="closed">Closed</option>
</select>
</div>
Затем я запускаю действие:
select.filter.ts:
...
statusType(value) {
this.store.dispatch(new fromAlerts.FetchAlertsByStatus(value));
}
...
, который выбирается в эффекте и возвращает новый набор данных следующим образом.
effect.ts
...
@Effect()
loadAlertsByStatus$ = this.actions$.ofType(alertFiltersActions.FETCH_ALERTS_BY_STATUS)
.pipe(
switchMap((action) => {
return this.alertsService.getAlertsByStatus(action).pipe(
map(alerts => new alertsActions.LoadAlertsSuccess(alerts)),
catchError(error => of(new alertsActions.LoadAlertsFail(error)))
);
})
);
...
ОднакоМой alerts.reducer.ts продолжает возвращать тот же исходный набор сущностей, а не новый «отфильтрованный» набор оповещений
alerts.reducer.ts:
import * as fromAlerts from '../actions/alerts.actions';
import * as fromAlertFilters from '../actions/filters.actions';
import { Alert } from '../../models/alert.model';
export interface AlertState {
entities: {[id: number]: Alert};
loaded: boolean;
loading: boolean;
alertSelected: Alert;
inspectorOpen: boolean;
}
export const initialState: AlertState = {
entities: {},
loaded: false,
loading: false,
alertSelected: null,
inspectorOpen: false
};
export function reducer(state = initialState, action: any): AlertState {
switch (action.type) {
case fromAlerts.LOAD_ALERTS: {
return {
...state,
loading: true
};
}
case fromAlerts.LOAD_ALERTS_SUCCESS: {
const alerts = action.payload;
const entities = alerts.reduce(
(entities: {[id: number]: Alert}, alert: Alert) => {
return {
...entities,
[alert._id]: alert
};
}, {
...state.entities
}
);
return {
...state,
loading: false,
loaded: true,
entities
};
}
case fromAlerts.LOAD_ALERTS_FAIL: {
return {
...state,
loading: false,
loaded: false
};
}
case fromAlerts.SELECT_ALERT: {
const alert = action.payload;
return {
...state,
alertSelected: alert,
inspectorOpen: true
};
}
case fromAlerts.CLOSE_INSPECTOR: {
return {
...state,
inspectorOpen: false
};
}
case fromAlertFilters.FETCH_ALERTS_BY_STATUS: {
return {
...state,
loading: true
};
}
}
return state;
}
// export different levels of state
export const getAlertsEntities = (state: AlertState) => state.entities;
export const getAlertsLoading = (state: AlertState) => state.loading;
export const getAlertsLoaded = (state: AlertState) => state.loaded;
export const getSelectedAlert = (state: AlertState) => state.alertSelected;
export const getInspectorState = (state: AlertState) => state.inspectorOpen;
alerts-list.component.ts:
import { Component, OnInit } from '@angular/core';
import { Store, select } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import * as fromStore from '../store';
import { Alert } from '../models/alert.model';
import { AlertsService } from './../services/alerts.service';
import { ActivatedRoute } from '@angular/router';
import { getAlertsLoading } from '../store/reducers/alerts.reducer';
declare var require: any;
const _ = require('underscore');
@Component({
selector: 'app-list-alerts',
templateUrl: './list-alerts.component.html',
styleUrls: ['./list-alerts.component.css']
})
export class ListAlertsComponent implements OnInit {
alerts$: Observable<Alert[]>;
realAlerts: any;
quickViewOpen$: Observable<boolean>;
alert: any;
loading: Observable<boolean>;
constructor(
private _alertsService: AlertsService,
private route: ActivatedRoute,
private store: Store<fromStore.AlertsState>
) { }
ngOnInit() {
this.loading = this.store.select(fromStore.getAlertsLoading);
this.alerts$ = this.store.pipe(
select(fromStore.getAllAlerts)
);
this.store.dispatch(new fromStore.LoadAlerts());
this.quickViewOpen$ = this.store.select(fromStore.getInspectorStatus);
}
}
alerts.selectors.ts
import { createSelector } from '@ngrx/store';
import * as fromRoot from '../../../../../store';
import * as fromFeature from '../reducers';
import * as fromAlerts from '../reducers/alerts.reducer';
import { Alert } from '../../models/alert.model';
export const getAlertState = createSelector(
fromFeature.getAlertsState,
(state: fromFeature.AlertsState) => state.alerts
);
export const getAlertsEntities = createSelector(
getAlertState,
fromAlerts.getAlertsEntities
);
export const getAllAlerts = createSelector(getAlertsEntities, entities => {
return Object.keys(entities).map(id => entities[id]);
});
export const getSelectedAlert = createSelector(
getAlertsEntities,
fromRoot.getRouterState,
(entities, router): Alert => {
return router.state && entities[router.state.params.id];
}
);
export const getAlertsLoading = createSelector(getAlertState, fromAlerts.getAlertsLoading);
export const getAlertsLoaded = createSelector(getAlertState, fromAlerts.getAlertsLoaded);
export const getCurrentlySelectedAlert = createSelector(getAlertState, fromAlerts.getSelectedAlert);
export const getInspectorStatus = createSelector(getAlertState, fromAlerts.getInspectorState);
Также этот подход будет работать длямногократная фильтрация или есть лучший подход?Я действительно не хочу использовать Angular Material, если смогу избежать этого.