[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report
[ ] Feature #request
[ ] Documentation issue or request
[ x] Support request
Hello All!
I am here because I need some support on something I need to do.
I am working on a project using NG4 + ngrx/store. We are integrating NG4 modules into existing webapp and so we are bootstrapping several modules in dynamic tags:
platformBrowserDynamic().bootstrapModule(App1Module)); // bootstrap AppModule in '<app1>'
platformBrowserDynamic().bootstrapModule(App2Module); // bootstrap AppModule in '<app2>'
App1 and App2 are basically 2 features (Search and display results for example). They are not in the same tree and not in the same app. They can't communicate through Angular.
I would like to be able to share store between 1 and 2.
Is it possible?
Do I need to have 2 states?
Do I need to pass actions from 1 to 2?
Do you have any advise, hint, how it is possible to achieve that?
I was thinking of having 2 stores, and sync actions between apps, like here for example:
https://medium.com/@Scarysize/syncing-redux-stores-across-browser-tabs-fff04f975423
Many thanks!
Pierre
Ok so I dig it up at little further.
I am going to use a middleware that will dispatch all actions to other Angular app using legacy JS communication bus. In each app I will have a service that listen to this bus and dispatch actions.
Each app will have their own store. The drawback is that state will be replicated into each app. I am afraid that will not be scalable..
It will not follow the one single store principle, but it will be easier to implement.
Another option would be to use the StoreModule.forRoot().providers in the platformBrowserDynamic() function which takes an array of providers to share the Store across bootstrapped applications.
OK, thank you @brandonroberts I will have a look at this option.
I have just tried it, and really thank you for this tips, it is perfect!
@brandonroberts Could you share an example of this? I tried it out, and Angular complained that some of the providers in the ModuleWithProviders instance's providers were not instances of Provider or Type.
platformBrowserDynamic().bootstrapModule(AppModule, {providers: store.providers})
Uncaught Error: Invalid provider - only instances of Provider and Type are allowed, got: function ActionsSubject() {
return _super.call(this, { type: INIT }) || this;
}
I also tried importing the ModuleWithProviders (resulting from calling StoreModule.forRoot(reducers)) directly into a second angular app, with this result:
Uncaught Error: Can't resolve all parameters for _createStoreReducers: ([object Object], [object Object], ?).
My goal here is to share a store between two Angular apps. One app is in a child window running in the same process, and can reference objects (including a traditional redux store) directly through window.opener.
@SmithPR sure. You supply the providers at the platform level and bootstrap both apps with the same platform. Your main.ts would look something like this.
import './polyfills.ts';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';
import { AppModule1 } from './app/app.module1';
import { AppModule2 } from './app/app.module2';
import { StoreModule } from '@ngrx/store';
import { reducers } from './reducers';
if (environment.production) {
enableProdMode();
}
const platform = platformBrowserDynamic(StoreModule.forRoot(reducers).providers);
platform.bootstrapModule(AppModule1);
platform.bootstrapModule(AppModule2);
@brandonroberts Thanks for taking the time to reply on a closed issue. I tried your approach out, and it does not seem to have made the jump between windows successfully.
I'm getting an error when bootstrapping the app in the child window of "Uncaught Error: No NgModule metadata found for 'ChildAppModule'."
(With the root module for the child app, which has the same basic annotations it has worked with before.)
I would assume that the PlatformRef instance just isn't portable between different 'window' contexts, but am I wrong there? I'm also compiling and building these apps separately using the multi-app feature of the CLI.
I would like to add another point with this solution:
Bootstrapping module this way will create 2 NgZone. Change detection will work from AppModule1 to AppModule2, but not the other way.
What we ended up doing, is using a private method:
_bootstrapModuleWithZone instead of bootstrapModule. We create zone ourselves and then pass it as 2nd argument of the private method.
The platformBrowserDynamic and bootstrap methods now take array of StaticProvider and is no longer compatible with the reflective providers defined in StoreModule.forRoot({}).providers.
@brandonroberts Is there an alternative?
Can we provide the StoreModule.forRoot({}) at platform level in angular 6/7 and ngrx 4 when two different angular app/elements on the same page ?
Did anybody find appropriate solution for this problem? Just looking here if this scheme for shared store and two apps could work?
Most helpful comment
The platformBrowserDynamic and bootstrap methods now take array of StaticProvider and is no longer compatible with the reflective providers defined in StoreModule.forRoot({}).providers.
@brandonroberts Is there an alternative?