NgRX Entity : ids are undefined in the State - javascript

I've been trying #ngrx/entity in a dummy "Todo" project, with a single AppModule, a single reducer and a single component. However, I am having issues trying it out.
My actions are pretty straight forward, just some CRUD operations :
import { Action } from '#ngrx/store';
import { Todo } from '../../models/todo';
export const CREATE = '[Todo] Create'
export const UPDATE = '[Todo] Update'
export const DELETE = '[Todo] Delete'
export class Create implements Action {
readonly type = CREATE;
constructor(public todo: Todo) { }
}
export class Update implements Action {
readonly type = UPDATE;
constructor(
public id: string,
public changes: Partial<Todo>,
) { }
}
export class Delete implements Action {
readonly type = DELETE;
constructor(public id: string) { }
}
export type TodoActions
= Create
| Update
| Delete;
Then my reducer file contains everything I need to handle my entity :
import * as actions from './todo.actions';
import { EntityState, createEntityAdapter } from '#ngrx/entity';
import { createFeatureSelector } from '#ngrx/store';
import { Todo } from '../../models/todo';
export interface TodosState extends EntityState<Todo> {}
export const todoAdapter = createEntityAdapter<Todo>();
export const initialState: TodosState = todoAdapter.getInitialState();
export function todoReducer(state: TodosState = initialState, action: actions.TodoActions) {
console.log("Got new action", action);
switch(action.type) {
case actions.CREATE:
return todoAdapter.addOne(action.todo, state);
case actions.UPDATE:
return todoAdapter.updateOne({
id: action.id,
changes: action.changes
}, state);
case actions.DELETE:
return todoAdapter.removeOne(action.id, state);
default:
return state;
}
}
export const {
selectIds,
selectEntities,
selectAll,
selectTotal
} = todoAdapter.getSelectors();
In my app.module.ts file, I am doing the following :
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { StoreModule } from '#ngrx/store';
import { StoreDevtoolsModule } from '#ngrx/store-devtools';
import { AppComponent } from './app.component';
import { todoReducer } from './reducers/todo.reducer';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
StoreModule.forRoot({
todo: todoReducer
}),
StoreDevtoolsModule.instrument({maxAge: 25}),
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Finally, in my app.component.ts, I am simply trying to create two TODOs :
import { Component, OnInit } from '#angular/core';
import { Store } from '#ngrx/store';
import { Observable } from 'rxjs/Observable';
import * as fromTodo from './reducers/todo.reducer';
import { Todo } from '../models/todo';
import { Create } from './reducers/todo.actions';
#Component({
selector: 'app-root',
template: `
`,
styles: []
})
export class AppComponent implements OnInit {
public todos: Observable<Todo[]>;
constructor(private store: Store<fromTodo.TodosState>) {
this.store.dispatch(new Create({
title: "Test todo",
content: "This is a test todo",
date: new Date()
}))
this.store.dispatch(new Create({
title: "Test todo 2",
content: "This is another todo",
date: new Date()
}))
}
ngOnInit() {
this.todos = this.store.select(fromTodo.selectAll);
}
}
However, after running this, I inspected the Redux DevTools. I saw that it only creates the first TODO, and its id is "undefined".
My console.log in my reducer displays #ngrx/store/init, as well as both [TODO] Create actions
Moreover, if I try to ngFor | async through my todos in my component, I get various errors depending on what I try ("Cannot read 'map' property of undefined" mainly).

After some research, I noticed that #ngrx/entity uses the id property of the model you use.
In my case, my Todo model did not have any id property, so #ngrx/entity could not handle my entities.
I thought it generated ids internally, but apparently it doesn't.
So the fix to this issue is to add an id property to the model, and auto-generate it each time you add an item to the state.
There is a Angular2 UUID module for example.
In my case, I am using ngrx with AngularFire2, which has a createId() method : const id = this.afs.createId(). Then I can add it to the item I want to add, and then store it in my Firestore database.

Related

angular form.io form-builder custom component get reference

