Login and Log out routing with material Sidenav - javascript

Hi I'm using Angular 4 with Angular Material 2 where I need some assistance in the routing. Currently I have the login component loaded when the app starts from the router-outlet in AppComponent, and when logged in the routing takes place inside the router-outlet in the Sidenav. The Sidenav is inside a HomeComponent and when logging out it cannot find the parent LoginComponent. How should I configure my routes, as I'm Not sure how to use child routes in Angular.
Inside app.routing
const appRoutes: Routes = [
{
path: '',
redirectTo: '/login',
pathMatch: 'full'
}
];
app.component.html
<router-outlet></router-outlet>
Home.Component.html
<md-sidenav-container *ngIf="isLoggedIn$ | async as isLoggedIn">
<md-sidenav #sidenav mode="over" opened="true">
</md-sidenav>
<md-toolbar color="primary">
<md-icon class="menu" (click)="sidenav.toggle()">menu</md-icon>
<span class="example-spacer"></span>
<button md-icon-button routerLink="/dashboards/surveys">
<md-icon class="example-icon">dashboard</md-icon>
</button>
<button md-icon-button [mdMenuTriggerFor]="menu">
<md-icon>person</md-icon>
</button>
<md-menu #menu="mdMenu">
<button md-button (click)="onLogout()" *ngIf="isLoggedIn">
<md-icon>exit_to_app</md-icon>
<span>Log out</span>
</button>
</md-menu>
</md-toolbar>
<div class="main-content">
<router-outlet></router-outlet>
</div></md-sidenav-container>
Any Idea of how to get the Proper routing here? Help would be appreciated.

Using child routes would be the best way to do it. For that you're going to need 2 router outlets in different component templates. Let's look at this example of routing:
{
path: 'login',
component: LoginComponent
},
{
path: '',
component: HomeComponent,
children: [
{
path: '',
component: DashboardComponent
},
{
path: 'somewhere/view',
component: SomeComponent
},
{
path: 'ducks',
component: DuckComponent,
canActivate: [QuackGuard]
}
}
Then you need a <router-outlet></router-outlet> in both your AppComponent and HomeComponent
Here's the app component template with a router outlet in it:
<div class="content">
<router-outlet></router-outlet>
</div>
And then, in your home component template, you'll need this:
<md-sidenav-container>
<router-outlet></router-outlet>
</md-sidenav-container>
(Of course, everything is cut for brevity but it's just a concept explanation anyway).

Related

VueJS 3 - <router-link-active> class not applied to routes that start with the same path name

I have created a simple navar where I have 3 links. All links are declared at a ROOT level of the router object. I've added a simple styling targeting the <router-link-active> class where the active link is highlighted on the navbar. This all works fine, switching between links updates the URL, changes the <router-view> as well as applies correct style to the navbar link currently on.
The issue I'm having is that whenever I click on a 4th link which is also declared on the ROOT level of the router object, starting with the same path name as currently active link, the <router-link-active> class disasters. e.g.
{ path: "/link2", component: link2 },
{ path: "/link2/sibling", component: sibling },
My understanding is because the /links2/sibling starts with the same name as /link2, the navbar item that navigates to /link2 should still be have the <router-link-active> class, even when the /link2/sibling is currently active URL.
Codesandbox
App.vue
<template>
<div>
<ul class="flex gap-x-5">
<router-link to="/">
<li>Link 1</li>
</router-link>
<router-link to="/link2">
<li>Link 2</li>
</router-link>
<router-link to="/link3">
<li>Link 3</li>
</router-link>
</ul>
</div>
<router-view />
</template>
<script>
export default {
name: "App",
};
</script>
<style>
a:hover,
a:active,
a.router-link-active {
color: #f1a80a;
border-color: #f1a80a;
background-color: #1a037e;
}
</style>
main.js
import App from "./App.vue";
import router from "./router.js";
const app = createApp(App);
app.use(router);
app.mount("#app");
router.js
import { createRouter, createWebHistory } from "vue-router";
import link1 from "./components/link1.vue";
import link2 from "./components/link2.vue";
import sibling from "./components/sibling.vue";
import link3 from "./components/link3.vue";
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: "/", component: link1 },
{ path: "/link2", component: link2 },
{ path: "/link2/sibling", component: sibling },
{ path: "/link3", component: link3 }
]
});
export default router;
link1.vue
<template>
<div>You are inside Link1</div>
</template>
link2.vue
<template>
<div>
<router-link to="/link2/sibling">
You are inside Link 2 (CLICK ME)
</router-link>
</div>
</template>
link3.vue
<template>
<div>You are inside Link 3</div>
</template>
sibling.vue
<template>
<div>You are inside Link2 sibling</div>
</template>
I think that is the natural behavior that we could expect from routing. when you click on You are inside Link 2 (CLICK ME) inside link2.vue component, the vue-router loads sibling.vue in the router-view part in your App.vue. So there is no You are inside Link 2 (CLICK ME) link in that view to see the router-link-active styles. If you want to see that styles, you must keep your link in the view and don't allow vue-router to disappear that.
For achieving such a goal you can use Nested Routes in vue-router like this. First change your router.js file to something like this:
import { createRouter, createWebHistory } from "vue-router";
import link1 from "./components/link1.vue";
import link2 from "./components/link2.vue";
import sibling from "./components/sibling.vue";
import link3 from "./components/link3.vue";
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: "/", component: link1 },
{
path: "/link2",
component: link2,
children: [
{
path: 'sibling',
component: sibling
},
]
},
// { path: "/link2/sibling", component: sibling
//
// },
{ path: "/link3", component: link3 }
]
});
export default router;
And then add a <router-view> to your link2.vue file like this:
<template>
<div>
<router-link to="/link2/sibling">
You are inside Link 2 (CLICK ME)
</router-link>
<router-view></router-view>
</div>
</template>

