I have a standard admin layout, where all main tabs are lazy loaded modules with separate state management. This is all wrapped in admin component with sidebar and router-outlet. One of my lazy-loaded admin tabs has a special component, which is supposed to open a full-screen preview of a product, occupying admin sidebar and navbar with it's own content.
My app router looks something like this:
export const appRoutes: Routes = [
/// ... some routes
{ path: 'admin', component: AdminComponent, canActivate: [SignedInGuard], children: [
/// ... some admin child routes
{ path: 'scrapers', loadChildren: '../scrapers/scrapers.module#ScrapersModule'}
/// ... some admin child routes
]}
/// ... some routes
]
And my scrapers module routes look like this:
export const scrapersRoutes: Routes = [
{ path: '', component: ScrapersListComponent },
{ path: 'single/:version', component: SingleScraperComponent, children: [
{ path: '', redirectTo: 'statistics', pathMatch: 'full' },
{ path: 'statistics', component: ScraperStatisticComponent },
{ path: 'targets', component: ScraperTargetsComponent },
]},
{ path: 'compare', component: CompareScrapersComponent },
{ path: 'preview', component: ScrapersPreviewComponent }
];
My goal is to open preview route of the scrapers module on the same outlet as admin.
My ideas for now:
a) overkill with html/css (very bad idea)
b) create a separate module for preview. Sounds resolute, but it hardly depends on scrapers lazy-loaded state, so I would not do this
c) load preview in a higher hierarchy outlet. If there is a valid way to do it, I would choose this.
Please, share your thoughts. Thanks!
Related
I have app component in which i lazy load create-new-module with component profilecomponent. now in profile component i hit router.navigate and trying to load another children detail in place of profile but its not working also no error in console.
please help
// App component route
const routes: Routes = [
{
path: 'create-new-emp',
loadChildren: () => import('./create-new-emp/create-new-emp.module').then(c => c.CreateNewEmpModule),
},
{ path: '', redirectTo: 'create-new-emp', pathMatch: 'full'},
{ path: '**', redirectTo: 'create-new-emp'}
];
// Emp Module Route
const routes: Routes = [
{ path: '', component: ContainerComponent,
children: [
{ path: '', component: ProfileComponent, outlet: 'form'},
{ path: 'profile', component: ProfileComponent, outlet: 'form'},
{ path: 'detail', component: DetailComponent, outlet: 'form' }] }
];
// Trying to hit below link but not working
this.router.navigate(['detail'])
<app-component>
<router-outlet>
<container-component>
<profile-component></profile-component>
</container-component>
</router-outlet>
</app-component>
Complicated with only these information to help. But is the way angular navigates amount components/pages. I think what you are trying to do is navigate between components (according your router.ts). If you want to navigate, you only need router-outlet in your html code and not use component tag in the HTML code.
Change this:
<app-component>
<router-outlet>
<container-component>
<profile-component></profile-component>
</container-component>
</router-outlet>
</app-component>
To this:
<app-component>
<router-outlet>
</router-outlet>
</app-component>
Then, into ContainerComponent.html you need to repeat to navigate to details o profile because these are child routes.
<router-outlet></router-outlet>
That will give you more information about what you need.
Its hard to say with this info, but may... you should define de router outlet name
<router-outlet name="form"></router-outlet>
Hope it's help.
I have a problem with my angular 8 app, not rendering into a named router-outlet.
The routes are:
routes.module:
const routes: Routes = [
...
{
path: 'settings', loadChildren: './settings/settings.module#SettingsModule', canActivate
},
]
settings.module
RouterModule.forChild([
{
path: '', component: SettingsComponent
},
{
path: 'profile', component: ProfileComponent, outlet: 'settings_o'
},
{
path: 'users', component: UsersComponent, outlet: 'settings_o'
}
])
settings.component.html
<nav mat-tab-nav-bar color="primary" class="bg-whitesmoke primary">
<span mat-tab-link
*ngFor="let link of navLinks"
[routerLink]="[{outlets: {settings_o: [link.link]}}]"
routerLinkActive #rla="routerLinkActive"
[active]="rla.isActive">
{{link.label}}
</span>
</nav>
<router-outlet name="settings_o"></router-outlet>
When I click a link, the url in the address bar changes (e.g. to http://localhost:4200/settings/(settings_o:profile)), but no content is rendered to settings_o, nor do the components get loaded. There is no error in the console.
link.link is, for example simply profile like in settings.module's routes.
What do I need to change?
This is a known bug which has been discussed a lot: https://github.com/angular/angular/issues/10981
As far as I know it hasn't been solved completely but there are workarounds: https://github.com/angular/angular/issues/10981#issuecomment-454425220
You should give the lazy loaded module a default route and define the child routes for the components that you would like to open in the named outlet, for example:
RouterModule.forChild([
{
path: "default",
component: SettingsComponent,
children: [
{ path: "profile", component: ProfileComponent,outlet: "settings_o" },
{ path: "users", component: UsersComponent, outlet: "settings_o" }
]
}
]);
Of course you have to change the navigation to the SettingsComponent accordingly: routerLink='/settings/default'
I made a Stackblitz which is not an exact copy of your code but which shows how it can be solved: https://stackblitz.com/edit/angular-nctjpv
By the way, in your original solution, if you placed the named router outlet in the root component, I think it would display the child component but in the wrong place.
I'm working on an Angular 6 application. Currently I'm struggling with routing. I'm interested, whether mine structure, what I have imagined can work or not. So it looks like this:
App module - contains main routing with some parent route, where layout is defined. Like this:
const routes: Routes = [
{
path: 'login',
component: LoginComponent
},
{
path: '',
component: LayoutComponent,
canActivate: [AuthGuard],
canActivateChild: [AuthGuard],
children: [
// {
// path: 'brands',
// loadChildren: 'app/modules/brands/brands.module#BrandsModule',
// pathMatch: 'prefix'
// }
]
}
];
#NgModule({
imports: [RouterModule.forRoot(routes), BrandsModule, ItemsModule],
exports: [RouterModule],
providers: [BosRouteLoader]
})
export class RoutingModule {}
One of mine feature module defines its own routing in a module like this:
const routes: Routes = [
{
path: 'brands',
children: [
{ path: '', component: BrandListComponent },
{ path: ':id', component: BrandDetailComponent },
{ path: '**', redirectTo: '' }
]
}];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class BrandsRoutingModule {}
I would like to achieve that every feature module will define its own routing and those routes are registered as a child routes of the App module.
With lazy loading I can manage it but then I have to define one more route always in mine App module, however I just want to define it in feature module.
If I do it without lazy loading, then mine parent route in App component is never hit. So if I go to http://localhost/brands it will load the appropriate BrandLisComponent but without LayoutComponent.
Is ther a way to define routes in feature module and register them as a child of main main routing module?
The concept is that you define a module routing in your higher-level module and then define its children in your desired module.
So in your case, you need to tell the angular that, hey when someone goes to brands route, use BrandsRoutingModule routings.
So in your app module, you're going to have:
{
path: 'brands',
loadChildren: 'app/modules/brands/brands.module#BrandsModule',
canActivate: [AuthGuard],
canActivateChild: [AuthGuard],
}
This tells that you need to load the routing of that module if the user goes to /brand.
Then in your BrandsRoutingModule, you need to define routes to be:
{
path: '',
component: LayoutComponent,
children: [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: BrandListComponent },
{ path: ':id', component: BrandDetailComponent },
{ path: '**', redirectTo: '' }
]
}
So whenever we route to /brands, we shall see the LayoutComponent as a main route relative to that and then the BrandListComponent and others will come as his children. But to show his children, you also need to put this line of code in your layout.component.html:
<router-outlet></router-outlet>
this tells angular that, hey if he's going to for example /brands/2, you need to load the BrandDetailComponent inside the LayoutComponent, literally as his child.
Hope it helps.
Imans77's answer works for lazy loaded modules (although the string from of LoadChildren is now deprecated). However, with eager loaded modules, if you want to tidy up the main routes module and split the file accross different modules, you could try the following approach:
app-routing.module.ts
const MODULE_ROUTES = [...module1Routes, module2Routes];
const routes: Routes = [
{ path: 'path1', component: Path1Component },
{ path: 'path2', component: Path2Component },
...MODULE_ROUTES,
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Instead of declaring all children of every component/module in the main routing file, you could create a *.route.ts file for each feature module, in which you could just declare and export routes in a normal way. For example:
export const module1Routes: Routes = [
{
path: 'brands',
children: [
{ path: '', component: BrandListComponent },
{ path: ':id', component: BrandDetailComponent },
{ path: '**', redirectTo: '' }
]
}];
By importing it in the main routing file, they would immediately be available for Angular.
I'm pretty new to Vue and I just can't find a good way how to use nested components alongside with vue-router.
What I have so far (some not-important code omitted):
index.html
<body>
<div id="app">
<router-view></router-view>
</div>
app.js
const router = new VueRouter({
routes: [{ path: '/login', component: Login }]
})
const app = new Vue({
router,
}).$mount('#app')
components/Login.vue
<template>
<h1>Please log in</h1>
</template>
This works perfectly well - I navigate to /login and it shows me the message in h1 tag. If I create more components, like Register or ResetPassword and add them to the router, it still works well. But the problem is that there is some repeating code in those components (for example, I want all the auth-related pages to have blue background) so I'd like to somehow create a "parent" component, that would define stuff that is same for all the "children" components. Something like:
Auth component (makes the page-background blue)
-> Login component (shows the login form)
-> Register component (shows the registration form)
I know I can do this through route's "children":
const router = new VueRouter({
routes: [
{ path: '/', component: Auth, children: [
{ path: '/login', component: Login }
{ path: '/register', component: Register }
]}
]
})
But with this configuration, there is the main route path: '/', which is completely wrong - I don't want it here - I don't want the Auth component to be used "standalone" - I want it just as a "wrapper" for the nested components.
What is the best way to solve this problem?
The way I've solved this issue is to use a base path redirect.
{ path: '', redirect: '/to/path' },
in your case it would be
const router = new VueRouter({
routes: [
{
path: '/',
component: Auth,
children: [
{ path: '', redirect: '/login' },
{ path: '/login', component: Login },
{ path: '/register', component: Register }
]
}
]
})
This ensures that
I have an app component an its use router-outlet, and a main component (what is loaded at router-outlet)
Now I would like to place packages in that component where we can insert widgets.
App component:
<cover></cover>
<div fxFlexFill fxLayout="row" fxLayoutAlign="stretch">
<div fxFlex>
<router-outlet></router-outlet>
</div>
</div>
Main component:
<app-header></app-header>
<main-widget></main-widget> //place where I would like to load custom content
<left-widget></left-widget> //place where I would like to load custom content
<right-widget></right-widget> //place where I would like to load custom content
Main component is come from a coreModul(share module) - this is a framework we have no access to it on project level.
So I would like to put content into widgets, but have no idea how to do that.
The hard thing to me is how to pass a component into a router-outlet and show it in right place. Its possible to use ng-templates in this case?
EDIT:
App routing:
import { RouterModule, Routes } from '#angular/router';
import {
LoginComponent,
LoginGuard,
MainComponent,
} from './../_system';
import { USERS_ROUTES, UsersComponent } from './../users';
const APP_ROUTES: Routes = [
{ path: 'login', component: LoginComponent },
{ path: '', component:MainComponent, canActivate: [LoginGuard], children: [
{ path: 'users', children: USERS_ROUTES},
{ path: '', redirectTo: '/login', pathMatch: 'full'},
{ path: '**', redirectTo: '/questions'}
]}
];
export const AppRoutingModule = RouterModule.forRoot(APP_ROUTES);