Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created October 10, 2017 11:31
Show Gist options
  • Save bennadel/5e6c0f3b469da0a67fa0e23b6cea3a0f to your computer and use it in GitHub Desktop.
Save bennadel/5e6c0f3b469da0a67fa0e23b6cea3a0f to your computer and use it in GitHub Desktop.
Closing Secondary Router-Outlet Views From Within The Named-Route View Components In Angular 4.4.4
// Import the core angular services.
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { RouterModule } from "@angular/router";
import { Routes } from "@angular/router";
// Import the application components and services.
import { AppComponent } from "./app.component";
import { ChatComponent } from "./chat.component";
import { LayoutAComponent } from "./layout-a.component";
import { LayoutBComponent } from "./layout-b.component";
import { LayoutWrapperComponent } from "./layout-wrapper.component";
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
var routes: Routes = [
{
// CAUTION: In order for the NAMED OUTLET child route to work (chat),
// its parent segment must contain a non-empty path. As such, we're
// using "main" for this wrapper component in order to ensure a non-
// empty path segment.
path: "main",
component: LayoutWrapperComponent,
children: [
{
path: "layout-a",
component: LayoutAComponent
},
{
path: "layout-b",
component: LayoutBComponent
},
{
outlet: "chat", // <--- Named outlet.
path: "open",
component: ChatComponent
}
]
}
// NOTE: We are OMITTING any not-found / catch-all REDIRECT as including it will
// partially mask the fact that some of our code is broken. Essentially, the redirect
// hides the broken URLs that get created.
// {
// path: "**",
// redirectTo: "/main/layout-a"
// }
];
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
@NgModule({
bootstrap: [
AppComponent
],
imports: [
BrowserModule,
RouterModule.forRoot(
routes,
{
// Tell the router to use the HashLocationStrategy.
useHash: true
}
)
],
declarations: [
AppComponent,
ChatComponent,
LayoutAComponent,
LayoutBComponent,
LayoutWrapperComponent
],
providers: [
// CAUTION: We don't need to specify the LocationStrategy because we are setting
// the "useHash" property in the Router module above.
// --
// {
// provide: LocationStrategy,
// useClass: HashLocationStrategy
// }
]
})
export class AppModule {
// ...
}
// Import the core angular services.
import { ActivatedRoute } from "@angular/router";
import { Component } from "@angular/core";
import { Router } from "@angular/router";
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
@Component({
selector: "chat",
styleUrls: [ "./chat.component.css" ],
template:
`
<h3>
Chat Widget
</h3>
<p>
<em>How can I help you?</em>
</p>
<h4>
Self-Closing Functionality
</h4>
<p>
<a [routerLink]="[ '../', { outlets: { chat: null } } ]">Close (via RouterLink)</a>
&mdash;
<strong>Broken</strong>
<em>(will appear to work, but will break on page-refresh)</em>.
</p>
<p>
<a (click)="closeChatViaMe()">Close (via .navigate() using self)</a>
&mdash;
<strong>Broken</strong>
<em>(will appear to work, but will break on page-refresh)</em>.
</p>
<p>
<a (click)="closeChatViaParent()">Close (via .navigate() using parent)</a>
</p>
`
})
export class ChatComponent {
private activatedRoute: ActivatedRoute;
private router: Router;
// I initialize the chat view component.
constructor( activatedRoute: ActivatedRoute, router: Router ) {
this.activatedRoute = activatedRoute;
this.router = router;
}
// ---
// PUBLIC METHODS.
// ---
// I attempt to close the chat by nullifying the secondary outlet using RELATIVE PATH
// navigation commands.
// --
// CAUTION: This is BROKEN. This DOES NOT WORK.
public closeChatViaMe() : void {
this.router.navigate(
[
"../",
{
outlets: {
chat: null
}
}
],
{
relativeTo: this.activatedRoute
}
);
}
// I attempt to close the chat by nullifying the secondary outlet using the PARENT'S
// ACTIVATED ROUTE.
public closeChatViaParent() : void {
this.router.navigate(
[
// NOTE: No relative-path navigation is required because we are accessing
// the parent's "activatedRoute" instance. As such, this will be executed
// as if we were doing this in the parent view component.
{
outlets: {
chat: null
}
}
],
{
relativeTo: this.activatedRoute.parent // <--- PARENT activated route.
}
);
}
}
[routerLink]="[ '../', { outlets: { chat: null } } ]
this.router.navigate(
[
"../",
{
outlets: {
chat: null
}
}
],
{
relativeTo: this.activatedRoute
}
);
this.router.navigate(
[
{
outlets: {
chat: null
}
}
],
{
relativeTo: this.activatedRoute.parent // <--- PARENT activated route.
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment