Я новичок в магазине NgRX. У меня возникла проблема с получением данных билетов в компонент билетов с помощью хранилища NgRx.
Я использовал модуль эффектов для получения асинхронных c билетов через метод http get в ticketService
Я не уверен, как настроить свой магазин и селектор для получения информации о билетах. Предоставление URL-адреса stackblitz для воспроизведения проблемы. Заранее спасибо.
https://stackblitz.com/edit/ngrx-demo-ticket
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpClientModule} from '@angular/common/http';
import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';
import { TicketsComponent } from './tickets/tickets.component';
import { TicketsService } from './tickets.service';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { environment } from './environment/environment';
import {TicketReducer} from './store/ticket.reducers';
import {TicketEffects} from './store/ticket.effects';
@NgModule({
imports: [ BrowserModule, FormsModule, HttpClientModule,
StoreModule.forRoot(TicketReducer, {}),
EffectsModule.forRoot([TicketEffects]),
!environment.production ? StoreDevtoolsModule.instrument() : [],
],
declarations: [ AppComponent, HelloComponent, TicketsComponent ],
bootstrap: [ AppComponent ],
providers: [TicketsService]
})
export class AppModule { }
Tickets.component.ts
import { Component, OnInit } from '@angular/core';
import { TicketsService } from '../tickets.service';
import { of, Observable, pipe } from 'rxjs';
import { Ticket } from '../models/ticket';
import { map, catchError, tap } from 'rxjs/operators';
import { Store, select } from '@ngrx/store';
import { AppState } from '../models/app.state';
import { selectTickets } from '../store/ticket.reducers';
import * as ticketActions from '../store/ticket.actions';
@Component({
selector: 'app-tickets',
templateUrl: './tickets.component.html',
styleUrls: ['./tickets.component.css']
})
export class TicketsComponent implements OnInit {
tickets$: Observable<Ticket[]>;
constructor(private store: Store<AppState>) {
this.tickets$ = this.store.select(pipe(selectTickets));
}
ngOnInit() {
this.store.dispatch(new ticketActions.loadTicketsAction());
this.tickets$.pipe(
// Getting tickets as undefined
tap(tickets => console.log('Store Tickets', tickets)),
map((data) => {
if (data && data !== null) {
data[6].assignee = '<a href="javascript:void(0);" class="btn btn-link">John Mike</a>';
return data;
}
}),
catchError(error => {
return of([]);
})
).subscribe(tickets => {
console.log('Store tickets', tickets)
});
}
}
app.state.ts
import { Ticket } from '../models/ticket';
export interface AppState {
readonly tickets: Ticket[];
}
ticket.ts
export interface Ticket {
id: string;
applicationName?: string;
category?: string;
subject: string;
description?: string;
status: string;
priority: string;
assignee: string;
platform?: string;
dueDate: string;
}
ticket.action.ts
import { Action } from '@ngrx/store';
import * as types from './action.types';
import { Ticket } from '../models/ticket';
export class loadTicketsAction implements Action {
readonly type = types.LOAD_TICKETS;
}
export class loadTicketsSuccessAction implements Action {
readonly type = types.LOAD_TICKETS_SUCCESS;
constructor(public payload: Ticket[]) {}
}
export type Actions =
loadTicketsAction |
loadTicketsSuccessAction;
ticket.reducers.ts
import * as ticketActions from './ticket.actions';
import * as types from './action.types';
import { AppState } from '../models/app.state';
export const initialState: AppState = {
tickets: []
}
export function TicketReducer(state = initialState, action: ticketActions.Actions):AppState {
switch(action.type) {
case types.LOAD_TICKETS_SUCCESS: {
return {...state, tickets: action.payload };
}
default:
return state;
}
}
export const selectTickets = (state: AppState) => state.tickets;
ticket.effects.ts
import { Injectable } from "@angular/core";
import { TicketsService } from "../tickets.service";
import { Effect, Actions, ofType } from '@ngrx/effects';
import { map, mergeMap } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { Action } from '@ngrx/store';
import * as ticketActions from './ticket.actions';
import * as types from './action.types';
@Injectable({
providedIn: 'root'
})
export class TicketEffects {
constructor(private ticketsService: TicketsService,
private actions$: Actions
) { }
@Effect() loadTickets$: Observable<Action> = this.actions$.pipe(
ofType<ticketActions.loadTicketsAction>(types.LOAD_TICKETS),
mergeMap(() => this.ticketsService.getAllTickets().pipe(
map(tickets => {
return (new ticketActions.loadTicketsSuccessAction(tickets))
})
))
)
}