Router outlet inside primary router outlet doesn't display anything with no errors

Cant seem to find what the issue is here as I'm getting no errors from Angular.
I am trying to get a router-outlet inside the primary router-outlet to display a component. Im correctly selecting the router but it is not showing the component i have selected in the second outlet.
app-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
const routes: Routes = [
{ path: 'dashboard', loadChildren: () => import('./pages/dashboard/dashboard.module').then(m => m.DashboardModule) }
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
dashboard-routing.module.ts
// ...
const routes: Routes = [
{ path: '', component: DashboardComponent },
{ path: 'forms', component: FormsComponent, outlet: 'sidebar' },
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class DashboardRoutingModule { }
dashboard.component.html
<app-header></app-header>
<mat-sidenav-container>
<mat-sidenav mode="side" opened>
<mat-nav-list>
<a mat-list-item [routerLink]="[{ outlets: { sidebar: ['forms'] } }]" routerLinkActive="active">Forms</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<main class="bfa-main">
<router-outlet name="sidebar"></router-outlet>
</main>
</mat-sidenav-content>
</mat-sidenav-container>
<app-footer></app-footer>
The routerlink is correctly selected and displays an active class, as well as a link too:
http://localhost:4200/dashboard/(sidebar:forms)
However there is nothing displayed here and no errors, when i am expecting to see the forms component inside the inner router outlet named sidebar
Does anyone know what I'm missing here?
Thanks
Decided to have the dashboard as a wrapper instead for each of the dashboard components using ng-content
<app-header></app-header>
<mat-sidenav-container>
<mat-sidenav mode="side" opened>
<mat-nav-list>
<a mat-list-item [routerLink]="['forms']" routerLinkActive="active">Forms</a>
<a mat-list-item [routerLink]="['users']" routerLinkActive="active">Users</a>
<a mat-list-item [routerLink]="['posts']" routerLinkActive="active">Posts</a>
<a mat-list-item [routerLink]="['pages']" routerLinkActive="active">Pages</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<main class="bfa-main">
<ng-content></ng-content>
</main>
</mat-sidenav-content>
</mat-sidenav-container>
<app-footer></app-footer>

Internal page navigation using Angular 7

I have a full working ASP.Net Zero application navigation working. Now I created an internal page I want to navigate, something like this:
With the following structure:
Content of test.component.html:
<div [#routerTransition]>
<div class="m-content">
<div class="m-portlet m-portlet--mobile tests">
<div class="row">
<div class="col-md-6 col-sm-12">
<div class="m-portlet__head">
<div class="m-portlet__head-caption">
<div class="m-portlet__head-title">
<h3 class="m-portlet__head-text">Spellings</h3>
</div>
</div>
</div>
<router-outlet></router-outlet>
</div>
</div>
</div>
</div>
There I defined the <router-outlet> to navigate using the "Navigation Area" of the pic.
I created a custom routing navigation defined in spelling-routing.module.ts:
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { TestComponent } from './test-list/test.component';
import { QuestionComponent } from './questions/questions.component';
import { TestContainerComponent } from './test-list/test-container/test-container.component';
#NgModule({
imports: [
RouterModule.forChild([
{
path: '',
component: TestComponent,
children: [
{ path: 'test-container', component: TestContainerComponent, data: { permission: 'Pages.Tenant.Tests' } },
{ path: 'questions/:testId', component: QuestionComponent, data: { permission: 'Pages.Tenant.Tests' } }
]
}
])
],
exports: [
RouterModule
]
})
export class SpellingRoutingModule { }
This works to load the main test.component.html, but can't fill the <router-outlet> inside it to navigate to some inner Components.
Please, how to fill the <router-outlet> object of test.component.html with a default one?
See the src folder content here:
Dropbox link to src folder

Error: Cannot match any routes. URL Segment: 'cmcwebapp'

I am using angular 4. My angular app works fine when I run it with "ng serve". That's when it run with context-root as "/".
My app need to compile with java webapp and is Deployed to servlet-container as part of war file. this app runs under context-root 'cmcwebapp'.
my index.html has element
<base href="/">
just under "head" element. and When I compile angular app I use command
ng build --base-href cmcwebapp
Once this compiles I copy contents of dist folder and paste it into java webapp and creates a war file.
when I run this on browser with "http://localhost:8080/cmcwebapp". all the javascript, css and images loads fine. the URL changes to "http://localhost:8080/cmcwebapp/cmcwebapp/" and I get this "Error: Cannot match any routes. URL Segment: 'cmcwebapp'".
I have this as my routes definition in app.module.ts
const appRoutes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'distribute', component: DistributeComponent },
{ path: 'consume', component: ConsumeComponent },
{ path: '', redirectTo: 'home', pathMatch: 'full'}
];
#NgModule({
declarations: [
AppComponent,
HomeComponent,
DistributeComponent,
ConsumeComponent
],
imports: [
BrowserModule,
HttpModule,
RouterModule.forRoot(appRoutes),
WjGridModule
],
providers: [EppmService],
bootstrap: [AppComponent]
})
export class AppModule { }
and this is my app.component.html
<div class="menu">
<nav class="navbar navbar-inverse" style="overflow:hidden">
<div class="container-fluid">
<ul class="nav navbar-nav">
<li routerLinkActive="active"><a routerLink="home">home</a></li>
<li routerLinkActive="active"><a routerLink="distribute">Distribute</a></li>
<li routerLinkActive="active"><a routerLink="consume">Consume</a></li>
</ul>
<div class="submission">
<button type="button" class="btn btn-primary">Submit</button>
</div>
</div>
</nav>
</div>
<div class="container-fluid">
<router-outlet></router-outlet>
</div>
I am not able to figure out where I am going wrong

