Closed richardshergold closed 5 years ago
Richard, thanks for the bug report! I'm looking into it now.
Quick Q. Is core a separate module that is imported into your root module, state module, etc?
Something else I should have noted:
My app.state.ts has the email entity state in it + my two non-entity states (have I done this right) ?
export interface IAppState {
email: IEntityState<Email>;
}
export type AppState = IAppState;
export const appReducer: ActionReducerMap<AppState> = {
email:emailReducer
};
export const appMetaReducers: Array<MetaReducer<AppState>> = !environment.production
? [autoEntityMetaReducer, storeFreeze]
: [autoEntityMetaReducer];
export const reducers = {
application: applicationReducer,
auth: authReducer
};
Re core - I have my guards, models and services sub-folders in a core folder off the app folder, is that what you mean?
Yes, that was what I was curious about. So your email service, is that also in your core module? It would help if you could put together a small example project in StackBlitz. That way I can see how you've organized things and what modules each model or service is in.
Email is in app/core/models/email.model.ts EmailService is in app/core/services/email.service.ts Emails-list component is in app/feature/emails/email-list/emails-list.component.ts and has its own module EmailFacade is in app/state/facades/email-facade.ts app.state.ts is in app/state email.state.ts is in app/state
Hope that helps!
and in app.module.ts I have
{ provide: Email, useClass: EmailService }
At the time of the error I can see
[Emails] Generic Load All
in Dev tools so the action is getting triggered. No http call is made though.
here's my package.json
{
"name": "pmx-ionic-4",
"version": "0.0.1",
"author": "Ionic Framework",
"homepage": "https://ionicframework.com/",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/common": "^8.0.2",
"@angular/core": "^8.0.2",
"@angular/forms": "^8.0.2",
"@angular/http": "^7.2.2",
"@angular/platform-browser": "^8.0.2",
"@angular/platform-browser-dynamic": "^8.0.2",
"@angular/router": "^8.0.2",
"@briebug/ngrx-auto-entity": "^0.1.1",
"@ionic-native/app-version": "^5.8.0",
"@ionic-native/core": "^5.0.0",
"@ionic-native/network": "^5.8.0",
"@ionic-native/push": "^5.8.0",
"@ionic-native/splash-screen": "^5.0.0",
"@ionic-native/status-bar": "^5.0.0",
"@ionic/angular": "^4.6.0",
"@ionic/storage": "^2.2.0",
"@ngrx/effects": "^8.0.1",
"@ngrx/store": "^8.0.1",
"@ngrx/store-devtools": "^8.0.1",
"cordova-android": "^8.0.0",
"cordova-ios": "^5.0.1",
"cordova-plugin-app-version": "^0.1.9",
"cordova-plugin-network-information": "^2.0.1",
"cordova-sqlite-storage": "^3.2.0",
"cordova-support-google-services": "^1.1.0",
"core-js": "^2.5.4",
"faye": "^1.2.4",
"ngrx-store-freeze": "^0.2.4",
"phonegap-plugin-multidex": "^1.0.0",
"phonegap-plugin-push": "^2.2.3",
"rxjs": "~6.5.1",
"sentry-cordova": "^0.15.0",
"tslib": "^1.9.0",
"zone.js": "^0.9.1"
},
"devDependencies": {
"@angular-devkit/architect": "~0.13.8",
"@angular-devkit/build-angular": "~0.800.4",
"@angular-devkit/core": "~7.3.8",
"@angular-devkit/schematics": "~7.3.8",
"@angular/cli": "~8.0.4",
"@angular/compiler": "~8.0.2",
"@angular/compiler-cli": "~8.0.2",
"@angular/language-service": "~8.0.2",
"@ionic/angular-toolkit": "~1.5.1",
"@types/jasmine": "~2.8.8",
"@types/jasminewd2": "~2.0.3",
"@types/node": "~12.0.0",
"codelyzer": "~4.5.0",
"cordova-plugin-device": "^2.0.2",
"cordova-plugin-ionic-keyboard": "^2.1.3",
"cordova-plugin-ionic-webview": "^4.1.0",
"cordova-plugin-splashscreen": "^5.0.2",
"cordova-plugin-statusbar": "^2.4.2",
"cordova-plugin-whitelist": "^1.3.3",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.1.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~1.1.2",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.4.0",
"ts-node": "~8.3.0",
"tslint": "~5.17.0",
"typescript": "~3.4.5"
},
"description": "An Ionic project",
"cordova": {
"plugins": {
"cordova-plugin-app-version": {},
"cordova-sqlite-storage": {},
"cordova-plugin-network-information": {},
"cordova-plugin-whitelist": {},
"cordova-plugin-statusbar": {},
"cordova-plugin-device": {},
"cordova-plugin-splashscreen": {},
"cordova-plugin-ionic-webview": {},
"cordova-plugin-ionic-keyboard": {},
"sentry-cordova": {},
"phonegap-plugin-push": {
"ANDROID_SUPPORT_V13_VERSION": "27.+",
"FCM_VERSION": "11.6.2"
}
},
"platforms": [
"ios",
"android"
]
}
}
Just to be clear - core is not a module, just a folder off of "app"
Here's my full app.module.ts
import { NgrxAutoEntityModule } from '@briebug/ngrx-auto-entity';
import { NgModule, ErrorHandler } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { RouteReuseStrategy } from "@angular/router";
import { IonicModule, IonicRouteStrategy } from "@ionic/angular";
import { SplashScreen } from "@ionic-native/splash-screen/ngx";
import { StatusBar } from "@ionic-native/status-bar/ngx";
import { AppComponent } from "./app.component";
import { AppRoutingModule } from "./app-routing.module";
import { StoreDevtoolsModule } from "@ngrx/store-devtools";
import { StoreModule } from "@ngrx/store";
import { EffectsModule } from "@ngrx/effects";
import { HttpClientModule, HTTP_INTERCEPTORS } from "@angular/common/http";
import { IonicStorageModule } from "@ionic/storage";
import { LoaderService } from "./core/services/loader.service";
import { AppVersion } from "@ionic-native/app-version/ngx";
import * as Sentry from "sentry-cordova";
import { Network } from "@ionic-native/network/ngx";
import { ComponentsModule } from 'src/app/shared/components/components.module';
import { AnnouncementPageModule } from 'src/app/feature/announcement/announcement.module';
import { PinPageModule } from 'src/app/feature/pin/pin.module';
import { reducers } from 'src/app/state/app.states';
import { AuthEffects } from 'src/app/state/effects/auth.effects';
import { DialogService } from 'src/app/core/services/dialog.service';
import { ApplicationService } from 'src/app/core/services/application.service';
import { PushService } from 'src/app/core/services/push.service';
import { RealtimeService } from 'src/app/core/services/realtime.service';
import { AuthService } from 'src/app/core/services/auth.service';
import { SentryService } from 'src/app/core/services/sentry.service';
import { NetworkService } from 'src/app/core/services/network.service';
import { StorageService } from 'src/app/core/services/storage.service';
import { HttpErrorInterceptor } from 'src/app/core/services/http-error.interceptor';
import { SentryIonicErrorHandler } from 'src/app/core/services/sentry-ionic-error-handler';
import { Email } from './core/models/email.model';
import { EmailService } from './core/services/email.service';
@NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [
BrowserModule,
HttpClientModule,
ComponentsModule,
AnnouncementPageModule,
PinPageModule,
NgrxAutoEntityModule,
StoreModule.forRoot(reducers, {
runtimeChecks: {
strictStateImmutability:true,
strictActionImmutability:true,
strictStateSerializability:true,
strictActionSerializability:true
}
}),
EffectsModule.forRoot([AuthEffects]),
StoreDevtoolsModule.instrument({
name: "PMX Ionic"
// In a production build you would want to disable the Store Devtools
// logOnly: environment.production,
}),
IonicModule.forRoot(),
IonicStorageModule.forRoot(),
AppRoutingModule
],
providers: [
StatusBar,
SplashScreen,
Network,
DialogService,
ApplicationService,
PushService,
RealtimeService,
AuthService,
LoaderService,
AppVersion,
SentryService,
NetworkService,
StorageService,
{ provide: HTTP_INTERCEPTORS, useClass: HttpErrorInterceptor, multi: true },
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
// { provide: ErrorHandler, useClass: GlobalErrorHandler }
{ provide: ErrorHandler, useClass: SentryIonicErrorHandler },
{ provide: Email, useClass: EmailService }
],
bootstrap: [AppComponent]
})
export class AppModule {}
Ah, ok. Well, if you have the store imported into your app module, you should be bringing in all the auto-entity state in there as well. Seeing your app module there, it does not appear as though you have actually brought in any of your auto-entity state. So what I would do is this. Anything you have in state.module, put it all in app.module. You seem to have non-entity reducers as well as entity reducers, so you may need to compose reducers to get both included into the StoreModule.forRoot() call. But, I suspect this is the issue...that you've basically configured everything through the one root module, but haven't brought in the state module.
Also do not forget to include EntityEffects
in the EffectsModule.forRoot() call.
Basically, either use a state.module, or bring all your state into app.module, but try not to mix and match the two.
Thanks Jon - I will take a look at this later or tomorrow and will get back to you. Much appreciated!
Sure, no problem!
I've put together a small reproduction repo:
https://github.com/jrista/ngrxae8
The way I currently have things in here, it works. Feel free to pull and fiddle with it. If you can replicate your issue, push it to a new branch and I'll take a look. But I suspect that the way you have your app.module and state.module configured right now is likely the problem.
Thanks!
@richardshergold You might want to edit your app.module post and yank out any keys or tokens. ;)
So if I separate my entityReducers and my non Entity reducers like this:
export const entityReducers: ActionReducerMap<AppState> = {
email:emailReducer
};
export const appReducers = {
application: applicationReducer,
auth: authReducer
};
how do I get both of those reducers into here?
StoreModule.forRoot(entityReducers, { metaReducers: appMetaReducers }),
you will need to use combineReducers
from @ngrx.
Oh ok - thank you so much for your help. I will give it a go in the morning.
It works! I didn't need to combine the reducers using combineReducers though. I just have this now and it seems to be working:
export interface AppState {
email: IEntityState<Email>;
application:ApplicationState;
auth:AuthState;
}
export const reducers: ActionReducerMap<AppState> = {
email: emailReducer,
application:applicationReducer,
auth:authReducer
};
thanks so much for your help
Hey guys,
Please remove me from the email list.
Thanks, James Duffy
On Jun 27, 2019, 11:05 AM -0600, Jon notifications@github.com, wrote:
Ah, ok. Well, if you have the store imported into your app module, you should be bringing in all the auto-entity state in there as well. Seeing your app module there, it does not appear as though you have actually brought in any of your auto-entity state. So what I would do is this. Anything you have in state.module, put it all in app.module. You seem to have non-entity reducers as well as entity reducers, so you may need to compose reducers to get both included into the StoreModule.forRoot() call. But, I suspect this is the issue...that you've basically configured everything through the one root module, but haven't brought in the state module. Also do not forget to include EntityEffects in the EffectsModule.forRoot() call. Basically, either use a state.module, or bring all your state into app.module, but try not to mix and match the two. — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.
Hey guys, Please remove me from the email list. Thanks, James Duffy
James, you must be watching the repo. You would have to unwatch/unfollow to stop getting emails. That wouldn't be something we control.
It works! I didn't need to combine the reducers using combineReducers though. I just have this now and it seems to be working:
export interface AppState { email: IEntityState<Email>; application:ApplicationState; auth:AuthState; } export const reducers: ActionReducerMap<AppState> = { email: emailReducer, application:applicationReducer, auth:authReducer };
thanks so much for your help
Glad you got it working! The above does indeed look correct to me. You usually want all your shared state configured in the root state interface and mapped in the main reducer map. Let me know if you have any other issues, but hopefully you can start rolling now.
I'm developing an Ionic/Angular app and giving NgRx-Auto a try. The project is using Angular 8 and NgRx 8. I think I have set everything up correctly but when I load a component and try the loadAll() method in the facade I get the error:
My Model:
My Service:
My facade:
My email.state:
My Component:
Full Error Log:
No doubt I am doing something wrong! Any ideas?