I'm developing in ANGULAR 10
I use form.io form-builder to render components
I add custom component that drow grid (ag-grid) According to this link add custom Components with Angular Elements
every think work well
I drag and drop the table several times to draw multiple tables.
I enclose a photo of how the form looks like after the drag and drop action into the form
The problem .
when form.io render my custom component that draw the ag-grid , i need to get the connection string and the sql statement from the component definition (json).
I do not know how to get this information from my custom component at the time it's be rendering. Without this information, I do not know generate the column names and row's content.
This is my project
builder component contain the formio tag
aggrid component is my custom component for display ag grid
formio.ts
import { Injector } from '#angular/core';
import { FormioCustomComponentInfo, registerCustomFormioComponent } from 'angular-formio';
import { AggridWrapperComponent } from './aggrid-wrapper.component';
export function minimalEditForm() {
return {
components: [
{ key: 'type', type: 'hidden' },
{
weight: 10,
type: 'textarea',
input: true,
key: 'key',
label: 'sql statement',
tooltip: 'please enter your sql statement',
}
],
};
}
const COMPONENT_OPTIONS: FormioCustomComponentInfo = {
type: 'sqlaggrid',
selector: 'sql-grid',
editForm: minimalEditForm,
title: 'sql-grid',
group: 'basic',
icon: 'fa fa-star',
};
export function registerAgGridComponent(injector: Injector) {
registerCustomFormioComponent(COMPONENT_OPTIONS, AggridWrapperComponent, injector);
}
aggrid-wrapper.component.html
<ag-grid-angular style="width: 500px; height: 500px;" class="ag-theme-alpine"
[gridOptions]="gridOptions">
</ag-grid-angular>
AggridWrapperComponent
import { Component, EventEmitter, Input, ElementRef, Output ,ViewChild} from '#angular/core';
import { FormioCustomComponent } from 'angular-formio';
import { Grid, GridOptions } from "ag-grid";
#Component({
selector: 'app-aggrid-wrapper',
templateUrl: './aggrid-wrapper.component.html',
styleUrls: ['./aggrid-wrapper.component.css']
})
export class AggridWrapperComponent implements FormioCustomComponent<number> {
#Input()
value: number; //number is missing (null)
#ViewChild('aggrid') input;
#Output()
valueChange = new EventEmitter<number>();
#Input()
disabled: boolean;
private _value: number;
public gridOptions: GridOptions;
constructor(private elRef: ElementRef) {
this.gridOptions = <GridOptions>{
columnDefs: this.createColumnsDefs(),
onGridReady: (params) => {
this.gridOptions.api.setRowData(this.executeStatement());
}
}
}
createColumnsDefs() {
/* return the grid columns */
/*If I could get the field definition containing the SQL statement then I could return the columns of the grid */
return ???;
}
executeStatement(){
/* get the grid rows */
/*If I could get the field definition containing the SQL statement then I could execute the statement and back the rows */
return ??? */
}
}
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule ,Injector } from '#angular/core';
import { RouterModule } from '#angular/router';
import {AppConfig} from './formio-config';
//import { AppRoutingModule } from './app-routing.module'
import { FormioModule } from 'angular-formio';
import { AppComponent } from './app.component';
import { BuilderComponent } from './builder/builder.component';
import { FormsModule } from '#angular/forms';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
import { RatingWrapperComponent } from './rating-wrapper/rating-wrapper.component';
import { registerAgGridComponent} from './aggrid-wrapper/formio'
import { AggridWrapperComponent } from './aggrid-wrapper/aggrid-wrapper.component';
import { AgGridModule } from 'ag-grid-angular';
import { HttpClientModule } from '#angular/common/http';
#NgModule({
declarations: [
AppComponent,
BuilderComponent,
AggridWrapperComponent
],
imports: [
BrowserModule,
HttpClientModule,
FormsModule,
FormioModule,
BrowserAnimationsModule,
NgbModule,
AgGridModule.withComponents([])
],
exports: [RouterModule],
providers: [ ],
bootstrap: [AppComponent]
})
export class AppModule{
constructor(injector: Injector) {
registerAgGridComponent(injector)
}
}
I am missing the reference to the component definition
any idea ?
have you tried getting the object by its key?
component = form.getComponent('keyName')
The problem is:
from Where did the form object come from.
I drag and drop the same component several times, and I do not know within the component (AggridWrapperComponent) which instance I am.
Hey I was able to achieve by creating a Subject and pushing the data at the OnChange of App Component and then retrieving where ever I want to.

