未加星标

Dreams Do Come True! Named Router Outlets in Angular 2

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二03 | 时间 2016 | 作者 红领巾 ] 0人收藏点击收藏
Intro

I am generally a positive person that endeavors to say nice things about people and frameworks. In the broadest sense, I love Angular, and it has been an amazing tool to build some really cool things. Angular 2 has exceeded my expectations in a lot of ways. But! There has always been some cognitive dissonance when it comes to the router in Angular 2. Its interesting history is no secret, and historically it has personally been a huge source of frustration for me. Having named outlets was something that I completely took for granted with UI-Router, and it drove me crazy that for the longest time, they just did not exist in Angular 2 and I wanted it! Well, dreams do come true! In the newest router, setting up named router outlets is a snap and in fact, they work pretty much exactly like unnamed router outlets. Please give Victor Savkin a hug next time you see him.

Speaking of Victor, I would like to thank him for his valuable input on this post.


Dreams Do Come True! Named Router Outlets in Angular 2

Our sample project allows us to see a list of speakers and their bios when you select on them. The speaker list and speaker bio components are mapped to two parallel named router outlets. Grab the sample project below and let’s go!

Sample Code Routing Module

The first thing that we need to do when setting up routes for our project is to define the routing table. We will start out with a basic home route that maps to the HomeComponent and then add another route to redirect the root path to our home route.

const routes: Routes = [ { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: 'home', component: HomeComponent } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], providers: [] }) export class RoutingModule { }

We will create another route that maps to our SpeakersComponent that has two children routes that we will use to introduce our named router outlets. Within the speakers route, we want to be able to display a list of speakers and the bio for the currently selected speaker. We accomplish this by adding in two child routes for the SpeakerListComponent and the BioComponent . Notice that both child routes follow the exact same structure as their parent route with the presence of a path and component property. The difference is that we have introduced an outlet property that we will use to map to a router-outlet in our template.

const routes: Routes = [ { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: 'home', component: HomeComponent }, { path: 'speakers', component: SpeakersComponent, children: [ { path: 'speakersList', component: SpeakersListComponent, outlet: 'list' }, { path: ':id', component: BioComponent, outlet: 'bio' } ] } ];

The path for the bio outlet is :id which we will use to send in a route param to load in a specific speaker.

Router Outlet

We are using an unnamed router outlet to load our home and speakers route as seen in the template below.

<div class="app-content"> <router-outlet></router-outlet> </div>

In our SpeakersComponent template, we are going to do essentially the same thing but instead of one router outlet, we will use two. And so that the router can delineate what component goes into what outlet, we will add a name attribute that matches up to our routing table. The route with the list output will be loaded into the outlet named list and so on.

<div class="columns"> <md-card> <router-outlet name="list"></router-outlet> </md-card> <md-card> <router-outlet name="bio"></router-outlet> </md-card> </div> Router Navigate

So far this has been a fairly straightforward exercise in the universe matching up with what we expect to see. Things get a little more interesting when we want to navigate to parallel named router outlets.

We can navigate to a route within our template using the routerLink directive and if the route is static then we can simply pass in the value to the route we want to navigate to. Because we do not need to pass in an dynamic values to the home route, adding routerLink=”home” to our button will suffice.

<button routerLink="home" md-button>Home</button>

When a route needs to generate a dynamic URL, we can pass it an array of values that get mapped to the URL. In our case, when we go to the speakers route, we want to map our list outlet to the speakerList path and our bio outlet to have a path of none which evaluates to a speaker id of none .

<button md-button [routerLink]="['/speakers', {outlets: {'list': ['speakersList'], 'bio': ['none']}}]"> Speakers </button>

This will generate a URL that looks like this http://localhost:4200/speakers/(list:speakersList//bio:none) and looks like this in the application.


Dreams Do Come True! Named Router Outlets in Angular 2

To navigate to a specific speaker, we will first add a click handler to our speakers list that calls showBio with the speaker.id .

