I'm trying to use NgRx/effects for my material autocompleted in angular 8.
I have created store, action, effects and reducers but I'm not getting the state after successfully calling the api. The api is returning the correct value.
Action file
import { Action } from '@ngrx/store';
import {IProviderSearchObject} from '../../models/provider.type';
export enum ProviderSearchActionTypes {
SearchProvidersRequest = '[SEARCH_PROVIDER] REQUEST',
SearchProvidersSuccess = '[SEARCH_PROVIDER] SUCCESS',
SearchProvidersFail = '[SEARCH_PROVIDER] FAILED'
}
export class ProviderSearchAction implements Action {
type: string;
payload: {
isRequesting: boolean,
providers: Array<IProviderSearchObject>,
error: boolean,
searchPhrase: string
};
}
export class SearchProvidersRequest implements Action {
readonly type = ProviderSearchActionTypes.SearchProvidersRequest;
constructor(readonly payload: {isRequesting: boolean, searchPhrase: string}) {}
}
export class SearchProvidersSuccess implements Action {
readonly type = ProviderSearchActionTypes.SearchProvidersSuccess;
constructor(readonly payload: {isRequesting: boolean, providers: Array<IProviderSearchObject>}) {}
}
export class SearchProvidersFail implements Action {
readonly type = ProviderSearchActionTypes.SearchProvidersFail;
constructor(readonly payload: {error: boolean}) {}
}
export type ProviderSearchActions = SearchProvidersRequest | SearchProvidersSuccess | SearchProvidersFail;
reducer file
import {IProviderSearchObject} from '../../models/provider.type';
import {ProviderSearchAction, ProviderSearchActionTypes} from '../actions/provider-search.action';
export interface IProviderSearchState {
isRequesting: boolean;
providers: Array<IProviderSearchObject> | null;
error: boolean;
}
const initialProviderSearchState: IProviderSearchState = {
isRequesting: false,
providers: null,
error: false
};
export function providerSearchReducer(state: IProviderSearchState = initialProviderSearchState, action: ProviderSearchAction): IProviderSearchState {
console.log(action, state);
switch (action.type) {
case ProviderSearchActionTypes.SearchProvidersRequest:
return {
isRequesting: true,
providers: null,
error: false
};
case ProviderSearchActionTypes.SearchProvidersSuccess:
return {
isRequesting: false,
providers: action.payload.providers,
error: false
};
case ProviderSearchActionTypes.SearchProvidersFail:
return {
isRequesting: false,
providers: null,
error: true
}
default:
return state;
}
}
import {ActionReducerMap, MetaReducer} from '@ngrx/store';
import {IProviderSearchState, providerSearchReducer} from './provider-search.reducer';
export interface IAppState {
providerSearch: IProviderSearchState;
}
export const reducers: ActionReducerMap<IAppState> = {
providerSearch: providerSearchReducer
};
export const selectProviderSearch = (state: IAppState) => state.providerSearch.providers;
export const metaReducers: MetaReducer<any>[] = [];
Effects file
import {Actions, Effect, ofType} from '@ngrx/effects';
import {IAppState} from '../reducers';
import {ProviderSearchService} from '../../modules/provider-search/services/provider-search.service';
import {Store} from '@ngrx/store';
import {ProviderSearchActionTypes, SearchProvidersSuccess, SearchProvidersFail} from '../actions/provider-search.action';
import {catchError, map, switchMap} from 'rxjs/operators';
import { of } from 'rxjs';
import {IProviderSearchObject} from '../../models/provider.type';
import {Injectable} from '@angular/core';
@Injectable()
export class ProviderSearchEffects {
constructor(private actions$: Actions,
private store: Store<IAppState>,
private providerSearchService: ProviderSearchService) {}
@Effect()
searchProvider$ = this.actions$
.pipe(
ofType<any>(ProviderSearchActionTypes.SearchProvidersRequest),
map(action => action.payload),
switchMap((action) => {
return this.providerSearchService.getProviderByPhrase(action.searchPhrase).pipe(
map((data: Array<IProviderSearchObject>) => new SearchProvidersSuccess({isRequesting: false, providers: data})),
catchError(error => of(new SearchProvidersFail({error: true})))
);
})
);
}
import { ProviderSearchEffects } from './provider-search.effects';
export const effects: Array<any> = [ProviderSearchEffects];
Service file
import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {environment} from './../../../../environments/environment';
import { Store } from '@ngrx/store';
import * as ProviderSearchAction from '../../../store/actions/provider-search.action';
import {IAppState} from '../../../store/reducers';
import {Observable} from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ProviderSearchService {
constructor(
private http: HttpClient,
private store: Store<IAppState>
) { }
public getProviderByPhrase = (searchPhrase: string): Observable<any> => {
return this.http.get('https://mydummyapi.com?q=' + searchPhrase);
}
public searchProviderByTermSearch = (searchPhrase: string): any => {
return this.store.dispatch(new ProviderSearchAction.SearchProvidersRequest({isRequesting: true, searchPhrase}));
}
}
Component file
ngOnInit() {
this.providerSearchControl.valueChanges
.pipe(
debounceTime(500),
tap(() => {
this.isLoading = true;
}),
switchMap((value: string) => this.providerSearchService.searchProviderByTermSearch(value))
.pipe(
finalize(() => {
this.isLoading = false;
})
)
)
)
.subscribe((data: Array<IProviderSearchObject>) => {
console.log(data);
if (data && data.length > 0) {
this.providerSearchResult = data;
}
});
}
When the user start typing the autocomplete field then searchProviderByTermSearch method is invoked inside the service file and that dispatches the action.
But after [SEARCH_PROVIDER] SUCCESS call is made nothing is happening.