angular 4 child routing - javascript

Im trying to write routing for childs. The problem Im having is with path not beeing inserted in url bar of thhe browser properly. Below the code.
router.module
const routes: Routes = [
{path: 'menu', component: MenuComponent, canActivate: [AuthGuard],
children: [
{ path: 'upload', component: DrawingUploadComponent },
{ path: 'account', component: AccountComponent },
{ path: 'projects', component: ProjectListComponent }
]}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class MenuRoutingModule {}
menu.component
<nav>
<a routerLink="/projects" routerLinkActive="active">Projects</a>
<a routerLink="/upload" routerLinkActive="active">Upload</a>
<a routerLink="/account" routerLinkActive="active">Account</a>
</nav>
MENU COMPONENT
<router-outlet></router-outlet>
the parent component:
const routes: Routes = [
{path: 'login', component: LoginComponent},
{path: 'register', component: RegistrationComponent},
{path: "", redirectTo: "login", pathMatch: "full"},
{path: 'menu', component: MenuComponent, canActivate: [AuthGuard]}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {
}
So the problem is when im under "/menu" the menu component is displayed, now when Im clicking on any link e.g
<a routerLink="/upload" routerLinkActive="active">Upload</a>
im getting console error
Cannot match any routes. URL Segment: 'upload'
Error: Cannot match any routes. URL Segment: 'upload'
but when i'd type the route by hand in browser bar "/menu/upload" I'm getting the proper result

When your route starts with /, that refers to the root of your app. You'll need to remove that, or else use the full path e.g. routerLink="/menu/upload".

Related

Is there a way I can render a 2 level nested component in Angular using `router-outlet`?

I have a sidebar with some links. The sidebar is located at the /dashboard route. The links on the sidebar are direct children to /dashboard. I now want to render the children of /dashboard inside the main router-outlet. I have no idea on how to approach this.
The following are some code snippets to elaborate my question further
My routing structure
const routes: Routes = [
{
path: '',
component: LoginComponent,
},
{
path: 'dashboard',
component: DashboardComponent,
children: [
{
path: 'roles',
component: RolesComponent,
},
{
path: 'workgroups',
component: WorkgroupsComponent,
children: [
{
path: 'savewg',
component: WgDetailsComponent,
},
]
},
{
path: 'users',
component: UsersComponent,
},
],
},
];
App component
<!-- Main app component -->
<div class="app-view">
<router-outlet></router-outlet>
</div>
Login.html
<button mat-raised-button color="warn" class="login-field" (click)="login(email, password)"
<!-- rest of code ommited for brevity -->
Login.ts
public login(email: string, password: string) {
this.router.navigate(['dashboard'], { replaceUrl: true });
}
Workgroup Component html
<button mat-raised-button color="warn" [routerLink]="['savewg']">
<mat-icon>add</mat-icon>
New
</button>
<!-- Code ommited for brevity -->
<router-outlet></router-outlet>
<div class="workgroup-filters">
<mat-form-field appearance="outline">
<!-- rest of Code ommited for brevity -->
When I click on the new button in the workgroup component, I want it to navigate me to the savewg component view and replace the content in the workgroup component.
Any suggestions on how I can tackle this will be appreciated
Modules are only allow one main router-outlet per module. You will have to create a separate module for workgroups path and lazy load it. The workgroups module will have its own routing file and its own router outlet where you will load all your routes from your workgroup module. See below stackblitz for a working example.
app-routing.module.ts
const routes: Routes = [
...
{
path: 'workgroups',
loadChildren: () => import('./workgroups/workgroups.module').then(m => m.WorkgroupsModule)
},
...
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
workgroups-routing.module.ts
const routes: Routes = [
{
path: '',
component: WorkgroupsComponent,
children: [
{
path: 'savewg',
component: WgDetailsComponent
},
{
path: '**',
redirectTo: 'savewg',
pathMatch: 'full'
}
]
},
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class WorkgroupsRoutingModule { }
workgroups.module.ts
#NgModule({
imports: [
CommonModule,
WorkgroupsRoutingModule
],
declarations: [
WorkgroupsComponent,
WgDetailsComponent
]
})
export class WorkgroupsModule { }
Below are resources for lazy loading modules and a stackblitz example.
https://stackblitz.com/edit/angular-ivy-hbogtn
https://www.freakyjolly.com/angular-nested-routing-with-multiple-routeroutlet-using-loadchildren-having-own-router-modules-example-application/#.X3IQa3WYXmE
I found a better solution to this. It turns out that Angular will load the empty path route as the default route and there is no need to worry about router outlet anymore. I modified my app-routing.module.ts in the following way:
const routes: Routes = [
{
path: '',
component: LoginComponent,
},
{
path: 'dashboard',
component: DashboardComponent,
children: [
{
path: 'roles',
component: RolesComponent,
},
{
path: 'workgroups',
children: [
{
path: 'savewg',
component: WgDetailsComponent,
},
{
path: '',
component: WorkgroupsComponent,
},
],
},
{
path: 'users',
component: UsersComponent,
},
],
},
];
As you can see, I've added an empty path as a child in the
workgroups component This may not be perfect, more approaches and
solutions are welcome.

Angular 8.x routing with named outlets

I try to configure routing in angular 8.x application, with lazy loading and named outlets. I have the next configuration:
main-layout.html
<header>
<app-top-menu></app-top-menu>
</header>
<mat-sidenav-container autosize="true" id="app-main-layout">
<mat-sidenav opened mode="side">
<app-left-menu></app-left-menu>
</mat-sidenav>
<router-outlet name="toolbar"></router-outlet>
<div id="app-layout-content">
<router-outlet></router-outlet>
</div>
</mat-sidenav-container>
app-router.module.ts
const routes: Routes = [
{
path: '', component: MainLayoutComponent, canActivate: [RouteGuardService],
children: [
{
path: 'databases',
loadChildren: () => import('./feature-modules/database-search/database-search.module')
.then(m => m.DatabaseSearchModule)
}
]
}
];
#NgModule({
imports: [RouterModule.forRoot(routes, { enableTracing: true })],
exports: [RouterModule]
})
export class AppRoutingModule { }
There is a lazy loaded module router:
databases-search-routing.module.ts
const routes: Routes = [
{
path: 'index',
component: DatabaseListComponent,
children: [
{
path: '',
component: DatabaseListActionsMenuComponent,
outlet: 'toolbar'
}
]
},
{
path: 'mappings',
component: MappingsComponent,
children: [
{
path: '',
component: DatabaseListActionsMenuComponent,
outlet: 'toolbar'
}
]
}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class DatabaseSearchRoutingModule { }
The aim here is to load different toolbar for different views. So /databases/index should load DatabaseListComponent into 'main' router outlet and DatabaseListActionsMenuComponent into named 'toolbar' outlet.
However, it is not working.
The main router outlet is populated correctly but the named outlet isn't. I can't figure out what I'm doing wrong.
What is the right configuration for this case?
You should try to put the primary outlet routes, and the toolbar outlet routes at the same depth, and have a componentless parent route for both, like this:
const routes: Routes = [{
path: 'index',
children: [{
path: '',
component: DatabaseListComponent
}, {
path: '',
component: DatabaseListActionsMenuComponent,
outlet: 'toolbar'
}
]
}, {
path: 'mappings',
children: [{
path: '',
component: MappingsComponent
}, {
path: '',
component: DatabaseListActionsMenuComponent,
outlet: 'toolbar'
}
]
}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class DatabaseSearchRoutingModule {}

Navigate to child of lazy loaded module angular 8

My app-routing.module.ts
const routes: Routes = [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },
{ path: 'updateBooking', loadChildren: () => import('./update-booking/update-booking.module').then(m => m.UpdateBookingModule) },
{ path: 'booking', loadChildren: () => import('./booking/booking.module').then(m => m.BookingModule) }
];
#NgModule({
imports: [RouterModule.forRoot(routes, { enableTracing: true })],
exports: [RouterModule]
})
export class AppRoutingModule { }
lazy loaded Booking module's routing:
const routes: Routes = [
{ path: '', redirectTo: 'bookingdashboard' },
{
path: 'bookingdashboard', component: BookingDashboardComponent,
children: [
{ path: '', redirectTo: 'associateinfo' },
{
path: 'associateinfo', component: AssociateInfoComponent
},
{
path: 'agenda', component: AgendaComponent
},
{
path: 'zone', component: ZoneComponent
},
]
}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class BookingRoutingModule { }
I am on associate info page with url http://localhost:4200/booking/bookingdashboard/associateinfo
From this page when I try to navigate to agenda page using this._route.navigate(['../agenda' ]); I am getting error Cannot match any routes. URL Segment: 'agenda'
Error: Cannot match any routes. URL Segment: 'agenda'
However If I try to navigate from HTML file using [routerLink]="[ '../agenda']" its navigating to agenda page
You are navigating to only component specific route path, you should follow route as module-path/component-path
this._route.navigate(['booking/bookingdashboard/agenda' ]);
try
this._route.navigate(['/booking/bookingdashboard/agenda']);
After the link parameters array, add an object with a relativeTo
property set to the ActivatedRoute. The router then calculates the
target URL based on the active route's location.
constructor(private _router: Router, private route: ActivatedRoute){}
this._router.navigate(['../agenda'], { relativeTo: this.route })

Display component data from nested routes - Angular

I have the following components:
TodosComponent (path: './todos/'): with html content <p>TODO WORKS</p>
AddTodosComponent (path: './todos/add'): with html content <p>ADD TODO WORKS</p>
DeleteTodosComponent (path: './todos/delete'): with html content <p>DELETE TODO WORKS</p>
Add and Delete are nested routes in Todos.
In my main AppComponent I have a sidenav with links for the 3 components (TodosComponent, AddTodosComponent, DeleteTodosComponent).
I am trying to display in the content area of AppComponent the contents of the 3 components whenever one is clicked from the sidenav.
When I click the child routes I am receiving this error: Cannot match any routes. URL Segment: 'todos/add'
How can I display in sidenav-content from AppComponent the html from the components when a link is clicked in the sidenav?
app-routing.module.ts
const appRoutes: Routes = [
{ path: '', redirectTo: '/todos', pathMatch: 'full' },
{ path: 'todos', component: TodosComponent, pathMatch: 'full', children: [
{ path: 'add', component: AddTodoComponent},
{ path: 'delete', component: DeleteTodoComponent},
]},
]
#NgModule({
imports: [RouterModule.forRoot(appRoutes)],
exports: [RouterModule]
})
app.component.html
<mat-sidenav-container>
<mat-sidenav opened="true" mode="side" fixedInViewport="true">
<p>I am the sidenav</p>
<mat-nav-list>
<mat-list-item>
<a matLine routerLink="/todos">List Todos</a>
</mat-list-item>
<mat-list-item>
<a matLine routerLink="/todos/add">Add Todo</a>
</mat-list-item>
<mat-list-item>
<a matLine routerLink="/todos/delete">Delete Todo</a>
</mat-list-item>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<router-outlet></router-outlet>
<p>Main Content</p>
</mat-sidenav-content>
</mat-sidenav-container>
What I want to achieve:
Excerpt from angular documentation
Technically, pathMatch = 'full' results in a route hit when the
remaining, unmatched segments of the URL match ''.
In your example, at the path todos, the remaining, unmatched part is /todos/add, which is not an exact match, and the router won't look the children inside that and skip to the next path (which you don't have any) and when none found, you get the error you are getting :)
Remove pathMatch: 'full' from /todos path and it should work:
const appRoutes: Routes = [
{ path: '', redirectTo: '/todos', pathMatch: 'full' },
{ path: 'todos', component: TodosComponent, children: [
{ path: 'add', component: AddTodoComponent},
{ path: 'delete', component: DeleteTodoComponent},
]},
]
Why we need children, as we are displaying all in the same router-outlet.
const appRoutes: Routes = [
{ path: '', redirectTo: '/todos', pathMatch: 'full' },
{ path: '/todos', component: TodosComponent },
{ path: '/todos/add', component: AddTodoComponent },
{ path: '/todos/delete', component: DeleteTodoComponent }
]

