使用新过滤的数据更新ngrx表中的实体列表

时间:2018-12-24 10:53:29

标签: angular ngrx ngrx-entity

我有一个角度为6的应用程序,我使用ngrx和效果。在一条路线上,我列出了从REST API提取的警报列表。 通过效果调用ngOnit中的/ alerts端点来完成。 但是,我现在想在警报表列表上方设置一些过滤器:按状态过滤,按受理人过滤,之前创建,之后创建等。 那么,基本上,向表添加过滤器并用过滤后的实体更新现有实体集的最佳方法是什么?下面详细介绍的我的初始方法将返回已过滤的警报,但是警报列表始终呈现初始的完整警报集,而不是已过滤的警报。

所以在选择更改上...

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

...

但是我的alert.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。

0 个答案:

没有答案