Pull-based cross-window communication for multi-window angular applications
- Send messages between different tabs/windows that are running the angular app
- Message receive notification for sending tab/window
- Automatic detection/registration of new tabs/windows
First you need to install the npm module:
npm install ngx-multi-window --save
Then add the NgxMultiWindowModule
to the imports array of your application module:
import {NgxMultiWindowModule} from 'ngx-multi-window';
@NgModule({
imports: [
/* Other imports here */
NgXMultiWindowModule
]
})
export class AppModule {
}
Finally you need to specify how your application should load the ngx-multi-window library:
All the compiled JavaScript files use ES2015 module format, so they are ready for usage with RollupJS. However, you cannot use them with SystemJS.
.metadata.json
files are generated for usage with Angular AoT compiler.
UMD bundles are available for SystemJS loading. Example:
System.config({
paths: {
'npm:': 'node_modules/'
},
map: {
app: 'app',
'@angular/core' : 'npm:@angular/core/bundles/core.umd.js',
'@angular/common' : 'npm:@angular/common/bundles/common.umd.js',
// further angular bundles...
'ngx-multi-window': 'npm:ngx-multi-window/bundles/ngx-multi-window.umd.js',
rxjs: 'npm:rxjs',
},
packages: {
app : {defaultExtension: 'js', main: './main.js'},
rxjs: {defaultExtension: 'js'}
}
});
Inject the MultiWindowService
into your component or service.
import {MultiWindowService} from 'ngx-multi-window';
export class AppComponent {
constructor(private multiWindowService: MultiWindowService) {
// use the service
}
}
Every window has a unique, unchangeable id which can be accessed via multiWindowService.id
.
In addition to that every window as a changeable name which can be get/set
via multiWindowService.name
.
Receive messages addressed to the current window by subscribing to the observable returned from
multiWindowService.onMessages()
:
import { MultiWindowService, Message } from 'ngx-multi-window';
class App {
constructor(private multiWindowService: MultiWindowService) {
multiWindowService.onMessage().subscribe((value: Message) => {
console.log('Received a message from ' + value.senderId + ': ' + value.data);
});
}
}
Send a message by calling multiWindowService.sendMessage()
:
import { MultiWindowService, WindowData, Message } from 'ngx-multi-window';
class App {
constructor(private multiWindowService: MultiWindowService) {
const recipientId: string; // TODO
const message: string; // TODO
multiWindowService.sendMessage(recipientId, 'customEvent', message).subscribe(
(messageId: string) => {
console.log('Message send, ID is ' + messageId);
},
(error) => {
console.log('Message sending failed, error: ' + error);
},
() => {
console.log('Message successfully delivered');
});
}
}
The message returns an observable which will resolve with a message id once the message has been send (= written to local storage).
The receiving window will retrieve the message and respond with a MessageType.MESSAGE_RECEIVED
typed message.
The sending window/app will be informed by finishing the observable.
In case no MessageType.MESSAGE_RECEIVED
message has been received by the sending window
within a certain time limit (MultiWindowConfig.messageTimeout
, default is 10s)
the message submission will be canceled. The observable will be rejected and the
initial message will be removed from the current windows postbox.
To get the names and ids of other window/app instances the MultiWindowService
offers two methods:
multiWindowService.onWindows()
returns an observable to subscribe to in case you require periodic updates of the
fellow windows. The observable will emit a new value every time the local storage has been scanned fpr the windows.
This by default happens every 5 seconds (MultiWindowConfig.newWindowScan
).
Use multiWindowService.getKnownWindows
to return an array of WindowData
.
No special handling is necessary to open new windows. Every new window/app will register itself
by writing to its key in the local storage. Existing windows will identify new windows
after MultiWindowConfig.newWindowScan
at the latest.
The MultiWindowService
offers convenient method newWindow()
which provides details for the
new window's start url. If used the returned observable can be utilized to get notified
once the new window is ready to consume/receive message.
This library is based on "pull-based" communication. Every window periodically checks the local storage for messages addressed to itself. For that reason every window has its own key in the local storage, whose contents/value looks like:
{"heartbeat":1508936270103,"id":"oufi90mui5u5n","name":"AppWindow oufi90mui5u5n","messages":[]}
The heartbeat is updated every time the window performed a reading check on the other window's local storage keys.
Sending message from sender A to recipient B involves the following steps:
- The sender A writes the initial message (including the text and recipient id of B) into the "messages" array located at its own local storage key
- The recipient window B reads the messages array of the other windows and picks up a message addressed to itself
- B places a "MESSAGE_RECEIVED" message addressed to A in its own messages array
- A picks up the "MESSAGE_RECEIVED" message in B's message array and removes the initial message from its own messages array
- B identifies that the initial message has been removed from A's messages array and removes the receipt message from its own messages array
The demo subfolder contains a project created with angular-cli that has been adapted to showcase the functionality of ngx-multi-window. Run the demo app by checking out that repository and execute the following command in the project root directory:
npm run demo
This will perform the following steps:
// Install the ngx-multi-window library
npm install
// Change into the example website folder
cd demo/
// Uninstall the current ngx-multi-window version
npm uninstall ngx-multi-window
// Install the demo website's dependencies
npm install
// Run the server
ng serve
- Tests and cross browser testing