Lazy loaded module base template

In app.module.ts I load 2 lazy modules like this
const appRoutes: Routes = [
{ path: 'anonym', loadChildren: './anonym/anonym.module#AnonymModule' },
{ path: 'user', loadChildren: './user/user.module#UserModule', canActivate: [AuthGuard] }
];
In app.component.html I can write some base html. My question - is there any way to have base html for my UserModule?
I have tried to create user.component.ts and load it like in app.module.ts
import { UserComponent } from './user.component';
#NgModule({
declarations: [UserComponent],
bootstrap: [UserComponent]
});
but it's not show me user.component.html
In your user module define a base route with an empty path, and then define the sub-paths as children.
const ROUTES: Routes = [
{
path: '',
component: UsersComponent,
children: [
{
path: '',
pathMatch: 'full',
redirectTo: 'login'
}, {
path: 'login',
component: LoginComponent
}, {
path: 'logout',
component: LogoutComponent
}
]
}
];
The UsersComponent will now be used as a base component, and if you navigate to just /users it will redirect to the /users/login path.
Make sure your UsersComponent has a template with <router-outlet></router-outlet> so the child routes.
#NgModule({
imports: [
RouterModule.forChild(ROUTES)
],
exports: [
RouterModule
]
})
export class UsersModule {
}

Categories

Resources