DEV Community

Cover image for How to Use ๐Ÿงจ Dynamic Titles from NgRx Selectors
David
David

Posted on

How to Use ๐Ÿงจ Dynamic Titles from NgRx Selectors

When Angular 14 released and custom title strategies became a possibility, my mind immediately went to asking, "how can I dynamically set a page's title from a selector?"

I wrote an RFC in the NgRx community to pitch an API for doing this. I'd like to explain how it works, and how you can leverage it today (whether or not it joins an @ngrx/* package).

Example of configuring a dynamic title

All the code for the following example can be found in this StackBlitz demo.

Say I have a website where I can enter the name of an "action" in an input, and then "do" it by clicking a "Do Action" button.

Blank field titled "Action" to the left of a button titled "Do Action"

When I click "Do Action", the title of my page reflects how many seconds have passed since the "action" was done.

Webpage tab above the form says "6 Seconds Since Accident"

In my Angular app routes, I have the route for the page configured using a tag function called ngrxTitle that allows me to inline selectors into a string.

const routes: Routes = [
  {
    path: '',
    component: AppComponent,
    title: ngrxTitle`${counterFeature.selectCount} Seconds Since ${counterFeature.selectEvent}`,
  },
];
Enter fullscreen mode Exit fullscreen mode

The selector counterFeature.selectCount selects the number of seconds since the button was clicked, while counterFeature.selectEvent selects the name of the action entered in the input when the button was clicked. Using ngrxTitle, I can templatize the title to include the latest results of multiple selectors like these.

ngrxTitle Implementation

ngrxTitle is a tag function that processes a template literal with selectors.

For every selector, it generates a unique ID and replaces the selector with the string 'NgRxTitleSelector${ID}'.

For example, when I ran my app, the title template literal was generated into the string 'NgRxTitleSelector${f35ace1e-28d8-4dc6-850a-f0900315ca8a} Seconds Since NgRxTitleSelector${40b2582b-832a-44f5-b6ce-f650518db278}'.

Angular 14 allows developers to implement custom "title strategies". A TitleStrategy is a class with an updateTitle method that is called each time the route changes. This gives us the opportunity to change the title any way desired.

That means we can process the title template generated by ngrxTitle and subscribe the selectors referenced by the template to produce a new title.

The NgRxTitleStrategy starts with this basic structure:

export class NgRxTitleStrategy extends TitleStrategy {

  private titleSubscription: Subscription | undefined;

  updateTitle(snapshot: RouterStateSnapshot): void {
    // Each time the route changes, cancel the last subscription
    this.titleSubscription?.unsubscribe();

    // Get the title using the base method
    // When using ngrxTitle, this will be the special template string
    const titleTemplate = this.buildTitle(snapshot);
    // Create an Observable of the title built from the template
    const title$ = this.selectTitleFromTemplate(titleTemplate);
    // Continuously update the title as the selectors emit new values
    this.titleSubscription = title$.subscribe((t) => this.title.setTitle(t));
  }
}
Enter fullscreen mode Exit fullscreen mode

In the app module, we can utilize the new title strategy in the providers.

@NgModule({
  declarations: [AppComponent],
  providers: [{
    provide: TitleStrategy,
    useClass: NgRxTitleStrategy,
  }],
  imports: [
    /* ... */
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

Full implementation

See the gist below for the full implementation.

Top comments (0)