Angular 2 optional route parameter
You can define multiple routes with and without parameter:
@RouteConfig([
{ path: '/user/:id', component: User, name: 'User' },
{ path: '/user', component: User, name: 'Usernew' }
])
and handle the optional parameter in your component:
constructor(params: RouteParams) {
var paramId = params.get("id");
if (paramId) {
...
}
}
See also the related github issue: https://github.com/angular/angular/issues/3525
Angular2+ routing - optional route params
So is there any way to define these type routes with optional params
like we do in ExpressJS
Simple answer is No, you have to define new route for each separate path.
{path: 'users', component: ItemsComponent},
{path: 'users/:filter', component: ItemsComponent}
Though you can verify the path and determine, if it has optional parameter inside the routed component
using ActivatedRoute
.
Angular routing with optional parameters
To allow the component route to have multiple optional parameters, inside your routing module, specify the route as follows:
const appRoutes: Routes = [
...
{path: 'route1',component: MyComponent}
...
];
In the calling component that you wish to call MyComponent from, use the router navigate() method as follows:
router.navigate(['route1', {p1:value1,p2:value2}]);
Where value1 and value2 are variables within your calling component that
you want to bind to the parameters p1 and p2.
The above should match parameters p1, p2 or p1 and p2 for the route.
In a HTML template, call the above using the following router link:
<a [routerLink]="['/route1', {p1:value1, p2:value2}]" .. />
The router URL link will then resolve to:
/route1;p1=value1;p2=value2
The following router link:
<a [routerLink]="['/route1', {p1:value1}]" .. />
Will resolve to the URL:
/route1;p1=value1
And the following router link:
<a [routerLink]="['/route1', {p2:value2}]" .. />
Will resolve to the URL:
/route1;p2=value2
Note: that if you omit the brackets [] in your router link, then the following error will appear with parameters are included:
Error: Cannot match any routes. URL Segment: ...
Within your component MyComponent, read the parameters using paramMap as follows:
const p1 = this.route.snapshot.paramMap.get('p1');
const p2 = this.route.snapshot.paramMap.get('p2');
The route parameters paramMap are an observable that can change when the same route is called within an application, so it is recommended to subscribe to it within the component as follows:
routingSubscription: Subscription;
constructor(private activatedRoute: ActivatedRoute,
private router: Router) { }
ngOnInit(): void {
let route = this.activatedRoute.snapshot;
let urlSegments = route['_urlSegment'].segments;
let relativePath: string = '';
urlSegments.forEach((pathSegment: UrlSegment) => {
relativePath = relativePath.concat(pathSegment.path, '/');
});
this.routingSubscription = this.activatedRoute.paramMap
.subscribe((params: ParamMap) => {
const firstParam: string = params.get('p1');
const secondParam: string = params.get('p2');
if (firstParam && !secondParam)
{
let mySecondParam: string = "2";
this.router.navigate(
[relativePath, {p1:firstParam,p2:mySecondParam}]);
}
});
}
The example above will allow a route to the component with the first parameter then re-route back with the relative path of the original route. This should also work within a feature module.
Alternatively, the relative path can specified without quantifying the individual path segments in the active route. This can be done using the relativeTo option within router.Navigate().
To make use of relativeTo, import NavigationExtras interface as follows:
import { NavigationExtras } from '@angular/router';
We can then specify and extend the navigation as follows:
this.router.navigate(
[{id1:firstParam,id2:mySecondParam}],
{ relativeTo: this.activatedRoute }
);
Angular - multiple optional route parameters
If you want the language parameter to be the first, you can do the following. You will first have to declare an empty app or whatever root component and use this in the bootstrap instead of the AppComponent
:
@Component({
selector: 'app-root',
template: `<router-outlet></router-outlet>`
})
export class RootComponent {}
Then create a module from your current routes, if you do not have that already. Call it AppRoutingModule
.
export const AppRoutes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'news', component: NewsComponent },
{ path: 'newsDetail/:id', component: NewsDetailComponent }
];
@NgModule({
imports: [RouterModule.forFeature(AppRoutes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
Then create a RootRoutingModule
, which will do the magic:
export const RootRoutes: Routes = [
{ path: '', loadChildren: () => import('./app.module').then((m) => m.AppModule) },
{ path: 'en', loadChildren: () => import('./app.module').then((m) => m.AppModule) }
];
@NgModule({
imports: [RouterModule.forRoot(AppRoutes)],
exports: [RouterModule],
})
export class RootRoutingModule {}
The issue with this, is that you'll have to hardcode all the languages you might support, as I don't think a :language
parameter will work
So basically, create a root module which will do the language routing and the bootstrapping
How to create optional router argument in angular 7
I don't know of a way to make the parameter optional. Depending on what you're trying to achieve you could use a specific string you could detect in the id param (Registration/new vs Registration/678A6).
Anyway the routes are just plain typescript so I guess you could keep it dry this way:
const registrationRouteConfig = {
component: RegisterComponent,
children: [
{ path:'',component:ProfileComponent},
{ path: 'Dependent', component: DependentComponent },
{ path: 'Matrimony', component: MatrimonyComponent },
{ path: 'Subscription', component: MagazinesubscriptionComponent },
{ path: 'Donation', component: DonationComponent }
]
}
const routes: Routes = [
{ path: 'Registration', ...registrationRouteConfig },
{ path: 'Registration/:id', ...registrationRouteConfig },
{ path: 'Profile', component: ProfilelistComponent }
]
Optional Parameters While Routing angular2
You can define multiple routes with and without parameter having the same component:
@RouteConfig([{
path: '/abc',
component: Abc,
name: 'abc'},
{
path: '/abc/:xyz',
component: Abc,
name: 'abcXyz'
}])
and then use the one that you need
<a [routerLink]="['/abcXyz',{xyz: blabla}]">
and
<a [routerLink]="['/abc']">
If routeCongig
is located in your root file, use /
before root's name and if it's on the second level or something, use
<a [routerLink]="['/parentRoot', {parentParams:value}, '/abc']">
Angular 2: Redirect route with parameters and optional parameters
The angular router basically looks at path objects and creates the set of basic routes of your app (without the optional parameters). Which then would be used to recognise routes if they match the path exactly. So the optional parameters cannot be used inside them because they're "optional". And the only way to include any route params in these path objects, is binding them inside the url with':something' syntax which then wouldn't be optional.
I think you have some other ways to cover this need of yours:
Adding your "mode" parameter to your basic route:
You can define a path like this: { path:'/bar/:id/:mode', component: BarComponent }
and change your redirect path to { path: 'foo/bar/:id', redirectTo: '/bar/:id/test' }
Using a proxy component:
Change the redirect path to: { path: 'foo/bar/:id', component: BarProxyComponent }
, and define that component like this:
export class BarProxyComponent {
constructor(private _router: Router, private _route: ActivatedRoute){
_router.navigate(['/bar/'+_route.snapshot.params['id'],{mode: 'test'}]);
}
}
Using a canActivate Guard: You can also create a guard service for your 'foo' path, and inside the guard redirect it to the route you want. However, it's not exactly the real intention behind these guards and it's just taking advantage of them for that said problem.
You can change the redirect path to { path: 'foo/bar/:id', component: UnusedFooComponent, canActivate: [FooGuard]}
and define the guard like this:
@Injectable()
export class FooGuard implements CanActivate {
constructor(private _router: Router){}
canActivate(route: ActivatedRouteSnapshot) {
this._router.navigate(['/bar/'+route.params['id'],{mode: 'test'}]);
return false;
}
}
Also don't forget to provide the FooGuard
at a module level.
And note that here, you're always redirecting to another place (and returning false
) in the guard before the UnusedFooComponent
is created...
Related Topics
Remove Duplicates Form an Array
Mixing Jsf El in a JavaScript File
JavaScript with Embedded Ruby: How to Safely Assign a Ruby Value to a JavaScript Variable
How to Geocode 20 Addresses Without Receiving an Over_Query_Limit Response
Push Is Overwriting Previous Data in Array
Using Socket.Io in Express 4 and Express-Generator's /Bin/Www
Updating Elements in Rails with Ajax
"Cannot Use Import Statement Outside a Module" Error When Importing React-Hook-Mousetrap in Next.Js
How to Make Regular Expression into Non-Greedy
How to Include Newlines in Labels in D3 Charts
Submitting Rails Form on a Radio Button Selection
Uint8Array to String in JavaScript
Rendering React Components with Promises Inside the Render Method
Firebase.Database Is Not a Function