Angular URL serializer to properly handle URLs that start with query parameters directly (without a path adding trailing slashes Angular

 Example Code

The key requirement:


In the parse method, I added special handling for URLs that start with query parameters:


If the URL starts with '?', I prepend a '/' so Angular can properly parse it

This allows Angular to handle URLs like ?param1=value1&param2=value2


In the serialize method, I added special handling for query-only URLs:


If the URL starts with '/?', I remove the leading slash

This converts Angular's internal representation back to the expected query-only format



This implementation properly handles these types of URLs:

  • ?param1=value1&param2=value2&param3=value3 (query-only URL)
  • /path?param1=value1&param2=value2 (path with query parameters)
  • /path/?param1=value1&param2=value2 (path with trailing slash and query parameters)


import { DefaultUrlSerializer, UrlTree } from '@angular/router';


export class TrailingSlashSerializer extends DefaultUrlSerializer {

  // Remove trailing slashes during ROUTE MATCHING

  parse(url: string): UrlTree {

    // Special handling for URLs that start with query parameters

    if (url.startsWith('?')) {

      return super.parse('/' + url);

    }

    

    // Normal case: Remove ALL trailing slashes for clean route matching

    const cleaned = url.replace(/\/+$/g, '') || '/';

    return super.parse(cleaned);

  }


  // Add trailing slashes during URL GENERATION

  serialize(tree: UrlTree): string {

    const defaultUrl = super.serialize(tree);

    

    // Handle URLs that are just query parameters (no path)

    if (defaultUrl.startsWith('/?')) {

      return defaultUrl.substring(1); // Remove the leading slash

    }

    

    // Split the URL into parts: path and query/fragment

    const [path, ...rest] = defaultUrl.split(/(?=\?|#)/);

    const queryOrFragment = rest.join(''); // Rejoin any query/fragment parts

    

    // Case 1: Root URL - keep as "/"

    if (path === '/') return '/' + queryOrFragment;

    

    // Case 2: .html files (SSG) - leave untouched

    if (path.endsWith('.html')) return path + queryOrFragment;

    

    // Case 3: Add exactly one trailing slash if not already present

    const modifiedPath = path.endsWith('/') ? path : `${path}/`;

    

    return modifiedPath + queryOrFragment;

  }

}


Example 2  


// trailing-slash-serializer.ts

import { DefaultUrlSerializer, UrlTree } from '@angular/router';


export class TrailingSlashSerializer extends DefaultUrlSerializer {

  parse(url: string): UrlTree {

    // Remove trailing slashes for route matching

    const cleaned = url.replace(/\/+$/g, '') || '/';

    return super.parse(cleaned);

  }


  serialize(tree: UrlTree): string {

    const defaultUrl = super.serialize(tree);

    const [path, queryOrFragment] = defaultUrl.split(/(?=[?#])/);


    // Handle root and .html files

    if (path === '/' || path.endsWith('.html')) {

      return defaultUrl;

    }


    // Add exactly one trailing slash

    const modifiedPath = path.endsWith('/') ? path : `${path}/`;

    return modifiedPath + (queryOrFragment || '');

  }

}

No comments:

Post a Comment

Asynchronous vs. Synchronous Operations

  1. Definitions Synchronous : Tasks execute  sequentially , one after another. Each task waits for the previous one to complete before star...

Best for you