REDUX

Action

@Injectable()
export class SearchActions {

  static GET_VIDEOS = '[Search] GET_VIDEOS';

  constructor(private store: Store<any>) {

  }

  getVideos(payload) {
    this.store.dispatch({type: SearchActions.GET_VIDEOS, payload});
  }

}

Effect

 @Effect()
  getVideos_ = this.appState_
    .ofType(SearchActions.GET_VIDEOS)
    .map((action: any) => action.payload)
    .switchMap(_ => this.dtsiVideosService.getVideos()
      .map((vid: VideoEntity) => this.searchEvents.getVideosComplete(vid))
      .catch(err => of(this.searchEvents.getVideosError(err))));

Event

import {Injectable} from '@angular/core';
import {Store} from '@ngrx/store';

@Injectable()
export class SearchEvents {

  static GET_VIDEOS_COMPLETE = '[Search] GET_VIDEOS_COMPLETE';

  constructor() {

  }

  getVideosComplete(payload) {
    return {type: SearchEvents.GET_VIDEOS_COMPLETE, payload};
  }

}

Reducer

@Reducer(VideoEvents.GET_VIDEOS_COMPLETE)
  @Reducer(SearchEvents.GET_VIDEOS_COMPLETE)
  getVideosComplete(state: VideosState, event: ReducerEvent) {

    const videosClone = {...state.entities};
    const videos = VideoNormalizer.videos(event.payload);

    const entities = videos.reduce((acc, curr) => {
      acc[curr.id] = curr;
      return acc;
    }, videosClone);

    return {...state, entities: entities};
  }

Projection

getVideoById_(videoId): Observable<VideoEntity> {
    return this.store.select('videos', 'entities')
      .map((entities: any) => entities[videoId]);
  }
getSearchResults_(): Observable<any> {
    return Observable.combineLatest(
      this.store.select('videos', 'entities'),
      this.store.select('tags', 'entities'),
      this.store.select('search', 'terms')
    ).map(([videos, tags, terms = []]: [any, any, any]) => {
      const videosIds = Object.keys(videos);
      const entities = videos;
      const tagIds = terms;
      const vids = videosIds
        .map(videosId => {
          let vid = entities[videosId];
          vid.tagIds = vid.tagIds || [];
          const ts = vid.tagIds.map(tagId => tags[tagId]);
          vid = {...vid, tags: ts};
          return vid;
        })
        .filter(video => {
          if (tagIds.length === 0) {
            return true;
          }
          const res = video.tagIds.map(tagId => tagIds.includes(tagId));
          return res.includes(true);
        });
      return _.orderBy(vids, (video) => {
        return video.tagIds.length;
      }, 'desc');
    });
  }

Combine Projection

getOnlineStatus(): any {
    let online = null;
    this.store.select('ui', 'online').take(1).subscribe(x => online = x);
    return online;
  }

Synchronous Projection

REDUX

By bretto

REDUX

  • 197