https://some-angular-m3e-components.pages.dev/
frontend material angular
0

Configure Feed

Select the types of activity you want to include in your feed.

README.md

Optional Router navigator#

Import from @fairylights-studio/ngx-m3-adaptive/router. Only applications using this secondary entrypoint need Angular Router.

Architecture: Shareable URLs & In-Memory Shadow Stack#

The router integration decouples the browser URL from session history:

  • Shareable URL: The URL strictly reflects only the currently active Destination (e.g. ?pane=primary:42), never a serialized history trail. URLs can be copied, sent to colleagues, or bookmarked.
  • In-Memory Shadow Stack: Complete Material 3 navigation history and BackBehavior policies (PopLatest, PopUntilScaffoldValueChange, etc.) are maintained in memory during the active session.
  • Synthetic Root: Opening an external deep link directly seeds the shadow stack with a fallback root beneath the active destination, so in-app Back navigation never encounters a dead end.
  • Clean Root URL: At the root destination (e.g. Inbox list), the query parameter is omitted entirely (e.g. /inbox).
  • Workspace Memory: The in-memory MatPaneRouteMemoryService caches workspace state keyed by an explicit cacheKey, safely restoring the user's selected pane when switching between top-level routes without cross-tenant collisions.
  • Template Helpers: navigator.queryParamsFor(pane, key) and navigator.linkCommandsFor(pane, key) allow seamless integration with native <a [routerLink]> elements.

Usage#

import {
  createMatPaneQueryParamCodec,
  createMatPaneRouterNavigator,
  matPaneGuard,
} from '@fairylights-studio/ngx-m3-adaptive/router';

@Component({
  ...
})
export class MessagesComponent {
  readonly navigator = createMatPaneRouterNavigator(
    createMatPaneQueryParamCodec({
      queryParam: 'pane',
      fallbackRoot: { pane: 'secondary', contentKey: null },
    }),
    {
      cacheKey: 'inbox-messages', // Or dynamic: (snapshot) => `${snapshot.params['orgId']}:inbox`
    },
  );
}

Route Guard#

Validate pane query parameters and reject malformed/unknown roles at the route level:

export const routes: Routes = [
  {
    path: 'inbox',
    component: MessagesComponent,
    canActivate: [matPaneGuard],
  },
];

Enable middle-click (open in new tab) and right-click (copy link) with native hyperlinks:

<a [routerLink]="[]" [queryParams]="navigator.queryParamsFor('primary', message.id)">
  {{ message.subject }}
</a>

Query-param Wire Format#

Destination Encoded Query Parameter Rendered URL
{ pane: 'secondary', contentKey: null } (Root) (omitted) /inbox
{ pane: 'primary', contentKey: null } ?pane=primary /inbox?pane=primary
{ pane: 'primary', contentKey: 'msg-42' } ?pane=primary:msg-42 /inbox?pane=primary:msg-42
{ pane: 'primary', contentKey: 'key:with:colons' } ?pane=primary:key%3Awith%3Acolons /inbox?pane=primary:key%3Awith%3Acolons