I'm working on a project using the old NgModules architecture and I'm transitioning into the new standalone components gradually. I'm stuck right now on how to provide the root store to the standalone component. I'm still bootstrapping the application using app.module so I'm not able to use bootstrapApplication in the app.module. If I use provideStore(reducers, {metaReducers}) I get error that the store was already declared.
app.module
@NgModule({
declarations: [
AppComponent,
ErrorPageComponent,
FallbackComponent,
ShouldLoginComponent
],
imports: [
BrowserAnimationsModule,
BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
BrowserModule,
HttpClientModule,
IdentityModule.forRoot(),
CoreModule,
StoreModule.forRoot(reducers, {metaReducers}), <-- the root store
...
],
bootstrap: [AppComponent]
})
export class AppModule { }
reducers.ts
export interface AppState {
activities: ActivityState,
auth: AuthState,
chatflows: ChatFlowsState,
kb: KbState,
layout: LayoutState,
properties: PropertiesState,
router: RouterReducerState<any>;
savedreplies: SavedRepliesState,
settings: SettingsState,
tickets: TicketsState,
visitors: VisitorState
}
export const reducers: ActionReducerMap<AppState> = {
activities: activityReducer,
auth: authReducer,
chatflows: chatFlowsReducer,
kb: KbStateReducer,
layout: layoutReducer,
properties: propertiesReducer,
router: routerReducer,
savedreplies: savedRepliesReducer,
settings: settingsReducer,
tickets: TicketsStateReducer,
visitors: visitorsReducer
};
export const metaReducers: MetaReducer<AppState>[] = [];
routes
const routes: Routes = [
{
path: '',
component: BaseComponent,
children: [
{
path: 'conversations',
canActivate: [IdentityGuardWithForcedLogin],
loadComponent: () => import('../conversations/conversations.components').then(m => m.ConversationsComponent),
providers: [
provideStore(reducers, {metaReducers}), <-- getting an error duplicate store
provideEffects([ActivityEffects, VisitorsEffects, TicketsEffects]),
]
},
{
path: 'live',
canActivate: [IdentityGuardWithForcedLogin],
loadChildren: () => import('../live/live.module').then(m => m.LiveModule)
},
{
path: 'dashboard',
canActivate: [IdentityGuardWithForcedLogin],
load children: () => import('../dashboard/dashboard.module').then(m => m.DashboardModule)
},
conversations.component.ts
@Component({
selector: 'conversations',
templateUrl: './conversations.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [VisitorsComponent, MessagesComponent, InfoComponent]
})
export class ConversationsComponent{
constructor(
private store: Store<AppState>, <-- injecting the root store here
private inboxService: ConversationsService,
private modalService: NgbModal,
) {
...
You can just use provideStore
directly in the AppModule
.
@NgModule({
declarations: [
AppComponent,
ErrorPageComponent,
FallbackComponent,
ShouldLoginComponent
],
imports: [
BrowserAnimationsModule,
BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
BrowserModule,
HttpClientModule,
IdentityModule.forRoot(),
CoreModule,
provideStore(reducers, {metaReducers}), // <-- the root store
provideEffects([ActivityEffects, VisitorsEffects, TicketsEffects]), // <-- the root effects
...
],
bootstrap: [AppComponent]
})
export class AppModule { }
Then we can remove it from the routing:
const routes: Routes = [
{
path: '',
component: BaseComponent,
children: [
{
path: 'conversations',
canActivate: [IdentityGuardWithForcedLogin],
loadComponent: () => import('../conversations/conversations.components').then(m => m.ConversationsComponent),
},