In Angular 9, how do I update a component's data field to show in the DOM without re-instantiating it?

I'm fairly new to Angular 9. I have a program where a user enters in a name - which, upon submitting - a POST HTTP request is sent and the name is stored. I then have an unrelated component for a sub-header that lists the names that have been stored using a GET HTTP request using ngOnInit(). However, I need the sub-header to update that list of names dynamically each time a new list is entered rather than just whenever the component instantiates.
I'm unsure how to proceed. I'm sure I could simply add a button that fetches and updates said list, but trying for something more dynamic. Thanks in advance!
//SERVICE.TS...
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { NewList } from './new-list.model';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class ListService {
createdLists: NewList[] = [];
constructor(private http: HttpClient) { }
createList(postData) {
return this.http
.post(
'API_KEY',
postData
);
}
getLists() {
return this.http
.get<NewList>(
'API_KEY'
).pipe(map(responseData => {
const responseArray: NewList[] = [];
for (const key in responseData) {
responseArray.push(responseData[key])
}
return responseArray;
})
);
}
}
// NEW-LIST-MENU.TS (USER ENTERS A NAME)...
import { Component, OnInit } from '#angular/core';
import { NgForm } from '#angular/forms';
import { Router } from '#angular/router';
import { ListService } from 'src/app/shared/list.service';
import { NewList } from 'src/app/shared/new-list.model';
import { UIService } from 'src/app/shared/ui.service';
#Component({
selector: 'app-new-list-menu',
templateUrl: './new-list-menu.component.html',
styleUrls: ['./new-list-menu.component.css']
})
export class NewListMenuComponent implements OnInit {
constructor(private listService: ListService,
private uiService: UIService,
private router: Router) { }
ngOnInit(): void {
}
onSubmit(form: NgForm) {
const listName = form.value.listname;
const newListObj = new NewList(listName, []);
this.listService.createList(newListObj)
.subscribe(() => {
this.router.navigate(['']);
});
const lists = this.listService.updateLists(newListObj);
form.reset();
}
onCancel() {
this.router.navigate(['']);
}
}
// SUB-HEADER.TS...
import { Component, OnInit, Output } from '#angular/core';
import { Router } from '#angular/router';
import { ListService } from 'src/app/shared/list.service';
import { NewList } from 'src/app/shared/new-list.model';
import { faWindowClose } from '#fortawesome/free-solid-svg-icons';
import { faPlusCircle } from '#fortawesome/free-solid-svg-icons';
import { faList } from '#fortawesome/free-solid-svg-icons';
import { faSignOutAlt } from '#fortawesome/free-solid-svg-icons';
import { Subject } from 'rxjs';
#Component({
selector: 'app-sub-header',
templateUrl: './sub-header.component.html',
styleUrls: ['./sub-header.component.css']
})
export class SubHeaderComponent implements OnInit {
createdLists: NewList[];
faWindowClose = faWindowClose;
faPlusCircle = faPlusCircle;
faList = faList;
faSignOutAlt = faSignOutAlt;
#Output() closeSub = new Subject();
constructor(private listService: ListService,
private router: Router) { }
ngOnInit(): void {
this.listService.getLists().subscribe((responseData) => {
this.createdLists = responseData;
});
}
onCloseSelect() {
this.closeSub.next();
}
onNewListSelect() {
this.onCloseSelect();
this.router.navigate(['new-list-menu']);
}
onLogOutSelect() {
}
}```
You can accomplish this in many ways, as these components are not related to each other, you can introduce a state service and use observables. see below possible solution
Create a new state service ListStateService
export class ListStateService {
private listData = new BehaviorSubject<NewList >({} as NewList);
listData$ = this.listData .asObservable();
}
Inject ListStateService into NewListMenuComponent
In the onSubmit, after you update,
const lists = this.listService.updateLists(newListObj);
this.listData .next(lists );
Inject ListStateService into SubHeaderComponent
In the ngOnInit(), subscribe to the ListStateService.listData$ and here you will get the value on changes
In your service, use an event emitter (very useful):
import { EventEmitter } from "#angular/core";
#Output() myEvent: EventEmitter<any> = new EventEmitter();
then emit new data to your sub header component through your service like so:
emitEvent (newData: Array<string>) {
this.myEvent.emit({
data: newData,
});
}
Subscribe to new data in your sub header component ngOnInit and use it:
this.myService.myEvent.subscribe((newData: Array<string>) => {
console.log(JSON.stringify(newData.data));
});
Note: Subscriptions will cause memory leaks if constantly re-subscribed in the component, so you can save the subscription and call unsubscribe() on it in the ngOnDestroy callback.
It's a little unclear what you are trying to do, but if you are trying to pass data from a parent component to a child component, you can do this either with Input fields or a ViewChild
to use Input fields your parent might looks like this:
<app-sub-header [names]="names"></app-sub-header>
then use an "Input" field in the child. Updating names in the parent should update the same named variable in the child in real time.

Restricting List of Items by User Account ID

Using Angular 4, Ngrx Store & AngularFire2
I am having real problems understanding how I can restrict a list of items from Firebase based on the currently logged in user account id.
I am using ngrx as well including ngrx effects.
The steps I need to follow are:
• Get Current Users UID – Auth Object
• Get User Object based on the UID from step above
• Get Company List based on the User Account ID Above
My problem is that because I am calling firebase as an Observable the call to company list is being made before I complete the first two steps.
The code is as per below, if someone can assist that would be appreciated:
The problem is in the getEntityList Method on the generic firebase service - I have marked where the problem is
Company Component
import { Component, OnInit, ChangeDetectionStrategy } from '#angular/core';
import { Observable } from 'rxjs/Rx';
import { Store } from '#ngrx/store';
import { AppState } from './../../../core/models/index';
import { CompanyModel } from './../../../core/models/index';
import { getCompanies} from './../../../core/store/actions/company.actions';
#Component({
selector: 'mj-company',
templateUrl: './company.component.html',
styleUrls: ['./company.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CompanyComponent implements OnInit {
entityList$: Observable<CompanyModel[]>;
constructor(private store: Store<AppState>) {
this.entityList$ = this.store.select(state => state.companies);
}
ngOnInit() { this.store.dispatch(getCompanies()); }
}
Company Actions
import { CompanyModel } from './../../models';
import { Action } from '#ngrx/store';
export const ActionTypes = {
GET_COMPANIES: 'GET_COMPANIES',
GET_COMPANIES_SUCCESS: 'GET_COMPANIES_SUCCESS',
GET_COMPANIES_ERROR: 'GET_COMPANIES_ERROR'
};
export function getCompanies() {
return {
type: ActionTypes.GET_COMPANIES,
entityRef: 'companys'
}
}
}
Company Reducer
import { ActionReducer, Action } from '#ngrx/store';
import { ActionTypes } from '../actions/company.actions';
import { CompanyModel } from '../../models';
export function companyReducer(state = [<CompanyModel>{}], action: Action) {
switch (action.type) {
case ActionTypes.GET_COMPANIES:
return action.payload;
case ActionTypes.GET_COMPANIES_SUCCESS:
return action.payload;
case ActionTypes.GET_COMPANIES_ERROR:
return action.payload;
default:
return state;
}
};
Company Effect
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Rx';
import { ActionTypes } from '../actions/company.actions';
import { Actions, Effect } from '#ngrx/effects';
import { FirebaseDataService } from './../../services/firebase-data.service';
#Injectable()
export class CompanyEffects {
constructor(
private actions$: Actions,
private firebaseDataService: FirebaseDataService
) { }
// tslint:disable-next-line:member-ordering
#Effect() getCompanies$ = this.actions$
.ofType(ActionTypes.GET_COMPANIES)
.switchMap(action =>
this.firebaseDataService.getEntityList(action.entityRef)
.map(companies => ({ type: ActionTypes.GET_COMPANIES_SUCCESS, payload: companies }))
.catch(() => Observable.of({ type: ActionTypes.GET_COMPANIES_ERROR })));
Firebase Generic Data Service
import { Injectable } from '#angular/core';
import { AngularFireDatabase, FirebaseListObservable, FirebaseObjectObservable } from 'angularfire2/database';
import { Observable } from 'rxjs/Rx';
import { AuthService } from './auth.service';
import { FirebaseUtilityService } from './../../core/services/firebase-utility.service';
import { UserModel, CompanyModel } from './../models/index';
#Injectable()
export class FirebaseDataService {
$key: string;
loginId: string;
currentUser: any;
constructor(private db: AngularFireDatabase,
private authService: AuthService,
private firebaseService: FirebaseUtilityService) { }
// Return an observable list with optional query
getEntityList(firebaseRef: string, query = {}): FirebaseListObservable<any[]> {
this.loginId = this.authService.currentUserId;
// I get this instantly which is good
console.log('logId: ', this.loginId);
this.currentUser = this.db.object('users/' + this.loginId);
console.log('accountId: ', this.currentUser.accountId);
// This is where the problem is because at this stage the subscription above is not complete so accountId is undefined.
return this.db.list(firebaseRef, {
query: {
orderByChild: 'accountId',
equalTo: this.currentUser.accountId
}
});
// return this.db.list(firebaseRef, query);
}
// Return a single observable item
getEntity(firebaseRef: string, key: string): FirebaseObjectObservable<any> {
const itemPath = `${firebaseRef}/${key}`;
return this.db.object(itemPath)
}
// Default error handling for all actions
private handleError(error) {
console.log(error)
}
}
Problem solved - using switchMap
return this.currentUser.switchMap(user => {
return this.db.list(firebaseRef, {
query: {
orderByChild: 'accountId',
equalTo: user.accountId
}
});
})

How to map from one model to another in Angular 2?

I have this function in my Angular 2 component, which calls Web Api:
getNextConjunctionApi(): Observable<any> {
return this._http.get(this.uri + '/GetNextConjunction')
.map((res: Response) => res.json());
}
Web Api returns a complex object, which I would like to map to an Angular 2 model called ClientModel:
export class ClientModel {
prop1: string;
prop2: string;
...
}
Can this mapping be done by rewriting the map functionality, or need I do it in some other way?
.map((res: Response) => res.json());
I accomplished this with a slightly different approach. I had my component call a service that would return an observable. My component could then use a specific type that I created. I will show you what I have done for a blog.
posts.component.ts
import { Component, OnInit } from '#angular/core';
import { PostsService } from './posts.service';
import { PostComponent } from '../post/post.component'; // --> This is my custom type
import { Observable } from 'rxjs/Rx';
#Component({
selector: 'app-posts',
templateUrl: './posts.component.html',
providers: [PostsService]
})
export class PostsComponent implements OnInit {
posts: Observable<PostComponent[]>; // --> I use the type here
constructor( private _postsService: PostsService ) { }
ngOnInit() {
this._postsService.getAllPosts()
.subscribe(
posts => { this.posts = posts }, // --> I add the return values here
error => { console.log(error) }
);
}
}
The above has three key pieces. I import the custom type, PostComponent, set posts to an Observable of type PostComponent array, and as the Observable comes back, I add the values to the posts array.
posts.service.ts
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
#Injectable()
export class PostsService {
constructor( private _http: Http ) {}
getAllPosts(){
return this._http.get('[INSERT API CALL]')
.map((response: Response) => response.json())
.catch(msg => Observable.throw(msg));
}
}
In my service, I only map the response to response.json. This gives me more information than I need. I 'filter' it in my post.component
post.component.ts
import { Component, Input } from '#angular/core';
#Component({
selector: 'post',
templateUrl: './post.component.html'
})
export class PostComponent{
#Input() curPost: {
'id': number,
'title': string,
'author': string,
'date': string,
'body' : string,
};
constructor() { }
}

#ngrx/store with Angular 2: Cannot read property of undefined

I'm trying to learn #ngrx/store with Angular 2 - RC4. I've got a service that I'm calling from my component, and I'm just trying to console log a list of vehicles whenever it changes.
Vehicle
export interface Vehicle {
...stuff...
}
Vehicle Reducer
import { Vehicle } from '../models';
export interface VehiclesState {
vins: string[];
vehicles: { [vin: string]: Vehicle };
}
const initialState: VehiclesState = {
vins: [],
vehicles: {}
}
export const vehicles = (state: any = initialState, {type, payload}) => {
switch (type) {
case 'LOAD_VEHICLES':
const vehicles: Vehicle[] = payload;
const newVehicles = vehicles.filter(vehicle => !state.vehicles[vehicle.vin]);
const newVehicleVins = newVehicles.map(vehicle => vehicle.vin);
const newVehiclesList = newVehicles.reduce((vehicles: { [vin: string]: Vehicle }, vehicle: Vehicle) => {
return mergeObjects(vehicles, {
[vehicle.vin]: vehicle
});
}, {});
return {
vins: [...state.vins, ...newVehicleVins],
vehicles: mergeObjects({}, state.vehicles, newVehiclesList)
}
}
}
main.ts
import { bootstrap } from '#angular/platform-browser-dynamic';
import { enableProdMode } from '#angular/core';
import { HTTP_PROVIDERS } from '#angular/http';
import { provideStore } from '#ngrx/store'
import { AppComponent, environment } from './app/';
import { vehicles } from './app/shared/reducers/vehicles'
if (environment.production) {
enableProdMode();
}
bootstrap(AppComponent,
[
HTTP_PROVIDERS,
provideStore(vehicles, {
vins: [],
vehicles: {}
})
]
);
VehiclesService
import {Http, Headers} from '#angular/http';
import {Injectable} from '#angular/core';
import {Store} from '#ngrx/store';
import {Observable} from "rxjs/Observable";
import 'rxjs/add/operator/map';
import {Vehicle} from '../models/vehicle.model';
const BASE_URL = 'http://localhost:3000/vehicles/';
const HEADER = { headers: new Headers({ 'Content-Type': 'application/json' }) };
#Injectable()
export class VehiclesService {
vehicles: Observable<Array<Vehicle>>;
constructor(private http: Http, private store: Store<Vehicle[]>) {
this.vehicles = this.store.select('vehicles');
}
loadVehicles() {
this.http.get(BASE_URL)
.map(res => res.json())
.map(payload => ({ type: 'LOAD_VEHICLES', payload: payload }))
.subscribe(action => this.store.dispatch(action));
}
}
AppComponent
import { Component, OnInit, Input } from '#angular/core';
import { Observable } from "rxjs/Observable";
import { Store } from '#ngrx/store';
import { Vehicle, VehiclesService } from './shared';
#Component({
moduleId: module.id,
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css'],
providers: [VehiclesService]
})
export class AppComponent implements OnInit{
title = 'app works!';
vehicles: Observable<Vehicle[]>;
constructor(private vehiclesService: VehiclesService) {
this.vehicles = vehiclesService.vehicles;
vehiclesService.loadVehicles();
}
ngOnInit() {
console.log(this.vehicles)
this.vehicles.subscribe(vehicles => console.log(vehicles));
}
}
But when it runs, I get a TypeError TypeError: Cannot read property 'vehicles' of undefined
The first console.log returns a Store object, but the subscription seems to fail.
Any idea what I'm doing wrong?
You need to change your provideStore to be provideStore({vehicles: vehicles}).
In my case, the error was the use of different names in the reducer object and the interface:
import { LeaderboardParticipant } from './...';
import * as fromLeaderboard from './...';
export interface IState {
leaderboard: fromLeaderboard.IState;
}
export const reducers = {
leaderboard: fromLeaderboard.reducer // I used to have 'search' instead of 'leaderboard'
};
export function selectChallengeId(state: IState): string {
return state.leaderboard.challengeId;
}
export function selectFilterTerms(state: IState): string {
return state.leaderboard.filterTerms;
}
There is not enough information: template app.component.ts is missing in the question.
However, check how do you access the member vehicles in your template. Try operator ?. instead of .. Something like:
{{ yourObject?.vehicles }}
When you declare your Store (Store), I think the right way is:
constructor(private http: Http, private store: Store<VehicleState>)

Categories

Resources