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¶m2=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¶m2=value2¶m3=value3
(query-only URL)/path?param1=value1¶m2=value2
(path with query parameters)/path/?param1=value1¶m2=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