In here it is use pathmatch as full and when i delete this pathmatch it doesn\'t even load the app or run the project
import { NgModule } from \'@angular/cor
The path-matching strategy, one of 'prefix' or 'full'. Default is 'prefix'.
By default, the router checks URL elements from the left to see if the URL matches a given path, and stops when there is a match. For example, '/team/11/user' matches 'team/:id'.
The path-match strategy 'full' matches against the entire URL. It is important to do this when redirecting empty-path routes. Otherwise, because an empty path is a prefix of any URL, the router would apply the redirect even when navigating to the redirect destination, creating an endless loop.
Source : https://angular.io/api/router/Route#properties
While technically correct, the other answers would benefit from an explanation of Angular's URL-to-route matching. I don't think you can fully (pardon the pun) understand what pathMatch: full
does if you don't know how the router works in the first place.
Let's first define a few basic things. We'll use this URL as an example: /users/james/articles?from=134#section
.
It may be obvious but let's first point out that query parameters (?from=134
) and fragments (#section
) do not play any role in path matching. Only the base url (/users/james/articles
) matters.
Angular splits URLs into segments. The segments of /users/james/articles
are, of course, users
, james
and articles
.
The router configuration is a tree structure with a single root node. Each Route
object is a node, which may have children
nodes, which may in turn have other children
or be leaf nodes.
The goal of the router is to find a router configuration branch, starting at the root node, which would match exactly all (!!!) segments of the URL. This is crucial! If Angular does not find a route configuration branch which could match the whole URL - no more and no less - it will not render anything.
E.g. if your target URL is /a/b/c
but the router is only able to match either /a/b
or /a/b/c/d
, then there is no match and the application will not render anything.
Finally, routes with redirectTo
behave slightly differently than regular routes, and it seems to me that they would be the only place where anyone would really ever want to use pathMatch: full
. But we will get to this later.
prefix
) path matchingThe reasoning behind the name prefix
is that such a route configuration will check if the configured path
is a prefix of the remaining URL segments. However, the router is only able to match full segments, which makes this naming slightly confusing.
Anyway, let's say this is our root-level router configuration:
const routes: Routes = [
{
path: 'products',
children: [
{
path: ':productID',
component: ProductComponent,
},
],
},
{
path: ':other',
children: [
{
path: 'tricks',
component: TricksComponent,
},
],
},
{
path: 'user',
component: UsersonComponent,
},
{
path: 'users',
children: [
{
path: 'permissions',
component: UsersPermissionsComponent,
},
{
path: ':userID',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
],
},
];
Note that every single Route
object here uses the default matching strategy, which is prefix
. This strategy means that the router iterates over the whole configuration tree and tries to match it against the target URL segment by segment until the URL is fully matched. Here's how it would be done for this example:
users
.'products' !== 'users'
, so skip that branch. Note that we are using an equality check rather than a .startsWith()
or .includes()
- only full segment matches count!:other
matches any value, so it's a match. However, the target URL is not yet fully matched (we still need to match james
and articles
), thus the router looks for children.:other
is tricks
, which is !== 'james'
, hence not a match.'user' !== 'users
, skip branch.'users' === 'users
- the segment matches. However, this is not a full match yet, thus we need to look for children (same as in step 3).'permissions' !== 'james'
, skip it.:userID
matches anything, thus we have a match for the james
segment. However this is still not a full match, thus we need to look for a child which would match articles
.
:userID
has a child route articles
, which gives us a full match! Thus the application renders UserArticlesComponent
.full
) matchingImagine now that the users
route configuration object looked like this:
{
path: 'users',
component: UsersComponent,
pathMatch: 'full',
children: [
{
path: 'permissions',
component: UsersPermissionsComponent,
},
{
path: ':userID',
component: UserComponent,
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
],
}
Note the usage of pathMatch: full
. If this were the case, steps 1-5 would be the same, however step 6 would be different:
'users' !== 'users/james/articles
- the segment does not match because the path configuration users
with pathMatch: full
does not match the full URL, which is users/james/articles
.What if we had this instead:
{
path: 'users/:userID',
component: UsersComponent,
pathMatch: 'full',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
}
users/:userID
with pathMatch: full
matches only users/james
thus it's a no-match once again, and the application renders nothing.
Let's consider this:
{
path: 'users',
children: [
{
path: 'permissions',
component: UsersPermissionsComponent,
},
{
path: ':userID',
component: UserComponent,
pathMatch: 'full',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
],
}
In this case:
'users' === 'users
- the segment matches, but james/articles
still remains unmatched. Let's look for children.'permissions' !== 'james'
- skip.:userID'
can only match a single segment, which would be james
. However, it's a pathMatch: full
route, and it must match james/articles
(the whole remaining URL). It's not able to do that and thus it's not a match (so we skip this branch)!As you may have noticed, a pathMatch: full
configuration is basically saying this:
Ignore my children and only match me. If I am not able to match all of the remaining URL segments myself, then move on.
Any Route
which has defined a redirectTo
will be matched against the target URL according to the same principles. The only difference here is that the redirect is applied as soon as a segment matches. This means that if a redirecting route is using the default prefix
strategy, a partial match is enough to cause a redirect. Here's a good example:
const routes: Routes = [
{
path: 'not-found',
component: NotFoundComponent,
},
{
path: 'users',
redirectTo: 'not-found',
},
{
path: 'users/:userID',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
];
For our initial URL (/users/james/articles
), here's what would happen:
'not-found' !== 'users'
- skip it.'users' === 'users'
- we have a match.redirectTo: 'not-found'
, which is applied immediately.not-found
.not-found
right away. The application renders NotFoundComponent
.Now consider what would happen if the users
route also had pathMatch: full
:
const routes: Routes = [
{
path: 'not-found',
component: NotFoundComponent,
},
{
path: 'users',
pathMatch: 'full',
redirectTo: 'not-found',
},
{
path: 'users/:userID',
children: [
{
path: 'comments',
component: UserCommentsComponent,
},
{
path: 'articles',
component: UserArticlesComponent,
},
],
},
];
'not-found' !== 'users'
- skip it.users
would match the first segment of the URL, but the route configuration requires a full
match, thus skip it.'users/:userID'
matches users/james
. articles
is still not matched but this route has children.articles
in the children. The whole URL is now matched and the application renders UserArticlesComponent
.path: ''
)The empty path is a bit of a special case because it can match any segment without "consuming" it (so it's children would have to match that segment again). Consider this example:
const routes: Routes = [
{
path: '',
children: [
{
path: 'users',
component: BadUsersComponent,
}
]
},
{
path: 'users',
component: GoodUsersComponent,
},
];
Let's say we are trying to access /users
:
path: ''
will always match, thus the route matches. However, the whole URL has not been matched - we still need to match users
!users
, which matches the remaining (and only!) segment and we have a full match. The application renders BadUsersComponent
.The OP used this router configuration:
const routes: Routes = [
{
path: 'welcome',
component: WelcomeComponent,
},
{
path: '',
redirectTo: 'welcome',
pathMatch: 'full',
},
{
path: '**',
redirectTo: 'welcome',
pathMatch: 'full',
},
];
If we are navigating to the root URL (/
), here's how the router would resolve that:
welcome
does not match an empty segment, so skip it.path: ''
matches the empty segment. It has a pathMatch: 'full'
, which is also satisfied as we have matched the whole URL (it had a single empty segment).welcome
happens and the application renders WelcomeComponent
.pathMatch: 'full'
?Actually, one would expect the whole thing to behave exactly the same. However, Angular explicitly prevents such a configuration ({ path: '', redirectTo: 'welcome' }
) because if you put this Route
above welcome
, it would theoretically create an endless loop of redirects. So Angular just throws an error, which is why the application would not work at all! (https://angular.io/api/router/Route#pathMatch)
Actually, this does not make too much sense to me because Angular also has implemented a protection against such endless redirects - it only runs a single redirect per routing level! This would stop all further redirects (as you'll see in the example below).
path: '**'
?path: '**'
will match absolutely anything (af/frewf/321532152/fsa
is a match) with or without a pathMatch: 'full'
.
Also, since it matches everything, the root path is also included, which makes { path: '', redirectTo: 'welcome' }
completely redundant in this setup.
Funnily enough, it is perfectly fine to have this configuration:
const routes: Routes = [
{
path: '**',
redirectTo: 'welcome'
},
{
path: 'welcome',
component: WelcomeComponent,
},
];
If we navigate to /welcome
, path: '**'
will be a match and a redirect to welcome will happen. Theoretically this should kick off an endless loop of redirects but Angular stops that immediately (because of the protection I mentioned earlier) and the whole thing works just fine.
pathMatch = 'full'
results in a route hit when the remaining, unmatched segments of the URL match is the prefix path
pathMatch = 'prefix'
tells the router to match the redirect route when the remaining URL begins with the redirect route's prefix path.
Ref: https://angular.io/guide/router#set-up-redirects
pathMatch: 'full'
means, that the whole URL path needs to match and is consumed by the route matching algorithm.
pathMatch: 'prefix'
means, the first route where the path matches the start of the URL is chosen, but then the route matching algorithm is continuing searching for matching child routes where the rest of the URL matches.
RouterModule.forRoot([
{ path: 'welcome', component: WelcomeComponent },
{ path: '', redirectTo: 'welcome', pathMatch: 'full' },
{ path: '**', component: 'pageNotFoundComponent' }
])
Case 1 pathMatch:'full'
:
In this case, when app is launched on localhost:4200
(or some server) the default page will be welcome screen, since the url will be https://localhost:4200/
If https://localhost:4200/gibberish
this will redirect to pageNotFound screen because of path:'**'
wildcard
Case 2
pathMatch:'prefix'
:
If the routes have { path: '', redirectTo: 'welcome', pathMatch: 'prefix' }
, now this will never reach the wildcard route since every url would match path:''
defined.