CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ember-page-title

Page title management for Ember.js applications with dynamic updates, FastBoot compatibility, and TypeScript support

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

page-title-service.mddocs/

Page Title Service

The page-title service provides programmatic control over title management with a token-based system, inheritance, and lifecycle hooks.

Capabilities

Page Title Service

Core service managing page title tokens and DOM updates.

/**
 * Service for managing page titles through a token-based system
 */
class PageTitleService extends Service {
  /** Array of all registered title tokens */
  tokens: PageTitleToken[];
  
  /** Default configuration for new tokens */
  _defaultConfig: PageTitleConfig;
  
  constructor(owner: Owner);
  
  /** Add or update a title token */
  push(token: PageTitleToken): void;
  
  /** Remove a token by its ID */
  remove(id: string): void;
  
  /** Schedule a title update on the next run loop cycle */
  scheduleTitleUpdate(): void;
  
  /** Generate the final title string from all tokens */
  toString(): string;
  
  /** Hook called after title updates (override in subclass) */
  titleDidUpdate(title: string): void;
  
  /** Update title in FastBoot environment */
  updateFastbootTitle(title: string): void;
  
  /** Apply default configuration to a token */
  applyTokenDefaults(token: PageTitleToken): void;
  
  /** Inherit properties from previous token in chain */
  inheritFromPrevious(token: PageTitleToken): void;
  
  /** Get tokens that should be displayed (respects replace behavior) */
  get visibleTokens(): PageTitleToken[];
  
  /** Get tokens in final display order (respects front, prepend, append) */
  get sortedTokens(): PageTitleToken[];
  
  /** Called when service is destroyed - cleanup router listeners */
  willDestroy(): void;
}

Service Usage:

import Component from '@glimmer/component';
import { service } from '@ember/service';
import type PageTitleService from 'ember-page-title/services/page-title';

export default class MyComponent extends Component {
  @service('page-title') declare pageTitle: PageTitleService;
  
  updateTitle() {
    // Add a title token programmatically
    this.pageTitle.push({
      id: 'my-component-title',
      title: 'Dynamic Title',
      separator: ' - ',
      prepend: true
    });
  }
  
  removeTitle() {
    // Remove a specific token
    this.pageTitle.remove('my-component-title');
  }
}

Token Management

The service manages titles through a token-based system with automatic ordering and inheritance.

/**
 * Add or update a title token in the service
 * @param token - Token to add or update
 */
push(token: PageTitleToken): void;

/**
 * Remove a token by its unique ID
 * @param id - Unique identifier of token to remove
 */
remove(id: string): void;

/**
 * Schedule a title update on the next afterRender run loop cycle
 */
scheduleTitleUpdate(): void;

Token System Examples:

// Add a basic token
this.pageTitle.push({
  id: 'main-title',
  title: 'My Application',
  separator: ' | '
});

// Add a token that replaces others
this.pageTitle.push({
  id: 'error-title', 
  title: 'Error Occurred',
  replace: true
});

// Add a token that always goes first
this.pageTitle.push({
  id: 'priority-title',
  title: 'URGENT',
  front: true
});

// Remove a specific token
this.pageTitle.remove('main-title');

Title Generation

The service generates final title strings through a sophisticated ordering and inheritance system.

/**
 * Generate the final title string from all tokens
 * @returns Complete title string ready for DOM
 */
toString(): string;

/**
 * Get tokens that should be displayed (respects replace behavior)
 * @returns Array of visible tokens
 */
get visibleTokens(): PageTitleToken[];

/**
 * Get tokens in final display order
 * @returns Array of tokens in display order
 */  
get sortedTokens(): PageTitleToken[];

Title Composition Logic:

  1. Visibility: Tokens marked with replace: true hide previous tokens
  2. Ordering: Tokens are sorted by front, prepend, and append behavior
  3. Joining: Final string joins token titles with their separators
// Example token processing
const tokens = [
  { id: '1', title: 'Home', separator: ' | ' },
  { id: '2', title: 'Products', separator: ' | ' }, 
  { id: '3', title: 'Laptop', separator: '' }
];

// Result: "Home | Products | Laptop"
console.log(this.pageTitle.toString());

Lifecycle Hooks

The service provides hooks for custom integration and monitoring.

/**
 * Hook called after title updates - override for custom behavior
 * @param title - The new title that was set
 */
titleDidUpdate(title: string): void;

Custom Service Extension:

// app/services/page-title.js
import PageTitleService from 'ember-page-title/services/page-title';

export default class extends PageTitleService {
  titleDidUpdate(title) {
    super.titleDidUpdate(title);
    
    // Custom logic after title changes
    console.log('Title updated:', title);
    
    // Track analytics
    if (window.gtag) {
      window.gtag('config', 'GA_MEASUREMENT_ID', {
        page_title: title
      });
    }
    
    // Update meta tags
    document.querySelector('meta[property="og:title"]')
      ?.setAttribute('content', title);
  }
}

Configuration and Defaults

The service applies configurable defaults to new tokens.

/**
 * Apply default configuration to a token
 * @param token - Token to apply defaults to
 */
applyTokenDefaults(token: PageTitleToken): void;

/**
 * Inherit properties from previous token in chain
 * @param token - Token to inherit properties for
 */
inheritFromPrevious(token: PageTitleToken): void;

/** Default configuration for new tokens */
_defaultConfig: PageTitleConfig;

Default Configuration:

The service reads defaults from config/environment.js:

// config/environment.js
module.exports = function(environment) {
  return {
    pageTitle: {
      separator: ' | ',  // Default separator
      prepend: true,     // Default prepend behavior
      replace: null      // Default replace behavior
    }
  };
};

FastBoot Integration

The service automatically handles server-side rendering environments.

/** 
 * Update title in FastBoot environment
 * @param title - Title to set in server context
 */
updateFastbootTitle(title: string): void;

FastBoot Features:

  • Automatic environment detection
  • Server-side DOM title element management
  • Compatible with FastBoot document API
  • Proper title element cleanup and creation

Install with Tessl CLI

npx tessl i tessl/npm-ember-page-title

docs

index.md

page-title-service.md

template-helper.md

test-support.md

typescript-integration.md

tile.json