npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ngx-named-router

v0.0.1

Published

A powerful Angular library that brings named route navigation to your Angular applications

Readme

ngx-named-router

npm version License: MIT

A powerful Angular library that brings named route navigation to your Angular applications. Navigate using semantic route names instead of brittle URL paths, making your code more maintainable and refactor-friendly.

Why ngx-named-router?

Traditional Angular routing requires hardcoded paths throughout your application:

// ❌ Brittle - breaks when URLs change
this.router.navigate(['/users', userId, 'settings']);

With ngx-named-router, you use semantic names:

// ✅ Maintainable - survives URL refactoring
this.namedRouter.navigate('user-settings', { routeParams: { userId: 123 } });

Features

Named Route Navigation - Use semantic names instead of URL paths
Type-Safe Parameters - Full TypeScript support for route and query parameters
Directive Support - [namedRouterLink] directive for templates
Programmatic API - Navigate from TypeScript code
Lazy Loading Support - Automatically discovers routes from lazy-loaded modules
Error Handling - Comprehensive validation and helpful error messages
Fragment & Query Params - Full support for URL fragments and query parameters
Angular 20+ Compatible - Built for modern Angular applications
Standalone Components - Fully standalone, no NgModules required


Table of Contents


Installation

npm install ngx-named-router

Peer Dependencies:

  • @angular/common ^20.0.0 or higher
  • @angular/core ^20.0.0 or higher
  • @angular/router ^20.0.0 or higher

Quick Start

1. Define Named Routes

Add name properties to your route configuration:

// app.routes.ts
import { Routes } from '@angular/router';
import { NamedRoute } from 'ngx-named-router';

export const routes: NamedRoute[] = [
  { 
    path: '', 
    component: HomeComponent, 
    name: 'home' 
  },
  { 
    path: 'users/:id', 
    component: UserDetailComponent, 
    name: 'user-detail' 
  },
  { 
    path: 'users/:id/settings', 
    component: UserSettingsComponent, 
    name: 'user-settings' 
  },
  {
    path: 'products',
    name: 'products',
    loadChildren: () => import('./products/products.routes').then(m => m.PRODUCTS_ROUTES)
  }
];

2. Configure Application

In your app.config.ts, add the named routes provider:

// app.config.ts
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideNamedRoutes } from 'ngx-named-router';
import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
  providers: [
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(routes),
    provideNamedRoutes()  // 👈 Add this
  ]
};

3. Use in Templates

// user-list.component.ts
import { Component } from '@angular/core';
import { NamedRouterLinkDirective } from 'ngx-named-router';

@Component({
  selector: 'app-user-list',
  standalone: true,
  imports: [NamedRouterLinkDirective],
  template: `
    <a [namedRouterLink]="'user-detail'" 
       [routeParams]="{id: 123}">
      View User 123
    </a>
    
    <a [namedRouterLink]="'user-settings'" 
       [routeParams]="{id: 456}"
       [queryParams]="{tab: 'profile'}">
      Edit User Settings
    </a>
  `
})
export class UserListComponent {}

4. Use Programmatically

// user-list.component.ts
import { Component, inject } from '@angular/core';
import { NamedRouterService } from 'ngx-named-router';

@Component({
  selector: 'app-user-list',
  standalone: true,
  template: `<button (click)="viewUser(123)">View User</button>`
})
export class UserListComponent {
  private namedRouter = inject(NamedRouterService);

  viewUser(userId: number) {
    this.namedRouter.navigate('user-detail', {
      routeParams: { id: userId },
      queryParams: { source: 'list' }
    });
  }
}

Configuration

Basic Setup

The library requires minimal configuration. Simply add provideNamedRoutes() to your application providers:

import { provideNamedRoutes } from 'ngx-named-router';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideNamedRoutes()
  ]
};

Route Naming Conventions

We recommend these naming conventions for route names:

  • Use kebab-case: 'user-detail' not 'userDetail'
  • Be descriptive: 'admin-user-settings' not 'settings'
  • Include context: 'product-reviews' not just 'reviews'
  • Unique across app: Each name must be unique globally

Lazy-Loaded Modules

Named routes automatically work with lazy-loaded modules:

// products/products.routes.ts
import { NamedRoute } from 'ngx-named-router';

export const PRODUCTS_ROUTES: NamedRoute[] = [
  { path: '', component: ProductListComponent, name: 'product-list' },
  { path: ':id', component: ProductDetailComponent, name: 'product-detail' }
];

// app.routes.ts
{
  path: 'products',
  loadChildren: () => import('./products/products.routes').then(m => m.PRODUCTS_ROUTES)
}

The library will automatically discover and register routes from lazy-loaded modules.


Usage

Template Navigation (Directive)

The NamedRouterLinkDirective works like Angular's routerLink but uses route names:

Basic Navigation

<a [namedRouterLink]="'home'">Home</a>

With Route Parameters

