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.
Related
I dynamically created sidebar navigation list using router-link.
<template>
<div class="sidebarListItem bg-light">
<router-link
v-for="route in $router.options.routes"
:key="route.path"
:to="route.path"
class="list-group-item list-group-item-action bg-light">
{{route.title}}
</router-link>
</div>
</template>
<script>
export default {
name: "PageSidebarList",
computed: {
routes(){
return this.$router.options.routes
}
},
}
</script>
Each router-link is one map.
But then, I need to use <router-link> in some other place in my app, so I need to register new view (map) in router.js. The problem is I don't want this one view to be in sidebar list and it is automatically because of my code. I tried to separate routes in different files(one that I need for list and the rest of the views) and then importem them in router.js. but still it does't work. Or I don't know how to call them separatelly. I am new to vue and vue-router so please help. Is it possible to do what I want?
It's possible to add custom meta data to each route:
{
path: '/foo',
component: Foo,
meta: { hideInNav: true }
}
And then you can use a v-if on the router-link v-if="!route.meta.hideInNav"
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
Sorry to revive a question. Im using Angular 7 and Im trying to use Router Link.
This is my app-routing-module
const routes: Routes = [
{ path: 'locations' , component : LocationManagerComponent },
{ path: 'locations/create' , component : CreateEditLocationComponent },
{ path: 'locations/create/:id', component : CreateEditLocationComponent },
{ path: '404' , component : PageNotFoundComponent},
{ path: '**' , redirectTo: '/404'}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
This is router link:
<a [routerLink] = "['/locations']" routerLinkActive="active"> test link </a>
When I click on link, nothing happens. The URL on browser changed but component is not loaded.
If I press F5, component is loaded and from that point on, routers link works.
I've tryed a lot of stackoverflow solution like writing link in any sort of variant like
<a routerLink="/locations" ...
<a [routerLink]= ['/locations'] ...
<a [routerLink]= "['/locations']" ...
With or without LinkAttive attribute. Putting
<base href="/">
in index.html etc....
Following this topic: TOPIC I've tried to include Router in my Layout component:
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-layout',
templateUrl: './layout.component.html',
styleUrls: ['./layout.component.css']
})
export class LayoutComponent implements OnInit {
constructor(
private route : ActivatedRoute
) { }
[...]
but nothing changes.
The strange part is that after an F5, all routes works, even route to component not yet loaded.
In this topic TOPIC 2 the user resolved removing css class. I've tried to put my link in a completely cleaned component HTML and it not working (but still works after a refresh).
<p>
dashboard works!
<a routerLink = '/locations' routerLinkActive="active"> test link </a>
</p>
UPDATE: This is layout.component where route tag is.
I can't figure out how to have a Sidenav without having route-outlet inside it.
<mat-sidenav-container fullscreen>
<mat-sidenav #sidenav mode="over">
<div class="profile_container">
<span> User Name </span>
</div>
<mat-nav-list>
<mat-list-item><a [routerLink]="['/locations']" routerLinkActive="active"> Locations
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<app-header (toggleSidenav)="sidenav.toggle()"></app-header>
<div style="padding: 20px 10px 10px 20px;">
<router-outlet></router-outlet>
</div>
</mat-sidenav-content>
</mat-sidenav-container>
Note: this answer is based on the previous version of your question, before you added the code of layout.component.html. So, instead of layout component, I am using the simplified dashboard component.
The below is working for me in Angular 8.1.
app.component.html
<app-dashboard></app-dashboard>
means that the DashboardComponent is contained within (is the child of) the AppComponent.
No change to the default app.component.ts
dashboard.component.html
<p>
dashboard works!
<a routerLink = '/locations' routerLinkActive="active">
Locations test link </a>
</p>
<p><a routerLink = '/locations/create' routerLinkActive="active">
Locations/create </a></p>
<p><a routerLink = '/locations/create/:id' routerLinkActive="active">
Locations/create/:id </a></p>
<p>router-outlet is below:</p>
<router-outlet></router-outlet>
All the links are working with click and with manually entering the url (eg: http://localhost:4200/locations/create/:id) in the browser and with reload (F5).
New Components
Generated using the ng generate component command:
Dashboard
LocationManager
CreateEditLocation
PageNotFound
app-routing-module.ts
The same as your file, but also added import statements for the newly generated components.
I figured what cause the problem but I can't unserstand why and I was not able to reproduce in StackBlitz.
This was my app.component.html, the root of all app:
<main>
<!-- Showing All Site Pages -->
<span *ngIf='isLogged()'>
<app-layout style="height:100%"></app-layout>
</span>
<!-- Showing Login Page -->
<div *ngIf='!isLogged()'>
<router-outlet></router-outlet>
</div>
</main>
The App-Layout code is above.
THIS NOT WORKS!
I changed it with a simply:
<main>
<app-layout style="height:100%"></app-layout>
</main>
As you see from my question, Layout has its own router-outlet.
I think the problem is the two router-outlet tag. Maybe Angular is not able to understand thats they are mutually exclusive. Maybe when I was clicking on menu, for some reason, Angular was updating the "first" router-outlet encountered and only after a refresh (F5), when the isLogged was already triggered and the app-layout was loaded directly, Angular knows which router-outlet to use.
In the new Way all pages, even Login, has to be child of AppLayout so every Layout component that's exists only if logged, has to be manually hide with *ngIf='!isLogged()'
A little price to pay to have routes works.
I have created toolbar and related components in my app
So here is layout I have created
<div fxLayout="column">
<div>
<app-platformbar ></app-platformbar>
</div>
<div>
<router-outlet></router-outlet>
</div>
</div>
platforbar component is common for all routing
<md-toolbar color="primary" >
<span><h2>{{Name}}</h2></span>
<span *ngIf="showLogoutBtn"><button md-raised-button color="warn" (click)="logout()">Logout</button></span>
</md-toolbar>
Inside platforBar component I have created one logout button which I don't want show on login( component) router
I have stored user object inside userservice to identify whether the user is logged in or not.
based on logged in I want to hide logout button.
So what I want to once user click on logout button from home router It will redirect it to login router but logout button from platformbar component is still there
So I want to hide it on login router.
We have a requirement of opening a modal dialog containing a route or a component. We are looking for some modal components, and saw ember-bootstrap's modal is useful.
So,
How can we open any route as a modal dialog ? (If parent route decides a route to be open in a modal, the child route should be open in modal.)
Can we create a service, to pop up a modal dialog? Such as: ModalDialogService.popup(title, bodyComponent, commitHandler, cancelHandler); or ModalDialogService.popup(title, routeName, commitHandler, cancelHandler); And how can we do this without violating the Data Down Action Up principle?
Is there any guide, document, tutorial or npm package for implementing modals in ember.js?
UPDATED:
What I need is to open any of the current routes in a modal. For example, in a given route hierarchy:
-module1
|-module1.query
|-module1.add
|-module1.update
|-module1.delete
Currently module1.query has transitions to others. But I want to give an option to the module developers to open any of the add, update, delete routes in a modal. So that query route doesn't lose its state, when an add operation finished.
Also we have some services used by components. At some conditions, services need to display a modal that has a component.
You should be able to use a service and component similar to one below to achieve what you want.
Have a look at the twiddle for a demo of how this works exactly, and the code below for quick reference
Your route template could look something like this.
// templates/hasmodal.hbs
{{#bs-modal}}
Modal Content
{{/bs-modal}}
Your route hooks, with service injected
// routes/hasmodal.js
export default Ember.Route.extend({
modalNavigation: Ember.inject.service(),
activate(){
console.log('openingModal')
this.get('modalNavigation').openModal()
},
deactivate(){
console.log('closingModal')
this.get('modalNavigation').openModal()
},
actions: {
onClose(){
console.log('we want to close route')
}
}
})
Your bs-modal or relevant component
//components/bs-modal.js
export default Ember.Component.extend({
modalNavigation: Ember.inject.service(),
isOpen: Ember.computed.alias('modalNavigation.modalOpen'),
classNameBindings: ['isOpen:modalDialog:notOpen'],
actions: {
close(){
this.get('modalNavigation').closeModal()
}
}
})
The bs-modal component template
// templates/components/bs-modal
<div>
{{yield}}
</div>
<button class='close' {{action 'close'}}>Close Me</button>
Your Modal Service to manage state
// services/modal-navigation.js
export default Ember.Service.extend({
modalOpen: false,
openModal(){
this.set('modalOpen',true)
},
closeModal(){
this.set('modalOpen',false)
}
})
UPDATE:
updated twiddle
It basically nests routes that contain a modal underneath a route you want to preserve the state of and show behind the modal.
// router.js [truncated]
Router.map(function() {
this.route('module1',function(){
this.route('query',function(){
this.route('add')
this.route('update', { path: '/update/:item_id' })
this.route('delete', { path: '/delete/:item_id' })
})
})
// templates/modules1/query.hbs
Queried List {{link-to 'add item' 'module1.query.add'}}<br/>
<ul>
{{#each model as |item|}}
<li>
{{item.id}}-{{item.title}}
{{link-to 'u' 'module1.query.update' item}}
{{link-to 'd' 'module1.query.delete' item}}
</li>
{{/each}}
</ul>
{{outlet}}
// templates/module1/query/add.hbs
{{#modal-component isOpen=true onClose=(action "routeClosed")}}
<div>
Title:{{input value=model.title}}
</div>
<button {{action 'save'}}>Save</button>
{{/modal-component}}
Where all the other sub components follow the same modal wrapper principle