In my app, i want to select value and rerender plotly graph type depends on selectedvalue, Im trying to get state from storage and insert state value to component, but nothing happens, in redux dev tool i can see that state changes on select change , but nothing happens in component where i want to use it, for info i cant get state in VisualizationComponent, what i doing wrong?
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import {changeType} from '../../../store/actions/actions';
@Component({
selector: 'app-controls',
templateUrl: './controls.component.html',
styleUrls: ['./controls.component.css']
})
export class ControlsComponent {
selectedOption: string;
selectedToggle: string;
title: string;
minValue: number;
maxValue: number;
options = [
{value: 'bar', viewValue: 'BarChart'},
{value: 'bubble', viewValue: 'BubblePlot'},
{value: 'box', viewValue: 'BoxPlot'},
];
constructor(private store: Store<ControlsComponent>) {
}
changeType(value) {
this.store.dispatch(changeType({payload: value}));
}
}
import {changeType} from '../actions/actions';
import {Action, createReducer, on} from '@ngrx/store';
export interface State {
selectedOption: string;
selectedToggle: string;
title: string;
minValue: number;
maxValue: number;
}
export const initialState: State = {
selectedOption: 'box',
selectedToggle: '',
title: '',
minValue: 0,
maxValue: 0,
};
export const controlReducer = createReducer(
initialState,
on(changeType, (state, action) => ({
...state,
selectedOption: action.payload
}))
);
export function reducer(state: State | undefined, action: Action) {
return controlReducer(state, action);
}
import {ActionReducerMap} from '@ngrx/store';
import * as fromControlReducer from './controlReducer';
export interface State {
control: fromControlReducer.State;
}
export const reducers: ActionReducerMap<State> = {
control: fromControlReducer.reducer
};
import {Component, Input, OnChanges, OnInit} from '@angular/core';
import {select, Store} from '@ngrx/store';
import {State} from '../../../store/reducers/controlReducer';
@Component({
selector: 'app-visualization',
templateUrl: './visualization.component.html',
styleUrls: ['./visualization.component.css']
})
export class VisualizationComponent implements OnChanges, OnInit{
@Input() title: string;
@Input() minValue: number;
@Input() maxValue: number;
@Input() typeOfToggle: string;
graph = {data: [], layout: {}};
trace1 = {};
trace2 = {};
type: string;
constructor(private store: Store<State>) {
}
ngOnInit() {
this.store.pipe(select(state => state.selectedOption)).subscribe(type => {this.type = type; });
}
ngOnChanges() {
this.graph = {
data: [
this.trace1 = {
x: [0, 10, 20, 30, 45, 50, 20, 30, 40],
y: [0, 30, 60, 40, 10, 20, 20, 10, 60],
name: 'Blue Trace',
type: this.type,
mode: 'markers',
marker: {
size: [10, 20, 30, 40]
}
},
this.trace2 = {
x: [0, 10, 10, 20, 30, 40, 10, 20, 20],
y: [0, 40, 10, 30, 20, 20, 40, 50, 50],
name: 'Orange Trace',
type: this.type,
mode: 'markers',
marker: {
size: [10, 20, 30, 40]
}
},
],
layout: {width: 500, height: 500, title: this.title,
xaxis: { type: this.typeOfToggle, range: [this.minValue, this.maxValue]},
yaxis: { type: this.typeOfToggle, range: [this.minValue, this.maxValue]}}
};
}
}
I think I noticed the issue. You actually have to go one level deeper, the state you are looking for is not directly in state object but rather in control property, see:
export interface State {
control: fromControlReducer.State;
}
In your case you should actually write the selector like this.
this.store.select(state => state.control.selectedOption).subscribe(...)
But there is a better way. Create some dedicated selectors and then it'll be more robust and easily reusable, something like that:
// control.selectors.ts
export const contolState = (state: AppState) => state.control;
export const selectedOptionSelector = createSelector(contolState , state => state.selectedOption);
And then use it like this:
this.store.select(selectedOptionSelector ).subscirbe(...)