In a SPA, I have made a header component which changes slightly on each page.
export default {
name: 'header',
//add some stuff based on user data
data: function (router) {
return {
//some data
}
},
}
And here are my routes:
export default [
{path:'/', component: showJokesAll },
{path:'/hot', component: showJokesHotAll },
{path:'/add', component: addJoke } ,
{path: '/login', component: webLogin},
{path: '/profile', component: webProfile},
{path: '/auth', component: webProfile},
]
I'm wondering what is the correct way to inject the header component into all routes?
Update: When I try to import the header component into app's main.js:
import Header from './components/header.vue'
Vue.component('page-header', Header);
I get this error:
Failed to mount component: template or render function not defined.
If you want to have the same header component in all routes. place it before router-view and change your css layout.
If you wan't to change the content of the header component depending on each route. You can place another <router-view name="header"> inside your header component. And then in your array of routes
<template>
<div>
<app-header><../>
<router-view><../>
</div>
</template>
Otherwise:
export default [
{
path:'/',
components: {
default: defaultComponentForThisRoute,
header: yourRouteHeaderComponent,
}
},
]
Related
I'm using for the first time quasar router, I already know how to use Vue router and this one should be almost the same, and it quite is but the problem is it doesn't work, I have created a Login Page and tried to insert the route in routes.ts file but now i can't access the main page neither the login one, and when I look in the console I get this error: "Failed to fetch dynamically imported module: http://localhost:9000/src/layouts/MainLayout.vue".
Here's the code:
Routes.ts
import { RouteRecordRaw } from 'vue-router';
const routes: RouteRecordRaw[] = [
{
// Main Page
path: '/',
component: () => import('layouts/MainLayout.vue'),
children: [
{ path: '', component: () => import('pages/QuestionsPage.vue') },
],
},
{
path: '/login',
component: () => import('pages/LoginPage.vue'),
},
{
path: '/:catchAll(.*)*',
component: () => import('pages/ErrorNotFound.vue'),
},
];
export default routes;
In case you need the login page and the main one:
<script setup lang="ts"></script>
<template>
<q-page padding>
<h1>Login</h1>
</q-page>
</template>
<script setup>
console.log('test');
</script>
<template>
<q-page padding>
<h1>Main Page</h1>
</q-page>
</template>
File structure:
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 creating a vuejs app, in which I want to have two different layouts like one for user interface and other for the admin interface.
In the user interface, I have a button named "Admin Panel" on click to this button want to go the admin side and render the new layout. So far I have done this as follows:
I have created a container folder in my src to keep the layout files
UserPanel.vue
AdminPanel.vue
And also a router folder to keep the route files
user.js
admin.js
index.js
###UserPanel.js###
<template>
<v-app>
<h4>User Layout</h4>
<router-view></router-view>
</v-app>
</template>
<script>
export default {
}
</script>
###AdminPanel.js###
<template>
<v-app>
<h4>Admin Layout</h4>
<router-view></router-view>
</v-app>
</template>
<script>
export default {
}
</script>
###user.js###
import UserPanel from 'Container/UserPanel';
const HomeV1 = () => import('Views/HomeV1');
const HomeV2 = () => import('Views/HomeV2');
const HomeV3 = () => import('Views/HomeV3');
export default{
path: '/',
component: UserPanel,
redirect:'/home',
children:[
{
path: '/',
component: HomeV1 ,
meta: {
header: 1
}
},
{
path: '/home',
component: HomeV1 ,
meta: {
header: 1
}
},
{
path: '/home-two',
component: HomeV2 ,
meta: {
header: 2
}
},
{
path: '/home-three',
component: HomeV3 ,
meta: {
header: 3
}
}
]
}
###admin.js###
import Admin from 'Container/Adminpanel.vue';
const Reports = () => import('Views/AdminPanel/Reports.vue');
const Invoice = () => import('Views/AdminPanel/Invoices.vue');
const AdminAccount = () => import('Views/AdminPanel/Account.vue');
export default {
path: '/admin-panel',
component: Admin,
redirect:'/admin-panel/reports',
children:[
{
path: '/admin-panel/reports',
component: Reports,
name:'Reports'
},
{
path: '/admin-panel/invoices',
component: Invoice,
name:'Invoice'
},
{
path: '/admin-panel/products',
component: AdminProducts,
name:'AdminProducts'
}
]
}
###index.js###
import Vue from 'vue'
import Router from 'vue-router'
import userRoutes from './user';
import adminRoutes from './admin';
Vue.use(Router);
export default new Router({
mode: 'history',
routes: [
userRoutes,
adminRoutes
]
})
Now only my user routing is working. To show the pages of admin I have to put its route in user.js and after that, it renders the user's layout not admin's layout.
Thank You.
Put attribute meta in the route like this:
const routes = [
{
path: '/admin',
name: 'admin',
meta: { layout: 'LayoutAdmin' },
component: Dashboard,
},
and in App.vue you can render depends of this condition this.$route.meta.layout here an example:
<template>
<div id="app">
<notifications width="400px" />
<LayoutAdmin v-if="this.$route.meta.layout">
<router-view class="content" />
</LayoutAdmin>
<LayoutDefault v-else :links="links" :headerButtons="headerButtons">
<router-view class="content" />
</LayoutDefault>
</div>
</template>
I have played around with this before and the way I did it was to have alternative layouts that switch depending on a route meta field...
So when you define a route, you can add a meta field:
path: '/admin-panel/reports',
component: Reports,
name:'Reports',
meta: { template: 'admin' }
Then you need to check routes as they change. The easiest way to do this is in a global navigation guard (like the example has on their page). If it detects it's an admin page, it changes a Vuex property which will then switch which template you're using.
I will say that in the end I stopped using this method and wrapped all of my pages with wrapper components (admin/user/etc) so I could control everything from Vue itself. This was mainly due to Vue Router's limitations around waiting for a user to be authenticated though so that may not be an issue for you.
I am a beginner of Angular2. When I am learning angular2 routing service from https://angular.io/tutorial/toh-pt5. I want to have herocomponent always displayed so I in the app.component.html like this:
<h1>{{title}}</h1>
<nav>
<a routerLink="/dashboard">Dashboard</a>
<a routerLink="/heroes">Heroes</a>
<a routerLink="/dummy">Dummy</a>
</nav>
<app-heroes></app-heroes>
<router-outlet></router-outlet>
<app-messages></app-messages>
And here is the app-routing.module.ts:
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { DashboardComponent } from './dashboard/dashboard.component';
import { HeroesComponent } from './heroes/heroes.component';
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
import {DummyComponentComponent} from './dummy-component/dummy-component.component';
const routes: Routes = [
{ path: '', redirectTo: '/', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },
{ path: 'detail/:id', component: HeroDetailComponent },
{ path: 'heroes', component: HeroesComponent },
{path: 'dummy',component:DummyComponentComponent}
];
#NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule {}
Strangely, when I click a hero on /dashboard or /heroes page it can direct to the correct URL and show the correct hero detail.
However, when I am on /detail/{{hero.id}} and click the hero on the hero component it can redirect the URL but the content in doesn't update. Can someone please help me with this?
if below is not issue then it should be issue that you are just changing parameter url that is reason its not updating
//put this code in your hero.component.ts file
ngOnInit() {
this.route.params.subscribe((params) => {
this.id = +params['id'];
this.loadComponentAgain();
});
}
above code monitor change in param value and update your component according to it.
There is issue because of this html
<app-heroes></app-heroes>
<router-outlet></router-outlet>
you are loading app-heroes component out side router-outlet, it should be loaded under router-outlet, so you should do this
<!-- <app-heroes></app-heroes> remove this-->
<router-outlet></router-outlet>
For changing a route with dynamic value you need to set your routerLink like this
[routerLink]="['/detail',hero.id]"
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);