feat(router): add trailingSlash config option #66276
Draft
+366
−13
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This commit introduces a highly requested
trailingSlashconfiguration option to the Angular Router, allowing developers to control how trailing slashes are handled in their applications. The options are:Additionally, this commit updates the
defaultUrlMatcherto optionally consume a single trailing empty path segment if the route otherwise matches. This ensures that routes withpathMatch: 'full'can correctly match URLs with trailing slashes (e.g.,/a/matching{path: 'a', pathMatch: 'full'}), resolving a long-standing inconsistency where such routes would fail despitepathMatch: 'prefix'variants (with empty children) succeeding.Alternatives Considered & Design Rationale:
UrlTree.hasTrailingSlashProperty: We initially explored adding a explicit boolean property toUrlTree. However, this would have required a significant public API change and breaking updates to customUrlSerializerimplementations to ensure the state was preserved. It also complicated the mental model of theUrlTreeas a direct representation of the URL structure. We settled on representing trailing slashes as a trailing emptyUrlSegment, which leverages the existing structure and serialization logic without API expansion.Why we chose the current approach:
We decided on a "Permissive Matcher, Strict Serializer/Location" pattern.
pathMatch: 'full'. This aligns logic with howpathMatch: 'prefix'matches empty children.trailingSlashconfiguration is verified at the boundaries (serialization and location normalization). IftrailingSlash: 'never'is set, the slash is stripped before matching ever occurs. If matching sees a slash, it implies the configuration allowed it (or we are in a permissive mode), so the matcher should handle it gracefully.fixes #16051