<a [namedRouterLink]="'user-detail'" 
   [routeParams]="{id: user.id}">
  View Profile
</a>

With Query Parameters

<a [namedRouterLink]="'products'" 
   [queryParams]="{category: 'electronics', sort: 'price'}">
  Electronics
</a>

With Fragment

<a [namedRouterLink]="'docs'" 
   [fragment]="'getting-started'">
  Documentation
</a>

Open in New Tab

<a [namedRouterLink]="'external-resource'" 
   target="_blank">
  Open in New Tab
</a>

Complete Example

<a [namedRouterLink]="'user-posts'"
   [routeParams]="{userId: user.id, postId: post.id}"
   [queryParams]="{edit: true, tab: 'comments'}"
   [fragment]="'comment-section'"
   [skipLocationChange]="false"
   [replaceUrl]="false">
  Edit Post Comments
</a>

Programmatic Navigation

Use NamedRouterService for navigation from TypeScript code:

Basic Navigation

import { inject } from '@angular/core';
import { NamedRouterService } from 'ngx-named-router';

export class MyComponent {
  private namedRouter = inject(NamedRouterService);

  goHome() {
    this.namedRouter.navigate('home');
  }
}

With Parameters

viewUser(userId: number) {
  this.namedRouter.navigate('user-detail', {
    routeParams: { id: userId }
  });
}

With Query Parameters

searchProducts(category: string) {
  this.namedRouter.navigate('products', {
    queryParams: { 
      category: category,
      page: 1,
      sort: 'price'
    }
  });
}

With Navigation Extras

updateSettings() {
  this.namedRouter.navigate('user-settings', {
    routeParams: { id: this.userId },
    replaceUrl: true,
    skipLocationChange: false,
    fragment: 'security'
  });
}

Generate URLs Without Navigating

// Create a URL tree
const urlTree = this.namedRouter.createUrlTree('user-detail', {
  routeParams: { id: 123 }
});

// Serialize to string
const url = this.namedRouter.serializeUrl('user-detail', {
  routeParams: { id: 123 },
  queryParams: { tab: 'posts' }
});
// Returns: '/users/123?tab=posts'

Check if Route Exists

if (this.namedRouter.hasRoute('admin-panel')) {
  // Route exists
}

Get All Route Names

const allRoutes = this.namedRouter.getAllRouteNames();
console.log('Available routes:', allRoutes);

Advanced Features

Optional Parameters

Routes can have optional parameters:

// Route definition
{ path: 'users/:id?', name: 'user-maybe' }

// Usage without parameter
this.namedRouter.navigate('user-maybe', {});
// Navigates to: /users

// Usage with parameter
this.namedRouter.navigate('user-maybe', {
  routeParams: { id: 123 }
});
// Navigates to: /users/123

Parameter Constraints

Parameters with regex constraints are supported:

// Route definition
{ path: 'users/:id(\\d+)', name: 'user-by-id' }

// The constraint pattern is automatically extracted
this.namedRouter.navigate('user-by-id', {
  routeParams: { id: 999 }
});

Special Characters in Parameters

Parameters are automatically URL-encoded:

this.namedRouter.navigate('search', {
  routeParams: { query: 'hello world & more' }
});
// Navigates to: /search/hello%20world%20%26%20more

Dynamic Route Updates

If routes change dynamically, refresh the registry:

import { NamedRouteService } from 'ngx-named-router';

export class MyComponent {
  private routeService = inject(NamedRouteService);

  async reloadRoutes() {
    await this.routeService.refresh();
  }
}

API Reference

provideNamedRoutes()

Function to configure the named routes service in your application.

Usage:

import { provideNamedRoutes } from 'ngx-named-router';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideNamedRoutes()
  ]
};

NamedRouterLinkDirective

Directive for template-based navigation.

Selector: [namedRouterLink]

Inputs:

| Input | Type | Description | |-------|------|-------------| | namedRouterLink | string | The name of the route to navigate to | | routeParams | RouteParams | Object with route parameters (e.g., {id: 123}) | | queryParams | QueryParams | Object with query parameters | | fragment | string | URL fragment (hash) | | target | string | Link target (_blank, _self, etc.) | | preserveFragment | boolean | Whether to preserve existing fragment | | skipLocationChange | boolean | Skip updating browser URL | | replaceUrl | boolean | Replace current state in history |

Example:

<a [namedRouterLink]="'user-detail'"
   [routeParams]="{id: 123}"
   [queryParams]="{tab: 'posts'}"
   [fragment]="'comments'">
  View User
</a>

NamedRouterService

Service for programmatic navigation.

Methods

navigate(routeName: string, extras?: NamedNavigationExtras): Promise<boolean>

Navigate to a named route.

await this.namedRouter.navigate('user-detail', {
  routeParams: { id: 123 },
  queryParams: { edit: true }
});

createUrlTree(routeName: string, extras?: NamedNavigationExtras): UrlTree

Create a URL tree without navigating.