Angular2 attribute directive does not work in components rendered in RouterOutlet?

I have been using NG2 since the final release 2.0.2 now 2.4.1. Attribute Directives work in simple case like what in the tutorial at https://angular.io/docs/ts/latest/guide/attribute-directives.html, and all tutorials I could find are also with simple case of rendering the directive declared immediately in app.component.html. However, I have components rendered in router outlet as defined in app.component.html like this:
<nav>
<a routerLink="/" routerLinkActive="active"> </a>
</nav>
<div class="jumbotron">
<div class="container">
<div class="col-sm-12">
<router-outlet></router-outlet>
</div>
</div>
</div>
And I declare the directive in app.module.ts:
#NgModule({
...
declarations: [
//** Root level components
AppComponent,
HomeComponent,
...
HighlightDirective,
],
And the feature modules with routes are declared in app-routing.module.ts:
const routes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: 'ml_payment', loadChildren: 'app/payment/payment.module#PaymentModule', canActivate: [AuthGuard] },
{ path: 'account', loadChildren: 'app/account/account.module#AccountModule', canActivate: [AuthGuard, AdminGuard] },
{ path: 'wip', component: WIPComponent },
{ path: '', component: HomeComponent, canActivate: [AuthGuard] },
{ path: '**', component: NotFoundComponent },
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
When the nested components are rendered, NG2 runtime do not render myHighlight into respective style tag of HTML. I just wonder if I had missed something or NG2 custom attribute directives do not work with RouterOutlet?
use routerLinkActive as [routerLinkActive]="['active']"
<nav>
<a routerLink="/" [routerLinkActive]="['active']"> </a>
</nav>
<div class="jumbotron">
<div class="container">
<div class="col-sm-12">
<router-outlet></router-outlet>
</div>
</div>
</div>
#ZZZ, did you put the directive in the "exports" section of the module where it was declared? Today I had a similar issue when I forgot to export a directive.
Good luck.

Categories