Angular компонентное представление не перечисляет полную полезную нагрузку состояния NGRX до refre sh (F5) - PullRequest
0 голосов
/ 23 марта 2020

У меня проблема с моим представлением компонентов. У меня есть модель Event, содержащая массив пользователей. Когда я загружаю событие, я получаю эту полезную нагрузку в избыточном devtools. Таким образом, все данные нам нужны в полезной нагрузке. Проблема в том, что я могу только перечислить пользователей для события при обновлении страницы (f5). Кто-нибудь видит проблему в коде? Я думаю, что проблема не в государстве, потому что я получаю правильные данные в полезной нагрузке ...

**payload**
title(pin):"Lasergame"
description(pin):"Bring shoes with you"
location(pin):"Interpool"
creatorId(pin):1
users(pin): {users..}     //here is the array which contains the users
id(pin):1
type(pin):"[API: /event] Load Event success"

Это подходящая часть html:

<div *ngIf="ev$ | async; let ev">
<div class="row">
 <div class="col-sm-8">
  <div class="tab-panel">
    <tabset class="member-tabset">
      <tab heading="Om evenemang">
        <h4 style="font-weight: bold;">Beskrivning</h4>
         <p>{{ ev.description }}</p>
          <ul *ngIf="ev.users"> 
           <li *ngFor="let item of ev.users">
            <p>
              {{ item.email }}
              {{ item.name }} 
            </p>
          </li>
           </ul> 
    </tabset>
  </div>
</div>
</div>
</div>

Это event.ts

import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';

import { AppState } from 'src/app/core/state';
import { Store, select } from '@ngrx/store';
import * as fromEvent from '../../state/events';
import { Observable } from 'rxjs';
import { Event, User } from 'src/app/shared/models';

import * as eventActions from '../../state/events';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'ex-event-detail',
  templateUrl: './event-detail.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  styleUrls: ['./event-detail.component.scss']
})
export class EventDetailComponent implements OnInit {
  ev$: Observable<Event>;

  constructor(private store$: Store<AppState>, private route: ActivatedRoute) {}

  ngOnInit() {
    this.LoadEvent();
    console.log(this.ev$);
  }

  private LoadEvent(): void {
    this.store$.dispatch(new eventActions.LoadEvent(this.getClickedId()));
    this.ev$ = this.store$.pipe(select(fromEvent.getCurrentEvent));

  }

  private getClickedId() {
    var id = Number(this.route.snapshot.paramMap.get('id'));
    return id;
  }

}

Это мой код ngrx.

events.actions.ts

export class LoadEvent implements Action {
  readonly type = ActionTypes.LOAD_EVENT;

  constructor(public payload: number) {}
}

export class LoadEventSuccess implements Action {
  readonly type = ActionTypes.LOAD_EVENT_SUCCESS;

  constructor(public payload: Event) {}
}

events.effects.ts

  @Effect()
  loadEvent$: Observable<Action> = this.actions$.pipe(
    ofType<eventsActions.LoadEvent>(eventsActions.ActionTypes.LOAD_EVENT),
    mergeMap((action: eventsActions.LoadEvent) =>
      this.eventResource.loadEvent(action.payload).pipe(
        map((event: Event) => new eventsActions.LoadEventSuccess(event)),
        catchError(err => of(new eventsActions.LoadEventError(err)))
     )
   )
 );

events.reducer.ts

case eventsActions.ActionTypes.LOAD_EVENT_SUCCESS: {
  return adapter.addOne(action.payload, {
    ...state,
    selectedEventId: action.payload.id
  });
}

events.selectors.ts

const { selectAll } = adapter.getSelectors();

export const selectState = (state: AppState) => state.event.evs;


export const getCurrentEventId = createSelector(selectState, state => 
state.selectedEventId)

export const getCurrentEvent = createSelector(selectState, getCurrentEventId, state =>         
state.entities[state.selectedEventId])
events.adapter.ts

export const adapter: EntityAdapter<Event> = createEntityAdapter<Event>({
 selectId: (ev: Event) => ev.id
});

Ответы [ 2 ]

1 голос
/ 23 марта 2020

Вы должны подписаться на activatedRoute.params, как показано ниже:

export class EventDetailComponent implements OnInit, OnDestroy {
  subscription: Subscription;
  ev$: Observable<Event>;

  constructor(
    private activatedRoute: ActivatedRoute,
    private store$: Store<AppState>
  ) { }

  ngOnInit() {
    this.ev$ = this.store$.pipe(select(fromEvent.getCurrentEvent));

    this.subscription = this.activatedRoute.params.subscribe(params => {
      const id = params['id'];
      this.store$.dispatch(new eventActions.LoadEvent(+id));
    });
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }

Подробнее в Доступ к параметрам URL в Angular: Снимок и подписка .

Также похоже, у вас проблема с селектором getCurrentEvent, ваш код должен быть:

const { selectIds, selectEntities } = adapter.getSelectors(getState);

export const getCurrentEvent = createSelector(
  selectEntities, getCurrentEventId, (entities, currentEventId) => {
    return entities[currentEventId])
})         

вместо:

export const getCurrentEvent = createSelector(selectState, 
  getCurrentEventId, state => state.entities[state.selectedEventId])
0 голосов
/ 23 марта 2020

Это мой код ngrx,

events.actions.ts

export class LoadEvent implements Action {
  readonly type = ActionTypes.LOAD_EVENT;

  constructor(public payload: number) {}
}

export class LoadEventSuccess implements Action {
  readonly type = ActionTypes.LOAD_EVENT_SUCCESS;

  constructor(public payload: Event) {}
}

events.effects.ts

  @Effect()
  loadEvent$: Observable<Action> = this.actions$.pipe(
    ofType<eventsActions.LoadEvent>(eventsActions.ActionTypes.LOAD_EVENT),
    mergeMap((action: eventsActions.LoadEvent) =>
      this.eventResource.loadEvent(action.payload).pipe(
        map((event: Event) => new eventsActions.LoadEventSuccess(event)),
        catchError(err => of(new eventsActions.LoadEventError(err)))
     )
   )
 );

events.reducer.ts

case eventsActions.ActionTypes.LOAD_EVENT_SUCCESS: {
  return adapter.addOne(action.payload, {
    ...state,
    selectedEventId: action.payload.id
  });
}

events.selectors.ts

const { selectAll } = adapter.getSelectors();

export const selectState = (state: AppState) => state.event.evs;


export const getCurrentEventId = createSelector(selectState, state => 
state.selectedEventId)

export const getCurrentEvent = createSelector(selectState, getCurrentEventId, state =>         
state.entities[state.selectedEventId])

events.adapter.ts

export const adapter: EntityAdapter<Event> = createEntityAdapter<Event>({
 selectId: (ev: Event) => ev.id
});
...