{"id":22662725,"url":"https://github.com/Andreas-Hjortland/ngxs-message-plugin","last_synced_at":"2025-08-06T10:32:40.128Z","repository":{"id":49761642,"uuid":"490712726","full_name":"Andreas-Hjortland/ngxs-message-plugin","owner":"Andreas-Hjortland","description":"An NGXS plugin which allows you to share state between different browser contexts","archived":false,"fork":false,"pushed_at":"2024-12-02T11:31:37.000Z","size":1314,"stargazers_count":3,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-12-02T11:41:22.542Z","etag":null,"topics":["angular","library","messaging","ngxs","popup","popup-window"],"latest_commit_sha":null,"homepage":"https://andreas-hjortland.github.io/ngxs-message-plugin/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Andreas-Hjortland.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-10T13:38:05.000Z","updated_at":"2024-12-02T11:31:41.000Z","dependencies_parsed_at":"2024-12-02T19:05:29.514Z","dependency_job_id":null,"html_url":"https://github.com/Andreas-Hjortland/ngxs-message-plugin","commit_stats":{"total_commits":37,"total_committers":4,"mean_commits":9.25,"dds":0.5135135135135135,"last_synced_commit":"379bc3b6ea9cb80a9c7a11723a0b64917e7fae1a"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Andreas-Hjortland%2Fngxs-message-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Andreas-Hjortland%2Fngxs-message-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Andreas-Hjortland%2Fngxs-message-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Andreas-Hjortland%2Fngxs-message-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Andreas-Hjortland","download_url":"https://codeload.github.com/Andreas-Hjortland/ngxs-message-plugin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228886856,"owners_count":17986899,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","library","messaging","ngxs","popup","popup-window"],"created_at":"2024-12-09T12:02:03.123Z","updated_at":"2024-12-09T12:02:04.515Z","avatar_url":"https://github.com/Andreas-Hjortland.png","language":"TypeScript","funding_links":[],"categories":["State Management"],"sub_categories":["NGXS"],"readme":"# NgxsMessagePlugin\n\n[![Build status](https://github.com/Andreas-Hjortland/ngxs-message-plugin/actions/workflows/build.yml/badge.svg)](https://github.com/Andreas-Hjortland/ngxs-message-plugin/actions/workflows/build.yml)\n[![npm](https://img.shields.io/npm/v/ngxs-message-plugin.svg)](https://www.npmjs.com/package/ngxs-message-plugin)\n[![npm](https://img.shields.io/npm/dm/ngxs-message-plugin.svg)](https://www.npmjs.com/package/ngxs-message-plugin)\n[![npm](https://img.shields.io/npm/l/ngxs-message-plugin.svg)](https://www.npmjs.com/package/ngxs-message-plugin)\n\nAn Ngxs plugin that allows you to synchronize state across different browser contexts.\n\nThis allows you to use the same state in an iframe or popup window, and dispatch actions which will transparently run on\nthe state host and update every app that subscribes to the state. For instance this makes it easier to manage state\nif you can detach elements from your app to a separate window.\n\nCheck out the sample app at https://andreas-hjortland.github.io/ngxs-message-plugin/ (or check out the source code in [projects/testapp](projects/testapp))\n\n## Installation and usage\n\nFirst you need to install the npm module:\n\n```bash\nnpm install ngxs-message-plugin --save\n```\n\nThen you need to include the module in your host and child apps.\n\n### Host\n\nFor modules you use the following syntax:\n\n```ts\n@NgModule({\n    imports: [\n        NgxsMessagePlugun.forRoot();\n    ]\n})\nexport class AppModule { }\n```\n\nFor standalone components you do it like this:\n```ts\nbootstrapApplication(AppComponent, {\n  // ...\n  providers: [\n    // ...\n    provideStore(\n      [RootState1, RootState2, ...],\n      {\n        // ...\n        developmentMode: !environment.production // optional\n      },\n      withNgxsMessagePlugin(/*isHost:*/ true);\n    )\n  ]\n})\n```\nThe `isHost` parameter on the plugin selects if we are the host component or a child component and should be true for\nthe host instance and false for the children.\n\n### Child (popup / iframe)\n\n```ts\n@NgModule({\n    imports: [\n        NgxsMessagePlugun.forChild();\n    ]\n})\nexport class AppModule { }\n```\n\nFor standalone components you do it like this:\n```ts\nbootstrapApplication(AppComponent, {\n  // ...\n  providers: [\n    // ...\n    provideStore(\n      [RootState1, RootState2, ...],\n      {\n        // ...\n        developmentMode: !environment.production // optional\n      },\n      withNgxsMessagePlugin(/*isHost:*/ false);\n    )\n  ]\n})\n```\n\nYou can then do `window.open('path/to/child/entrypoint')` and see that the state is the same in both the child and the\nhost state. You can also dispatch actions from the child state and they will be evaluated on the host store.\n\n## Configuration\n\nIf you need to customize the module, the `forRoot` / `forChild` functions can take an optional configuration object. For\ninstance if you want to synchronize the state between all open windows on the origin, you can use the `BroadcastChannel`\nmessage transport, or maybe you want to create your own message transport that uses web sockets to synchronize the state\nwith another browser alltogether. To configure the module, do like this\n\n```ts\n@NgModule({\n    imports: [\n        NgxsMessagePlugun.forRoot({\n            messageHandler: 'broadcast',\n            broadcastChannelName: 'myChannel', // this is what separates messages from different instances of the app\n            debounce: 100,\n        });\n    ]\n})\nexport class AppModule { }\n```\n\nIf you are using standalone mode, you configure it like this\n\n```ts\nbootstrapApplication(AppComponent, {\n  // ...\n  providers: [\n    // ...\n    provideStore(\n      [ /* ... */ ],\n      { /* ... */ },\n      withNgxsMessagePlugin(true /* or false if client */, {\n        messageHandler: 'broadcast',\n        broadcastChannelName: 'myChannel', // this is what separates messages from different instances of the app\n        debounce: 100,\n      });\n    )\n  ]\n})\n```\n\nYou can check out all the configuration options in [`symbols.ts`](projects/ngxs-message-plugin/src/lib/symbols.ts), but\nthe most important options are `messageHandler` which lets you configure how the messages are passed between instances.\nThe default is `port` which will register any popup window or frame that is opened on the same domain with the opener\nstate. You can also roll your own by providing an implementation of `MessageCommunicationService`. Another potentially\nuseful configuration option is `debounce` which tells how long to debounce before we actually calculate the state\ndiff and transfer it to the clients. Default is 100 milliseconds.\n\n## Test app\n\nThe test app is a simple demo app which highlights how to use the library and demos that both the state and actions are\ntransparently handled. Here you can also see that we are using the `KNOWN_ACTION` injection token to help the host\ndeserialize the actions since we are using `instanceof` in the [`counter.state.ts`](projects/testapp/src/app/counter/counter.state.ts)\n\nTo start the test app, just check out the project, install dependencies using `npm install` and start it using `npm start`\n\n## Known issues, limitations and potential improvements\n\n- If you are auto generating the action type names, you have to ensure that the action type name is the same on both the\n  store owner and consumer.\n  - For the ngxs emitter plugin, you will have to supply the action type in the `@Receiver` decorator.\n- If you are relying on the `instanceof` operator in your reducers, you will have to register the action class with the\n  `KNOWN_ACTION` injection token or through the `knownActions` configuration parameter on the host. This lets the plugin\n  map actions from the clients so that we can re-apply the prototype after deserializing the objects\n- The state must be serializable and clonable using the structured clone algorithm. This is already best practice, but\n  anything in the store not serializable will be ignored.\n- On the children, you should not add any other plugins that modify the state because that may or may not be caught\n  by the message plugin and therefore lost. That is not a problem on the host.\n\n## Contributions\n\nAll contributions are welcome (both issues and pull requests) as long as we keep a civil tone :)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAndreas-Hjortland%2Fngxs-message-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAndreas-Hjortland%2Fngxs-message-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAndreas-Hjortland%2Fngxs-message-plugin/lists"}