<md-grid-list cols="3" gutterSize="4px"> <md-grid-tile *ngFor="let speaker of speakers" [style.background-image]="'url(assets/' + speaker.src + ')'" (click)="showBio(speaker.id)" <blockquote> </md-grid-tile> </md-grid-list>

And within our SpeakersListComponent , we will call router.navigate to update our bio outlet with a path based on the id parameter.

showBio(id) { this.router.navigate(['/speakers', {outlets: {'bio': [id]}}]); }

This will generate a URL that looks like this http://localhost:4200/speakers/(bio:1//list:speakersList) and looks like this in the application.


Dreams Do Come True! Named Router Outlets in Angular 2

For reference, you can see the entire SpeakersListComponent below.

import { Component, OnInit } from [email protected]/core'; import { Router } from [email protected]/router'; import { SpeakersService, Speaker } from '../shared'; @Component({ selector: 'app-speakers-list', templateUrl: './speakers-list.component.html', styleUrls: ['./speakers-list.component.css'] }) export class SpeakersListComponent implements OnInit { speakers: Speaker[] = []; constructor( private router: Router, private service: SpeakersService ) { } ngOnInit() { this.speakers = this.service.getSpeakers(); } showBio(id) { this.router.navigate(['/speakers', {outlets: {'bio': [id]}}]); } } Route Params

We are successfully generating a URL that communicates appropriate paths to our named router outlets but how do we use that information to do something useful? We can use ActivatedRoute to get the route parameters off of the active route to perform logic within our components. In our case, we want to use the id parameter to retrieve the correct speaker information so that we can display it in our template. We can use Activated to get all sorts of useful information about the route loaded within a component but in our case, we are most interested in the params property. The params property is an observable that we can subscribe to that will give us the parameters that have been scoped to the current route.

ngOnInit() { this.route.params.subscribe((params: {id: string}) => { this.currentSpeaker = this.service.getSpeakerByID(params.id); }); }

Within the subscribe method, we will use params.id to set this.currentSpeaker by calling this.service.getSpeakerByID .

For reference, you can see the entire BioComponent below.

import { Component, OnInit } from [email protected]/core'; import { ActivatedRoute } from [email protected]/router'; import { SpeakersService, Speaker } from '../shared'; @Component({ selector: 'app-bio', templateUrl: './bio.component.html', styleUrls: ['./bio.component.css'] }) export class BioComponent implements OnInit { currentSpeaker: Speaker; constructor( private route: ActivatedRoute, private service: SpeakersService ) { } ngOnInit() { this.route.params.subscribe((params: {id: string}) => { this.currentSpeaker = this.service.getSpeakerByID(params.id); }); } }

And just to wrap things up, within our BioComponent template, we are binding to currentSpeaker and using the safe navigation operator to keep our template stable when there isn’t a speaker selected.

<div *ngIf="!currentSpeaker"> <md-card-title>Please select a speaker</md-card-title> <md-card-subtitle>No speaker selected</md-card-subtitle> </div> <md-card-title>{{currentSpeaker?.name}}</md-card-title> <md-card-subtitle>{{currentSpeaker?.bio}}</md-card-subtitle>
Dreams Do Come True! Named Router Outlets in Angular 2
Review

And this is how we can have parallel, named router outlets within our Angular 2 application! I am so happy!

Let’s do a quick recap of what we covered.

A named outlet route works just like an unnamed outlet route with the difference being the addition of the outlet property on the route definition. We add a name property to the router-outlet element so the router knows where to load the component. When navigating to a route with named outlets, we need to add in an outlet object that defines the approprioate path for each outlet We can use Router.navigate to navigate to a route within our component. We can use ActivatedRoute to get route parameter values to perform logic within our component. Resources

A super awesome resource in general. Victor Savkin’s Blog

Well worth the $25 investment. Buy it now! Angular 2 Router Book by Victor Savkin

And just in case… Router API Documentation

Sample Code

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

分页:12
转载请注明
本文标题:Dreams Do Come True! Named Router Outlets in Angular 2
本站链接:http://www.codesec.net/view/481523.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(55)