Opening the same application in multiple tabs should not require every form, loading flag, or selection to become shared state. Chapter 13 shows how Tab Sync keeps finalized FeatureCell State aligned across same-origin tabs while transient presentation state remains local.
You will configure the Tab Sync behavior and controller once, open a second browser tab, and observe committed character State move between tabs. The boundary is deliberate: this is browser coordination, not server-authoritative collaboration, cross-device synchronization, or conflict-resolution infrastructure.
Key takeaway: Begin with the completed Chapter 7 project. Chapter 13 changes configuration, presentation, and tests; the existing service and component do not add their own cross-tab messaging code.
Why Shared Feature State Should Not Mean Shared Forms
People often open the same application twice: a preference changes in one tab, a draft remains open in another, or an administrative view needs the latest committed record. The useful question is not whether every piece of UI should be synchronized. It is which values belong to the feature boundary and which values belong only to the page that is currently presenting it.
Tab Sync shares finalized Feature State while each tab retains its own selection, form, loading, and error experience. That lets a second tab see a committed character collection without inheriting an unfinished edit from the first tab.
| State surface | Tab Sync decision |
|---|---|
| Finalized FeatureCell value | Shared with matching same-origin tabs. |
| Selection and unsaved form values | Remain local to the tab where they are being edited. |
| Loading and error presentation | Remain local transient UI state. |
| Server authority and cross-device recovery | Not provided by browser Tab Sync. |
Configure Tab Sync at the FeatureCell Boundary
Tab Sync is a pair: the behavior broadcasts finalized snapshots to other browser tabs, and the controller coordinates initial snapshot negotiation when a new tab opens. Register both on the same FeatureCell key. The behavior belongs in the behaviors array, while the controller belongs in the controllers array.
The service and component keep their original responsibilities. The configuration owns cross-tab coordination, so the feature does not need a second messaging service or a collection of tab-specific event handlers.
// app.config.ts import { ApplicationConfig } from '@angular/core'; import { provideVault, provideFeatureCell } from '@sdux-vault/angular'; import { withTabSyncStateBehavior, withTabSyncController } from '@sdux-vault/core'; import { EmployeeService } from './employee.service'; export const appConfig: ApplicationConfig = { providers: [ provideVault({ logLevel: 'off' }), provideFeatureCell( EmployeeService, { key: 'employees', initialState: [] }, [ // Enable cross-tab state synchronization withTabSyncStateBehavior ], [ // Tab Sync Controller handles initial negotiation withTabSyncController ] ) ] }; // employee.service.ts import { Injectable } from '@angular/core'; import { FeatureCell, injectVault } from '@sdux-vault/angular'; import { Employee } from './employee.shape'; @FeatureCell<Employee[]>('employees') @Injectable({ providedIn: 'root' }) export class EmployeeService { readonly vault = injectVault<Employee[]>(EmployeeService); constructor() { this.vault.initialize(); } addEmployee(): void { // State is committed locally and broadcast to other tabs this.vault.mergeState({ value: [{ id: 1, name: 'Jane Doe' }] }); } } Warning: Pro capability: Tab Sync requires a valid Pro license for production use. The tutorial's development configuration is an evaluation convenience, not a production licensing model.
Verify Finalized State Across Same-Origin Tabs
A same-origin tab is one using the same scheme, host, and port. The FeatureCell key also has to match. Once those boundaries line up, one tab can commit a character update and the other tabs can observe the resulting State without any component-to-component messaging.
The new tab also performs initial snapshot negotiation. If a peer has a committed snapshot, the new tab can adopt it rather than presenting only its bootstrap value. That negotiation is separate from the ongoing propagation of later finalized State changes.
// Tab A commits state this.vault.mergeState({ value: [{ id: 1, name: 'Jane Doe' }] }); // Tab B automatically receives the updated snapshot this.vault.state$.subscribe(snapshot => { console.info(snapshot.value); // → [{ id: 1, name: 'Jane Doe' }] }); Key takeaway: What to look for: committed FeatureCell State values are preserved and updated between tabs, including shared resets. Forms, selection, loading, errors, and other page interactions remain local to the tab where they occur. A failed pipeline attempt does not update a peer tab.
Keep Selection and Unsaved Forms Local
The most useful Tab Sync test is a stale-form exercise. Leave an unsaved edit open in Tab B, commit a change in Tab A, and return to Tab B. The committed collection should update, but Tab B's transient form should remain under Tab B's control.
This separation keeps a peer's committed data fresh without pretending that the peer intended to submit your local edit. Cancel the stale form before continuing, then repeat the exercise with a deliberate save so the application can demonstrate its normal record-level update rules.
| Step | Observation |
|---|---|
| Tab A | Commit an add, edit, delete, or reset. |
| Tab B | Observe the committed collection update. |
| Tab B form | Confirm an unsaved edit remains local and is not overwritten. |
| Failed attempt | Confirm a peer tab remains unchanged. |
What Tab Sync Does Not Provide
Tab Sync is same-origin browser coordination. It is useful when several open tabs need the same committed feature value, but it does not turn browser tabs into a transactional collaboration system.
- It does not provide server authority or authorization.
- It does not synchronize State across devices.
- It does not provide offline reconciliation or audit history.
- It does not resolve every collaborative editing conflict.
- It does not make transient form state globally shared.
Environment support also matters. If the browser does not provide the required storage or messaging mechanism, Tab Sync degrades to ordinary single-tab Core State. The same FeatureCell configuration can therefore run in SSR, Node.js, Deno, or web workers without application code adding conditional feature detection.
Warning: Scope boundary: use Tab Sync for same-origin coordination. Choose a server-authoritative design when the application needs identity, authorization, cross-device recovery, audit history, or durable conflict resolution.
Chapter 13 Round-up
Your Tab Sync example is complete when the behavior and controller are registered together in app.config.ts and the View Tab Sync action lets you observe committed character State moving between tabs. The existing service and component continue to own their original responsibilities.
- Cross-tab coordination is structural configuration, not component or service logic.
- Each tab keeps its local form and presentation State while sharing the finalized FeatureCell value.
- The same FeatureCell key identifies the State that participates in synchronization.
Read the Tab Sync Controller documentation, the Tab Sync Behavior documentation, and the withTabSyncController reference for the complete configuration and environment notes.
