I have the below setup in my app.routing.module.ts.
app.component.html
<router-outlet></router-outlet>
modules/core/components/home/home.component.html
<mat-sidenav-container autosize>
<mat-sidenav #sidenav role="navigation">
<!--this is a place for us to add side-nav code-->
<wn-sidenav-list (sidenavClose)="sidenav.close()"></wn-sidenav-list>
</mat-sidenav>
<mat-sidenav-content>
<!--in here all the content must reside. We will add a navigation header as well-->
<wn-header (sidenavToggle)="sidenav.toggle()"></wn-header>
<main>
<!-- I want the components child components of the home components to be loaded here -->
<router-outlet></router-outlet>
</main>
<wn-footer></wn-footer>
</mat-sidenav-content>
Problem
When I access localhost:4200/campaigns or localhost:4200/dashboard their respective components are displayed but they aren't using their parent's (home.component.html) view
My Goal
I want all sub-components of the home component to be displayed in the router-outlet of the home.component.html and other components will be displayed in the router-outlet of app.component.html
I've had a setup like this before but I wasn't using modules at the time and it was working perfectly. Is there something about lazy loading that I don't understand?
When I access localhost:4200/campaigns or localhost:4200/dashboard the
components of the campaign module are displayed but they aren't using
their parent's (home.component.html) view
In your route config you are using redirectTo:'/dashboard' so that's why you will see the view of campaign modue
Related
I login using router-outlet tag in main app.component.html and if the login is successful i navigate to home page which is a different component consists of toolbar,side-nav and an area to display my dashboard content.Now in my home page i need another router-outlet where it displays the content upon choosing option in side-nav
my project structure is :
src
--login
----login.component.html
----login.component.ts
----login.component.css
--home-page
dashboard
--dashboard.component.html
--dashboard.component.ts
----home.component.html
----home.component.ts
----home.component.css
--application-details
app-overview
--app-overview.component.html
--app-overview.component.ts
----application.component.html
----application.component.ts
--users
----users.component.html
----users.component.ts
In my app.component.html has the following
<router-outlet></router-outlet>
In login.componnet.ts
upon success this.route.navigate(['/home-page'])
In my app-routing.module.ts
{ path:'', redirectTo:'/login',pathMatch:'full'},
{ path: 'login', component: LoginComponent},
{ path:'/home-page',component:HomePgaeComponent,
children:[
{ path:'',component:DashboardComponent,outlet:'dashboard'},
{ path:'user',component:UsersComponent,outlet:'user'}, ]
},
now as soon as i login based on success condition triggers the page
navigates to dashboard which is inside home page like this
<tool-bar></tool-bar>
<div>
<side-menu></side-menu>
<div class="main-content">
<router-outlet name="dashboard"></router-outlet>
<router-outlet name="user"></router-outlet>
</div>
</div>
here when i click upon the user option from side-nav it appends dashboard
content as well as "user" content.I have other options as well so for the
very first time it loads the landing page perfectly but when i select other
side-nav options all the other content is mixed up. So When i select options
from side-nav that respective content should be loaded in content area of
home page.another scenario is when i navigate to homepage i need to navigate
to another page when i perform some click action in dashboard component.
I have gone through tutorials and there they were passing some ids through
services and i have no idea how to do that. As per my knowledge i know that
passing outlet name into router-outlet will fetch the content of that
component likewise as many router i mention those many multiple routers will
be generated.
here when i click upon the user option from side-nav it appends
dashboard content as well as "user" content
<router-outlet name="dashboard"></router-outlet>
<router-outlet name="user"></router-outlet>
Both are children of same component
{ path:'/home-page',component:HomePgaeComponent,
children:[
{ path:'',component:DashboardComponent,outlet:'dashboard'},
{ path:'user',component:UsersComponent,outlet:'user'}, ]
},
Either you use same router outlet to render both dashboard and user or you have user router outlet inside dashboard and user is child of dashboard.
Here is my template section:
<template>
<!-- START Home.vue section -->
<div class="container-fluid" v-if="user.authenticated">
<!-- START Sidebar.vue section -->
<sidebar-component></sidebar-component>
<!-- END Sidebar.vue section -->
<div class="main-container">
<!-- START Nav.vue section -->
<nav-component></nav-component>
<!-- END Nav.vue section -->
<!-- START Content Section -->
<router-view></router-view>
<!-- END Content Section -->
</div>
</div>
<!-- END Home.vue section -->
</template>
Clearly it has 3 components: NavComponent,SidebarComponent, Main component area that will be replaced by the routed component.
I have another component ApplicationList component that when will replace the router-view section of above template, is supposed to cause the sidebar component to behave differently(say for example sidebar becomes hidden or its background becomes red).
So how do I do it?
Install https://github.com/vuejs/vuex-router-sync . It will give you your current route state in your Vuex.
In your <sidebar-component> just refer to this.$store.state.route.name (or path, or whatever you need) and use it in your v-if or some watch .
This is the easiest and most scalable solution to handle changes in components based on current route in application.
Hope it helps.
How can I use template inheritance (Like what jade has, extends file.jade and then the blocks with the same name would be overwritten)?
I know that I can do everything with composition, but for components like footer and header which appear on every single page except one or two (e.g.login page) I must write them on every single component. In my app I have a two level navigation and it seems painful to repeat them on every one of those child components :(
I know that I can use jade and then inherit a jade file within my components, but it seems wrong because I would have some jade and some Vue files, is there any other way to do this?
// Component.vue
<template lang="jade">
extends ./StandardLayout
block content
router-view
</template>
// StandardLayout.Vue
<template lang="jade">
div
navbar
div.container
div.spacer
div.row
block content
<template>
What I've settled for, is a layouts folder filled with jade layouts and I use them to extend my components. I used vue-cli with webpack template.
In the most general case if you have to repeat the same HTML over and over, one option you could use is <partial>s.
<partial name="header"></partial>
<div>My content content</div>
<partial name="footer"></partial>
Where you declare partials as
Vue.partial('header', '<h3>This is the title: {{title}}</h3>')
Vue.partial('footer', '<footer>Mini footer</footer>')
However if you are building a Single Page Application the strategy you could follow is to simply have a header and a footer around your <router-view>, here is a jsfiddle that demonstrates how to do.
https://jsfiddle.net/gurghet/vdqutw2y/
<header><h1>
My title: {{title}}
</h1></header>
<p>
<a v-link="{ path: '/foo' }">Go to Foo</a>
<a v-link="{ path: '/bar' }">Go to Bar</a>
</p>
<router-view></router-view>
<footer>Such footer, many links, wow!</footer>
If you know Chinses, please look it
// Base Component
<template>
<div class="base-thing special-class">
<Button />
</div>
</template>
<script>
import Button from './ButtonClick'
export default {
components: { Button }
}
</script>
// Inheriting Component
<script>
import BaseComponent from './BaseComponent'
import Button from './OtherButton'
export default {
extends: BaseComponent
components: {
Button
}
}
</script>
The Button of Child Component will be replaced OtherButton. We can do something in the OtherButton
I'd like to use two separate layouts for my aurelia app. Difference between them is that one doesn't have a sidebar. Currently I'm using one layout file defined as below:
<template>
<div class="container">
<router-view></router-view>
</div>
</template>
If an active route needs this sidebar to appear I'm just putting it into its view.
What I'd like to achieve is to add another layout that would have this sidebar by default:
<template>
<require from="../common/elements/sidemenu/sidemenu"></require>
<div class="container">
<sidemenu></sidemenu>
<router-view></router-view>
</div>
</template>
So the question is - how to do this? Is it even possible with an aurelia app to have multiple layouts (or master pages, however you call those)?
Use aurelia.setRoot()
You can manually set up your application by specifying a script with configure instructions in your index.html. Typically, this is set to main.
index.html
<body aurelia-app="main">
In this script you can specify a root view model using aurelia.setRoot('root'). If no argument is provided, the convention is to use 'app'.
main.js
aurelia.start().then(() => aurelia.setRoot());
However, you can inject the aurelia object anywhere in your application, and call the setRoot function at any time to load a different root view model.
home.js
#inject(aurelia)
export class HomeViewModel {
constructor(aurelia) {
this.aurelia = aurelia;
}
doStuff() {
this.aurelia.setRoot('withSidebar');
}
}
One common use case for this is having a login page, and I've created a complete template for this use case that you can review, clone, or fork here: http://davismj.me/portfolio/sentry/
I have a nested route that looks like:
/products
/products/:productId
And the /products template renders with a sidebar listing all the products, and a "main" content <div> in the center that is populated with a specific product when clicked. ie:
<div id="productsSidebar">
... navigation tree ...
</div>
<div id="mainContainer">
{{outlet}}
</div>
However, I would like for the {{outlet}} to be replaced with a message like
Please select a product to the left.
When there is no child route, ie. we're just looking at /products and the main <div> is otherwise completely empty.
I haven't found any reference/tutorial demonstrating if this is possible - is there a standard way to render a "default" block of HTML if there no outlet available?
You can use the products index route template to display that html text. You may need to generate the route with something like ember g route products/index