Angular 2: Working with auxiliary routes

Datetime:2016-08-23 02:35:24          Topic: AngularJS           Share

In theprevious blog we learned that a child route is represented by a URL that consists of parent’s and child’s segments. Our small single page app had a single tag <router-outlet> where Angular would render the component configured for either parent or the child. The next subject to discuss how to configure and render sibling routes, i.e. the ones that are rendered in separate outlets at the same time. Let’s see some use cases:

* If a Gmail Web client displays the list of emails in your input mailbox and you decide to compose a new email, the new view will be displayed on the right side of the window and you’ll be able to switch between the inbox and the draft of the new email without closing either view.

* Imagine a dashboard-like SPA that has several dedicated areas (outlets) and each area could render more than one component (one at a time). The outlet A can display your stock portfolio either as a table or as a chart, while the outlet be shows either the latest news or the advertisement.

* Say we want to add to an SPA a chat area so the user can communicate with a customer service representative while keeping the current route active as well. Basically we want to add an independent chat route allowing the user to use both routes at the same time and switch from one route to another.

In Angular, you could implement any of these scenarios by having not only the primary outlet, but also the named auxiliary outlets, which are displayed at the same time with the primary one.

To separate rendering of components for a primary and an auxiliary routes you’ll need to add yet another tag(s) <router-outlet>, but this outlet has to have a name. For example the following code snippet defines a primary and a chat outlets:

<router-outlet></router-outlet>
<router-outlet name="chat"></router-outlet>

Let’s add a named route for a chat to our sample application.The snapshot below illustrates two routes opened at the same time after the user clicked on the Home and then on the Open Chat links. The left side shows the rendering of the Home component in the primary outlet, and the right side shows the Chat component rendered in a named outlet. Clicking on the Close Chat link will remove the the content of the named outlet.

We added an HTML <input> field to the HomeComponent, and a <textarea> to the ChatComponent so it’s easier to see which component has a focus when the user switches between the home and chat routes.

Note the parentheses in the URL of the auxiliary route http://localhost:8080/#home/(chat) . While a child route is separated from the parent using the forward slash, an auxiliary route is represented as a URL segment in parentheses. This URL tells us that home and chat are sibling routes.

The corresponding code that implements this sample is located in the file main_aux.ts and it’s shown next. We keep all the required components in the same file for simplicity. Both HomeComponent and ChatComponent have inlined styles to allocate them next to each other in the window. The HomeComponent is styled to get 70% of the available viewport width, and the ChatComponent will get the remaining 30%.

import {Component} from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {LocationStrategy, HashLocationStrategy} from '@angular/common';
import { Routes, RouterModule } from '@angular/router';

@Component({
    selector: 'home',
    template: `<div class="home">Home Component
               <input type="text" placeholder="Type something here"/> </div>`,
    styles: [`.home {background: red; padding: 15px 0 0 30px;  height: 80px; width:70%;
                    font-size: 30px; float:left; box-sizing:border-box;}`]})
export class HomeComponent {}

@Component({
    selector: 'chat',
    template: `<textarea placeholder="Chat with customer service"
                       class="chat"></textarea>`,
    styles: [`.chat {background: #eee; height: 80px;width:30%; font-size: 24px;
                     float:left; display:block; box-sizing:border-box;} `]})
export class ChatComponent {}

const routes: Routes = [
    {path: '',  redirectTo: 'home', pathMatch: 'full'},
    {path: 'home', component: HomeComponent}, // <1>
    {path: 'chat', component: ChatComponent, outlet:"aux"} // <2>
];

@Component({
    selector: 'app',
    template: `
        <a [routerLink]="['']">Home</a>
        <a [routerLink]="[{outlets: {primary: 'home', aux: 'chat'}}]">Open Chat</a> // <3>
        <a [routerLink]="[{outlets: {aux: null}}]">Close Chat</a> // <4>
        <br/>
        <router-outlet></router-outlet> // <5>
        <router-outlet name="aux"></router-outlet> // <6>
    `
})
class AppComponent {}

@NgModule({
    imports:      [ BrowserModule, RouterModule.forRoot(routes)],
    declarations: [ AppComponent, HomeComponent, ChatComponent],
    providers:[{provide: LocationStrategy, useClass: HashLocationStrategy}],
    bootstrap:    [ AppComponent ]
})
class AppModule { }

platformBrowserDynamic().bootstrapModule(AppModule);

1. Configure the route for Home component. Since no outlet is specified, the component will be rendered in the primary one.

2. Configure the route for Chat component to be rendered in the outlet named aux.

3. Render Home component in the primary outlet and Chat in the outlet called aux.

4. To remove the named outlet with its content give it a null value.

5. Declaring the primary outlet

6. Declaring an additional name outlet <router-outlet>. We named it aux.

If you want to navigate (or close) the named outlets programmatically use the method Router.navigate() as it was explained earlier in this chapter, e.g.:

navigate([{outlets: {aux: 'chat'}}]);

Hope this blog shed some additional lite on the very powerful Angular 2 router.

If you’re interested in learning Angular 2 in depth, enroll into one of our workshops. We’ll run the next public training online starting from September 11, 2016. I can also deliver this workshop privately for your organization (send an email to training@faratasystems.com).





About List