const urlTree = this.namedRouter.createUrlTree('user-detail', {
  routeParams: { id: 123 }
});

serializeUrl(routeName: string, extras?: NamedNavigationExtras): string

Generate a URL string.

const url = this.namedRouter.serializeUrl('user-detail', {
  routeParams: { id: 123 }
});
// Returns: '/users/123'

hasRoute(routeName: string): boolean

Check if a route name exists.

if (this.namedRouter.hasRoute('admin-panel')) {
  // Route exists
}

getAllRouteNames(): string[]

Get all registered route names.

const routes = this.namedRouter.getAllRouteNames();

NamedRouteService

Low-level service for route registry management (typically not used directly).

Methods

initialize(): Promise<void>

Initialize the route registry. Called automatically by provideNamedRoutes().

getRoutePath(name: string): string | undefined

Get the path pattern for a route name.

refresh(): Promise<void>

Re-scan and rebuild the route registry.

reset(): void

Clear the route registry.


Types

NamedRoute

Extended route interface with optional name property:

interface NamedRoute extends Route {
  name?: string;
  children?: NamedRoute[];
}

RouteParams

Type for route parameters:

type RouteParams = { [key: string]: string | number };

QueryParams

Type for query parameters:

type QueryParams = { 
  [key: string]: string | number | boolean | (string | number)[] 
};

NamedNavigationExtras

Options for navigation:

interface NamedNavigationExtras extends Omit<NavigationExtras, 'queryParams'> {
  routeParams?: RouteParams;
  queryParams?: QueryParams;
}

Error Classes

NamedRouteError

Thrown when route configuration is invalid or navigation fails.

DuplicateRouteNameError

Thrown when duplicate route names are detected.

try {
  await this.namedRouter.navigate('invalid-route');
} catch (error) {
  if (error instanceof NamedRouteError) {
    console.error('Route error:', error.message);
  }
}

Best Practices

1. Consistent Naming

// ✅ Good - descriptive and consistent
'home'
'user-detail'
'admin-user-settings'
'product-reviews'

// ❌ Bad - inconsistent or vague
'userDetail'  // Not kebab-case
'settings'    // Too vague
'page1'       // Not descriptive

2. Centralized Route Names

Create a constants file for route names:

// routes/route-names.ts
export const ROUTE_NAMES = {
  HOME: 'home',
  USER_DETAIL: 'user-detail',
  USER_SETTINGS: 'user-settings',
  ADMIN_DASHBOARD: 'admin-dashboard'
} as const;

// Usage
this.namedRouter.navigate(ROUTE_NAMES.USER_DETAIL, {
  routeParams: { id: 123 }
});

3. Type-Safe Route Params

Define interfaces for route parameters:

interface UserDetailParams {
  id: number;
}

interface ProductSearchParams {
  category: string;
  page: number;
  sort?: string;
}

// Usage with type safety
const params: UserDetailParams = { id: 123 };
this.namedRouter.navigate('user-detail', { routeParams: params });

4. Error Handling

Always handle navigation errors:

async navigateToUser(userId: number) {
  try {
    const success = await this.namedRouter.navigate('user-detail', {
      routeParams: { id: userId }
    });
    
    if (!success) {
      console.error('Navigation was cancelled');
    }
  } catch (error) {
    if (error instanceof NamedRouteError) {
      console.error('Route error:', error.message);
      // Fallback to home or show error message
      this.namedRouter.navigate('home');
    }
  }
}

5. Guard Integration

Use with route guards:

@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
  private namedRouter = inject(NamedRouterService);

  canActivate(): boolean {
    const isAuthenticated = this.checkAuth();
    
    if (!isAuthenticated) {
      this.namedRouter.navigate('login', {
        queryParams: { returnUrl: window.location.pathname }
      });
      return false;
    }
    
    return true;
  }
}

Troubleshooting

Route Not Found

Problem: Route 'xxx' not found in registry

Solutions:

  1. Ensure the route has a name property
  2. Check for typos in the route name
  3. Verify initialization completed (routes should appear in console on startup)
  4. For lazy routes, ensure they've been loaded at least once

Duplicate Route Names

Problem: DuplicateRouteNameError: Duplicate route name 'xxx' detected

Solutions:

  1. Use unique names across your entire application
  2. Add context to names: 'admin-users' vs 'public-users'
  3. Use prefixes for feature modules: 'products-list', 'products-detail'

Missing Required Parameters

Problem: Missing required route parameters: id

Solutions:

  1. Provide all required parameters in routeParams
  2. Make parameters optional in route definition: :id?
  3. Check parameter names match route definition exactly

Lazy Routes Not Registered

Problem: Lazy-loaded routes don't appear in registry

Solutions:

  1. Navigate to the lazy route at least once
  2. Use refresh() after dynamic route changes
  3. Ensure lazy module exports routes correctly

License

MIT © Eric Taurone

See LICENSE file for details.


Support


Made with ❤️ for the Angular community