Merge remote-tracking branch 'angular.io/master' into merge-review-rex
# Conflicts: # public/docs/ts/latest/tutorial/toh-pt5.jade
This commit is contained in:
commit
7d5e2cf412
|
@ -7,7 +7,7 @@ if version && language
|
|||
else
|
||||
- var styleguide = "/docs/ts/latest/styleguide.html"
|
||||
|
||||
.main-footer
|
||||
div(class="main-footer" data-swiftype-index="false")
|
||||
nav.background-midnight.grid-fluid
|
||||
|
||||
.c3.main-footer-branding
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
- var language = current.path[1]
|
||||
- var version = ''
|
||||
- var section = ''
|
||||
|
||||
if current.path[2]
|
||||
- var version = current.path[2].replace(/\_+/gm, ".")
|
||||
|
||||
if current.path[3]
|
||||
- var section = current.path[3].toUpperCase()
|
||||
|
||||
|
||||
if language == 'js'
|
||||
if language == 'dart'
|
||||
|
||||
if title == "Angular"
|
||||
title #{title}
|
||||
else if section
|
||||
title #{title} - #{language} - #{section}
|
||||
else if language
|
||||
title #{title} - #{language}
|
||||
else
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- var language = current.path[1] || 'ts'
|
||||
- if (language !== 'ts' || language !== 'js' || language !== 'dart') { language = 'ts'; }
|
||||
|
||||
nav(class="main-nav l-pinned-top l-layer-5", scroll-y-offset-element)
|
||||
nav(data-swiftype-index="false" class="main-nav l-pinned-top l-layer-5", scroll-y-offset-element)
|
||||
h1 <a href="/" md-button>Angular <sup>by Google</sup></a>
|
||||
|
||||
button(class="main-nav-button main-nav-mobile-trigger l-right" aria-label="查看菜单" ng-click="appCtrl.toggleMainMenu($event)" md-button) 网站菜单 <span class="icon icon-arrow-drop-down"></span>
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
|
||||
[*.md]
|
||||
max_line_length = 0
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
# Indentation override
|
||||
#[lib/**.js]
|
||||
#[{package.json,.travis.yml}]
|
||||
#[**/**.js]
|
|
@ -1,7 +1,7 @@
|
|||
<!-- #docregion -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<head>
|
||||
<title>Dependency Injection</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
@ -19,7 +19,6 @@
|
|||
System.import('app').catch(function(err){ console.error(err); });
|
||||
</script>
|
||||
</head>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<my-app>Loading my-app ...</my-app>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// #docregion
|
||||
import {
|
||||
Component, Input,
|
||||
OnChanges, SimpleChange,
|
||||
OnChanges, SimpleChanges,
|
||||
} from '@angular/core';
|
||||
|
||||
import { LoggerService } from './logger.service';
|
||||
|
@ -22,7 +22,7 @@ export class MyCounterComponent implements OnChanges {
|
|||
@Input() counter: number;
|
||||
changeLog: string[] = [];
|
||||
|
||||
ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
|
||||
// Empty the changeLog whenever counter goes to zero
|
||||
// hint: this is a way to respond programmatically to external value changes.
|
||||
|
@ -36,7 +36,6 @@ export class MyCounterComponent implements OnChanges {
|
|||
let prev = JSON.stringify(chng.previousValue); // first time is {}; after is integer
|
||||
this.changeLog.push(`counter: currentValue = ${cur}, previousValue = ${prev}`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/***************************************/
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// #docregion
|
||||
import {
|
||||
Component, Input, OnChanges,
|
||||
SimpleChange, ViewChild
|
||||
SimpleChanges, ViewChild
|
||||
} from '@angular/core';
|
||||
|
||||
class Hero {
|
||||
|
@ -33,7 +33,7 @@ export class OnChangesComponent implements OnChanges {
|
|||
changeLog: string[] = [];
|
||||
|
||||
// #docregion ng-on-changes
|
||||
ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
for (let propName in changes) {
|
||||
let chng = changes[propName];
|
||||
let cur = JSON.stringify(chng.currentValue);
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
SimpleChange
|
||||
SimpleChanges
|
||||
} from '@angular/core';
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { LoggerService } from './logger.service';
|
||||
|
@ -51,7 +51,7 @@ export class PeekABooComponent extends PeekABoo implements
|
|||
}
|
||||
|
||||
// only called for/if there is an @input variable set by parent.
|
||||
ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
let changesMsgs: string[] = [];
|
||||
for (let propName in changes) {
|
||||
if (propName === 'name') {
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<!-- #docregion -->
|
||||
<h3>Top Heroes</h3>
|
||||
<div class="grid grid-pad">
|
||||
<div *ngFor="let hero of heroes" class="col-1-4">
|
||||
<div class="module hero">
|
||||
<h4>{{hero.name}}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,6 +1,12 @@
|
|||
/* #docregion */
|
||||
[class*='col-'] {
|
||||
float: left;
|
||||
text-decoration: none;
|
||||
padding-right: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
[class*='col-']:last-of-type {
|
||||
padding-right: 0;
|
||||
}
|
||||
*, *:after, *:before {
|
||||
-webkit-box-sizing: border-box;
|
||||
|
@ -10,12 +16,8 @@
|
|||
h3 {
|
||||
text-align: center; margin-bottom: 0;
|
||||
}
|
||||
[class*='col-'] {
|
||||
padding-right: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
[class*='col-']:last-of-type {
|
||||
padding-right: 0;
|
||||
h4 {
|
||||
position: relative;
|
||||
}
|
||||
.grid {
|
||||
margin: 0;
|
||||
|
@ -32,9 +34,6 @@ h3 {
|
|||
background-color: #607D8B;
|
||||
border-radius: 2px;
|
||||
}
|
||||
h4 {
|
||||
position: relative;
|
||||
}
|
||||
.module:hover {
|
||||
background-color: #EEE;
|
||||
cursor: pointer;
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
// #docregion imports
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:angular2/core.dart';
|
||||
// #docregion import-router
|
||||
import 'package:angular2/router.dart';
|
||||
// #enddocregion import-router
|
||||
|
||||
import 'hero.dart';
|
||||
import 'hero_service.dart';
|
||||
// #enddocregion imports
|
||||
|
||||
@Component(
|
||||
selector: 'my-dashboard',
|
||||
|
@ -24,24 +23,14 @@ class DashboardComponent implements OnInit {
|
|||
List<Hero> heroes;
|
||||
|
||||
// #docregion ctor
|
||||
final Router _router;
|
||||
final HeroService _heroService;
|
||||
|
||||
DashboardComponent(this._heroService, this._router);
|
||||
DashboardComponent(this._heroService);
|
||||
|
||||
// #enddocregion ctor
|
||||
|
||||
Future<Null> ngOnInit() async {
|
||||
heroes = (await _heroService.getHeroes()).skip(1).take(4).toList();
|
||||
}
|
||||
|
||||
// #docregion gotoDetail
|
||||
void gotoDetail(Hero hero) {
|
||||
var link = [
|
||||
'HeroDetail',
|
||||
{'id': hero.id.toString()}
|
||||
];
|
||||
_router.navigate(link);
|
||||
}
|
||||
// #enddocregion gotoDetail
|
||||
}
|
||||
// #enddocregion component
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<h3>Top Heroes</h3>
|
||||
<div class="grid grid-pad">
|
||||
<!-- #docregion click -->
|
||||
<div *ngFor="let hero of heroes" (click)="gotoDetail(hero)" class="col-1-4" >
|
||||
<!-- #enddocregion click -->
|
||||
<a *ngFor="let hero of heroes" [routerLink]="['/detail', hero.id]" class="col-1-4">
|
||||
<!-- #enddocregion click -->
|
||||
<div class="module hero">
|
||||
<h4>{{hero.name}}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
// #docplaster
|
||||
// #docregion imports
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:angular2/core.dart';
|
||||
|
||||
import 'hero.dart';
|
||||
import 'hero_service.dart';
|
||||
// #enddocregion imports
|
||||
|
||||
// #docregion component
|
||||
@Component(
|
||||
selector: 'my-dashboard',
|
||||
templateUrl: 'dashboard_component.html')
|
||||
class DashboardComponent implements OnInit {
|
||||
List<Hero> heroes;
|
||||
final HeroService _heroService;
|
||||
|
||||
DashboardComponent(this._heroService);
|
||||
|
||||
Future<Null> ngOnInit() async {
|
||||
heroes = (await _heroService.getHeroes()).skip(1).take(4).toList();
|
||||
}
|
||||
|
||||
gotoDetail(Hero hero) {/* not implemented yet */}
|
||||
}
|
|
@ -42,16 +42,16 @@ describe('Tutorial part 5', () => {
|
|||
beforeAll(() => browser.get(''));
|
||||
|
||||
function getPageElts() {
|
||||
let hrefElts = element.all(by.css('my-app a'));
|
||||
let navElts = element.all(by.css('my-app nav a'));
|
||||
|
||||
return {
|
||||
hrefs: hrefElts,
|
||||
navElts: navElts,
|
||||
|
||||
myDashboardHref: hrefElts.get(0),
|
||||
myDashboardHref: navElts.get(0),
|
||||
myDashboard: element(by.css('my-app my-dashboard')),
|
||||
topHeroes: element.all(by.css('my-app my-dashboard > div h4')),
|
||||
|
||||
myHeroesHref: hrefElts.get(1),
|
||||
myHeroesHref: navElts.get(1),
|
||||
myHeroes: element(by.css('my-app my-heroes')),
|
||||
allHeroes: element.all(by.css('my-app my-heroes li')),
|
||||
selectedHero: element(by.css('my-app li.selected')),
|
||||
|
@ -73,7 +73,7 @@ describe('Tutorial part 5', () => {
|
|||
|
||||
const expectedViewNames = ['Dashboard', 'Heroes'];
|
||||
it(`has views ${expectedViewNames}`, () => {
|
||||
let viewNames = getPageElts().hrefs.map((el: ElementFinder) => el.getText());
|
||||
let viewNames = getPageElts().navElts.map((el: ElementFinder) => el.getText());
|
||||
expect(viewNames).toEqual(expectedViewNames);
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<!-- #docregion -->
|
||||
<h3>Top Heroes</h3>
|
||||
<div class="grid grid-pad">
|
||||
<div *ngFor="let hero of heroes" class="col-1-4">
|
||||
<div class="module hero">
|
||||
<h4>{{hero.name}}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,27 +0,0 @@
|
|||
// #docplaster
|
||||
// #docregion imports
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { Hero } from './hero';
|
||||
import { HeroService } from './hero.service';
|
||||
// #enddocregion imports
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'my-dashboard',
|
||||
templateUrl: 'dashboard.component.html'
|
||||
})
|
||||
// #docregion component
|
||||
export class DashboardComponent implements OnInit {
|
||||
|
||||
heroes: Hero[] = [];
|
||||
|
||||
constructor(private heroService: HeroService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.heroService.getHeroes()
|
||||
.then(heroes => this.heroes = heroes.slice(1, 5));
|
||||
}
|
||||
|
||||
gotoDetail(hero: Hero): void { /* not implemented yet */}
|
||||
}
|
|
@ -1,22 +1,26 @@
|
|||
/* #docregion */
|
||||
[class*='col-'] {
|
||||
float: left;
|
||||
}
|
||||
*, *:after, *:before {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
h3 {
|
||||
text-align: center; margin-bottom: 0;
|
||||
}
|
||||
[class*='col-'] {
|
||||
padding-right: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
[class*='col-']:last-of-type {
|
||||
padding-right: 0;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
*, *:after, *:before {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
h3 {
|
||||
text-align: center; margin-bottom: 0;
|
||||
}
|
||||
h4 {
|
||||
position: relative;
|
||||
}
|
||||
.grid {
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -24,16 +28,13 @@ h3 {
|
|||
width: 25%;
|
||||
}
|
||||
.module {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #eee;
|
||||
max-height: 120px;
|
||||
min-width: 120px;
|
||||
background-color: #607D8B;
|
||||
border-radius: 2px;
|
||||
}
|
||||
h4 {
|
||||
position: relative;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #eee;
|
||||
max-height: 120px;
|
||||
min-width: 120px;
|
||||
background-color: #607D8B;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.module:hover {
|
||||
background-color: #EEE;
|
||||
|
@ -47,15 +48,15 @@ h4 {
|
|||
padding-right: 20px;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
.module {
|
||||
font-size: 10px;
|
||||
max-height: 75px; }
|
||||
.module {
|
||||
font-size: 10px;
|
||||
max-height: 75px; }
|
||||
}
|
||||
@media (max-width: 1024px) {
|
||||
.grid {
|
||||
margin: 0;
|
||||
}
|
||||
.module {
|
||||
min-width: 60px;
|
||||
}
|
||||
.grid {
|
||||
margin: 0;
|
||||
}
|
||||
.module {
|
||||
min-width: 60px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<h3>Top Heroes</h3>
|
||||
<div class="grid grid-pad">
|
||||
<!-- #docregion click -->
|
||||
<div *ngFor="let hero of heroes" (click)="gotoDetail(hero)" class="col-1-4">
|
||||
<a *ngFor="let hero of heroes" [routerLink]="['/detail', hero.id]" class="col-1-4">
|
||||
<!-- #enddocregion click -->
|
||||
<div class="module hero">
|
||||
<h4>{{hero.name}}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
// #docregion imports
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
// #docregion import-router
|
||||
import { Router } from '@angular/router';
|
||||
// #enddocregion import-router
|
||||
|
||||
import { Hero } from './hero';
|
||||
import { HeroService } from './hero.service';
|
||||
// #docregion metadata
|
||||
// #enddocregion imports
|
||||
|
||||
// #docregion metadata
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'my-dashboard',
|
||||
|
@ -19,27 +19,18 @@ import { HeroService } from './hero.service';
|
|||
// #docregion metadata
|
||||
})
|
||||
// #enddocregion metadata
|
||||
// #docregion component
|
||||
// #docregion class
|
||||
export class DashboardComponent implements OnInit {
|
||||
|
||||
heroes: Hero[] = [];
|
||||
|
||||
// #docregion ctor
|
||||
constructor(
|
||||
private router: Router,
|
||||
private heroService: HeroService) {
|
||||
}
|
||||
constructor(private heroService: HeroService) { }
|
||||
// #enddocregion ctor
|
||||
|
||||
ngOnInit(): void {
|
||||
this.heroService.getHeroes()
|
||||
.then(heroes => this.heroes = heroes.slice(1, 5));
|
||||
}
|
||||
|
||||
// #docregion gotoDetail
|
||||
gotoDetail(hero: Hero): void {
|
||||
let link = ['/detail', hero.id];
|
||||
this.router.navigate(link);
|
||||
}
|
||||
// #enddocregion gotoDetail
|
||||
}
|
||||
// #enddocregion class
|
||||
|
|
|
@ -40,8 +40,10 @@ export class HeroesComponent implements OnInit {
|
|||
this.selectedHero = hero;
|
||||
}
|
||||
|
||||
// #docregion gotoDetail
|
||||
gotoDetail(): void {
|
||||
this.router.navigate(['/detail', this.selectedHero.id]);
|
||||
}
|
||||
// #enddocregion gotoDetail
|
||||
// #docregion renaming
|
||||
}
|
||||
|
|
|
@ -1,22 +1,26 @@
|
|||
/* #docregion */
|
||||
[class*='col-'] {
|
||||
float: left;
|
||||
}
|
||||
*, *:after, *:before {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
h3 {
|
||||
text-align: center; margin-bottom: 0;
|
||||
}
|
||||
[class*='col-'] {
|
||||
padding-right: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
[class*='col-']:last-of-type {
|
||||
padding-right: 0;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
*, *:after, *:before {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
h3 {
|
||||
text-align: center; margin-bottom: 0;
|
||||
}
|
||||
h4 {
|
||||
position: relative;
|
||||
}
|
||||
.grid {
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -24,16 +28,13 @@ h3 {
|
|||
width: 25%;
|
||||
}
|
||||
.module {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #eee;
|
||||
max-height: 120px;
|
||||
min-width: 120px;
|
||||
background-color: #607D8B;
|
||||
border-radius: 2px;
|
||||
}
|
||||
h4 {
|
||||
position: relative;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #eee;
|
||||
max-height: 120px;
|
||||
min-width: 120px;
|
||||
background-color: #607D8B;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.module:hover {
|
||||
background-color: #EEE;
|
||||
|
@ -47,15 +48,15 @@ h4 {
|
|||
padding-right: 20px;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
.module {
|
||||
font-size: 10px;
|
||||
max-height: 75px; }
|
||||
.module {
|
||||
font-size: 10px;
|
||||
max-height: 75px; }
|
||||
}
|
||||
@media (max-width: 1024px) {
|
||||
.grid {
|
||||
margin: 0;
|
||||
}
|
||||
.module {
|
||||
min-width: 60px;
|
||||
}
|
||||
.grid {
|
||||
margin: 0;
|
||||
}
|
||||
.module {
|
||||
min-width: 60px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,20 +18,11 @@ import 'hero_search_component.dart';
|
|||
class DashboardComponent implements OnInit {
|
||||
List<Hero> heroes;
|
||||
|
||||
final Router _router;
|
||||
final HeroService _heroService;
|
||||
|
||||
DashboardComponent(this._heroService, this._router);
|
||||
DashboardComponent(this._heroService);
|
||||
|
||||
Future<Null> ngOnInit() async {
|
||||
heroes = (await _heroService.getHeroes()).skip(1).take(4).toList();
|
||||
}
|
||||
|
||||
void gotoDetail(Hero hero) {
|
||||
var link = [
|
||||
'HeroDetail',
|
||||
{'id': hero.id.toString()}
|
||||
];
|
||||
_router.navigate(link);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<!-- #docregion -->
|
||||
<h3>Top Heroes</h3>
|
||||
<div class="grid grid-pad">
|
||||
<div *ngFor="let hero of heroes" (click)="gotoDetail(hero)" class="col-1-4">
|
||||
<a *ngFor="let hero of heroes" [routerLink]="['/detail', hero.id]" class="col-1-4">
|
||||
<div class="module hero">
|
||||
<h4>{{hero.name}}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<hero-search></hero-search>
|
||||
|
|
|
@ -48,16 +48,16 @@ describe('Tutorial part 6', () => {
|
|||
beforeAll(() => browser.get(''));
|
||||
|
||||
function getPageElts() {
|
||||
let hrefElts = element.all(by.css('my-app a'));
|
||||
let navElts = element.all(by.css('my-app nav a'));
|
||||
|
||||
return {
|
||||
hrefs: hrefElts,
|
||||
navElts: navElts,
|
||||
|
||||
myDashboardHref: hrefElts.get(0),
|
||||
myDashboardHref: navElts.get(0),
|
||||
myDashboard: element(by.css('my-app my-dashboard')),
|
||||
topHeroes: element.all(by.css('my-app my-dashboard > div h4')),
|
||||
|
||||
myHeroesHref: hrefElts.get(1),
|
||||
myHeroesHref: navElts.get(1),
|
||||
myHeroes: element(by.css('my-app my-heroes')),
|
||||
allHeroes: element.all(by.css('my-app my-heroes li')),
|
||||
selectedHero: element(by.css('my-app li.selected')),
|
||||
|
@ -82,7 +82,7 @@ describe('Tutorial part 6', () => {
|
|||
|
||||
const expectedViewNames = ['Dashboard', 'Heroes'];
|
||||
it(`has views ${expectedViewNames}`, () => {
|
||||
let viewNames = getPageElts().hrefs.map((el: ElementFinder) => el.getText());
|
||||
let viewNames = getPageElts().navElts.map((el: ElementFinder) => el.getText());
|
||||
expect(viewNames).toEqual(expectedViewNames);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,23 +1,26 @@
|
|||
/* #docplaster */
|
||||
/* #docregion */
|
||||
[class*='col-'] {
|
||||
float: left;
|
||||
}
|
||||
*, *:after, *:before {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
h3 {
|
||||
text-align: center; margin-bottom: 0;
|
||||
}
|
||||
[class*='col-'] {
|
||||
padding-right: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
[class*='col-']:last-of-type {
|
||||
padding-right: 0;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
*, *:after, *:before {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
h3 {
|
||||
text-align: center; margin-bottom: 0;
|
||||
}
|
||||
h4 {
|
||||
position: relative;
|
||||
}
|
||||
.grid {
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -25,16 +28,13 @@ h3 {
|
|||
width: 25%;
|
||||
}
|
||||
.module {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #eee;
|
||||
max-height: 120px;
|
||||
min-width: 120px;
|
||||
background-color: #607D8B;
|
||||
border-radius: 2px;
|
||||
}
|
||||
h4 {
|
||||
position: relative;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #eee;
|
||||
max-height: 120px;
|
||||
min-width: 120px;
|
||||
background-color: #607D8B;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.module:hover {
|
||||
background-color: #EEE;
|
||||
|
@ -48,16 +48,15 @@ h4 {
|
|||
padding-right: 20px;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
.module {
|
||||
font-size: 10px;
|
||||
max-height: 75px; }
|
||||
.module {
|
||||
font-size: 10px;
|
||||
max-height: 75px; }
|
||||
}
|
||||
@media (max-width: 1024px) {
|
||||
.grid {
|
||||
margin: 0;
|
||||
}
|
||||
.module {
|
||||
min-width: 60px;
|
||||
}
|
||||
.grid {
|
||||
margin: 0;
|
||||
}
|
||||
.module {
|
||||
min-width: 60px;
|
||||
}
|
||||
}
|
||||
/* #enddocregion */
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<!-- #docregion -->
|
||||
<h3>Top Heroes</h3>
|
||||
<div class="grid grid-pad">
|
||||
<div *ngFor="let hero of heroes" (click)="gotoDetail(hero)" class="col-1-4">
|
||||
<a *ngFor="let hero of heroes" [routerLink]="['/detail', hero.id]" class="col-1-4">
|
||||
<div class="module hero">
|
||||
<h4>{{hero.name}}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<hero-search></hero-search>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// #docregion , search
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { Hero } from './hero';
|
||||
import { HeroService } from './hero.service';
|
||||
|
@ -15,18 +14,10 @@ import { HeroService } from './hero.service';
|
|||
export class DashboardComponent implements OnInit {
|
||||
heroes: Hero[] = [];
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private heroService: HeroService) {
|
||||
}
|
||||
constructor(private heroService: HeroService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.heroService.getHeroes()
|
||||
.then(heroes => this.heroes = heroes.slice(1, 5));
|
||||
}
|
||||
|
||||
gotoDetail(hero: Hero): void {
|
||||
let link = ['/detail', hero.id];
|
||||
this.router.navigate(link);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
- if (language !== 'ts' || language !== 'js' || language !== 'dart') { language = 'ts'; }
|
||||
|
||||
|
||||
nav(class="sidenav l-pinned-left l-layer-4 l-offset-nav" ng-class="appCtrl.showDocsNav ? 'is-visible' : ''")
|
||||
nav(class="sidenav l-pinned-left l-layer-4 l-offset-nav" data-swiftype-index="false" ng-class="appCtrl.showDocsNav ? 'is-visible' : ''")
|
||||
// SEARCH BAR
|
||||
header.sidenav-search.st-input-wrapper
|
||||
.st-input-inner
|
||||
|
|
|
@ -625,7 +625,7 @@ block redirect-vs-use-as-default
|
|||
|
||||
使用下列内容创建文件:
|
||||
|
||||
+makeExcerpt('app/dashboard.component.html')
|
||||
+makeExample('app/dashboard.component.1.html', '', 'app/dashboard.component.html')
|
||||
|
||||
:marked
|
||||
We use `*ngFor` once again to iterate over a list of heroes and display their names.
|
||||
|
@ -634,13 +634,6 @@ block redirect-vs-use-as-default
|
|||
我们又一次使用`*ngFor`来在英雄列表上迭代,并显示它们的名字。
|
||||
还添加了一个额外的`<div>`元素,来帮助稍后的美化工作。
|
||||
|
||||
There's a `(click)` binding to a `gotoDetail` method we haven't written yet and
|
||||
we're displaying a list of heroes that we don't have.
|
||||
We have work to do, starting with those heroes.
|
||||
|
||||
这里的`(click)`绑定到了`gotoDetail`方法,但我们还没实现它。而且我们也还没有要显示的英雄列表数据。
|
||||
我们有活儿干了,就从这些英雄列表开始吧。
|
||||
|
||||
### Share the *HeroService*
|
||||
|
||||
### 共享*HeroService*
|
||||
|
@ -668,7 +661,7 @@ block redirect-vs-use-as-default
|
|||
|
||||
打开<span ngio-ex>dashboard.component.ts</span>文件,并把必备的`import`语句加进去。
|
||||
|
||||
+makeExcerpt('app/dashboard.component.2.ts','imports')
|
||||
+makeExcerpt('app/dashboard.component.ts','imports')
|
||||
|
||||
:marked
|
||||
We need `OnInit` interface because we'll initialize the heroes in the `ngOnInit` method as we've done before.
|
||||
|
@ -681,7 +674,7 @@ block redirect-vs-use-as-default
|
|||
|
||||
我们现在就实现`DashboardComponent`类,像这样:
|
||||
|
||||
+makeExcerpt('app/dashboard.component.2.ts (class)', 'component')
|
||||
+makeExcerpt('app/dashboard.component.ts (class)', 'class')
|
||||
|
||||
:marked
|
||||
We've seen this kind of logic before in the `HeroesComponent`:
|
||||
|
@ -700,10 +693,9 @@ block redirect-vs-use-as-default
|
|||
|
||||
* 在Angular的`ngOnInit`生命周期钩子里面调用服务来获得英雄列表。
|
||||
|
||||
The noteworthy differences: we cherry-pick four heroes (2nd, 3rd, 4th, and 5th)
|
||||
and stub the `gotoDetail` method until we're ready to implement it.
|
||||
In this dashboard we cherry-pick four heroes (2nd, 3rd, 4th, and 5th) with the `Array.slice` method.
|
||||
|
||||
值得注意的区别是:我们提取了四个英雄(第2、3、4、5个),暂时隔离`gotoDetail`方法直到时机成熟。
|
||||
值得注意的区别是:我们用`Array.slice`方法提取了四个英雄(第2、3、4、5个)。
|
||||
|
||||
Refresh the browser and see four heroes in the new dashboard.
|
||||
|
||||
|
@ -974,8 +966,7 @@ block extract-id
|
|||
修改模板,添加这个按钮以提醒我们还要做更多的改进,
|
||||
并把模板移到独立的<span ngio-ex>hero-detail.component.html</span>文件中去。
|
||||
|
||||
|
||||
+makeExample('app/hero-detail.component.html')
|
||||
+makeExample('app/hero-detail.component.html')(format='.')
|
||||
|
||||
:marked
|
||||
We update the component metadata with a `moduleId` and a `templateUrl` pointing to the template file that we just created.
|
||||
|
@ -1004,49 +995,25 @@ block extract-id
|
|||
|
||||
当用户从仪表盘中选择了一位英雄时,本应用要导航到`HeroDetailComponent`以查看和编辑所选的英雄。
|
||||
|
||||
In the dashboard template we bound each hero's click event to the `gotoDetail` method, passing along the selected `hero` entity.
|
||||
Although the dashboard heroes are presented as button-like blocks, they should behave like anchor tags.
|
||||
When hovering over a hero block, the target URL should display in the browser status bar
|
||||
and the user should be able to copy the link or open the hero detail view in a new tab.
|
||||
|
||||
在仪表盘模板中,我们把每个英雄的click事件都绑定成`gotoDetail`方法,并且传入选中的这个`hero`实体对象。
|
||||
To achieve this effect, reopen the `dashboard.component.html` and replace the repeated `<div *ngFor...>` tags
|
||||
with `<a>` tags. The opening `<a>` tag looks like this:
|
||||
|
||||
+makeExample('toh-5/ts/app/dashboard.component.html','click', 'app/dashboard.component.html (click绑定)')(format=".")
|
||||
+makeExample('app/dashboard.component.html', 'click', 'app/dashboard.component.html (repeated <a> tag)')
|
||||
|
||||
:marked
|
||||
We stubbed the `gotoDetail` method when we rewrote the `DashboardComponent`.
|
||||
Now we give it a real implementation.
|
||||
Notice the `[routerLink]` binding.
|
||||
|
||||
当初我们重写`DashboardComponent`的时候,`gotoDetail`还是一个“桩方法”。
|
||||
现在,我们给它一个真正的实现。
|
||||
In the top level navigation in the [`AppComponent`
|
||||
template](#router-links) has router links set to fixed !{_pathVsName}s of the
|
||||
destination routes, "/dashboard" and "/heroes".
|
||||
|
||||
+makeExcerpt('app/dashboard.component.ts','gotoDetail')
|
||||
|
||||
:marked
|
||||
The `gotoDetail` method navigates in two steps:
|
||||
|
||||
`gotoDetail`方法分两步完成导航:
|
||||
|
||||
1. Set a route *link parameters !{_array}*
|
||||
|
||||
1. 生成路由的 *链接参数数组*
|
||||
|
||||
1. Pass the !{_array} to the router's navigate method
|
||||
|
||||
1. 把这个数组传给路由器的navigate方法。
|
||||
|
||||
For navigation, we wrote router links <span if-docs="dart">as *link
|
||||
parameters !{_array}s*</span> in the [`AppComponent`
|
||||
template](#router-links). Those link<span if-docs="dart"> parameters
|
||||
!{_array}</span>s had only one element, the !{_pathVsName} of the
|
||||
destination route.
|
||||
|
||||
我们为导航在[`AppComponent`的模板](#router-links)中生成导航链接<span if-docs="dart">as *link
|
||||
parameters !{_array}s*</span>。这些链接<span if-docs="dart"> parameters
|
||||
!{_array}</span>只有一个元素:目标路由的路径。
|
||||
|
||||
This link parameters !{_array} has two elements, the ***!{_pathVsName}*** of
|
||||
the destination route and a ***route parameter*** <span if-docs="dart">with
|
||||
an `id` field</span> set to the value of the selected hero's `id`.
|
||||
|
||||
这个链接参数数组有两个元素:目标路由的***路径(path)***和一个***路由参数对象***,其中包括一个`id`字段,它的取值是所选英雄的`id`。
|
||||
This time, we're binding to an expression containing a **link parameters !{_array}**.
|
||||
The !{_array} has two elements, the ***!{_pathVsName}*** of
|
||||
the destination route and a ***route parameter*** set to the value of the current hero's `id`.
|
||||
|
||||
The two !{_array} items align with the ***!{_pathVsName}*** and ***:id***
|
||||
token in the parameterized hero detail route definition we added to
|
||||
|
@ -1057,17 +1024,6 @@ block extract-id
|
|||
- var _file = _docsFor == 'dart' ? 'app/app.component.ts' : 'app/app.module.3.ts'
|
||||
+makeExcerpt(_file + ' (hero detail)', 'hero-detail')
|
||||
|
||||
:marked
|
||||
The `DashboardComponent` doesn't have the router yet. We obtain it in the usual way:
|
||||
import the `router` reference and inject it in the constructor (along with the `HeroService`):
|
||||
|
||||
`DashboardComponent`还没有路由器。我们使用常规的方式为它加上路由:
|
||||
`import` `router`对象的引用,并且把它注入到构造函数中(就像`HeroService`那样):
|
||||
|
||||
+makeExcerpt('app/dashboard.component.ts ()','import-router', '')
|
||||
|
||||
+makeExcerpt('app/dashboard.component.ts', 'ctor', '')
|
||||
|
||||
:marked
|
||||
Refresh the browser and select a hero from the dashboard; the app should navigate directly to that hero’s details.
|
||||
|
||||
|
@ -1181,7 +1137,7 @@ block extract-id
|
|||
|
||||
我们要做的是将详情组建移动到它自己的视图,并在用户决定编辑一个英雄时导航到它。
|
||||
|
||||
Delete the `<h1>` at the top (forgot about it during the `AppComponent`-to-`HeroesComponent` conversion).
|
||||
Delete the `<h1>` at the top (we forgot about it during the `AppComponent`-to-`HeroesComponent` conversion).
|
||||
|
||||
删除顶部的`<h1>`(在从`AppComponent`转到`HeroesComponent`期间可以先忘掉它)。
|
||||
|
||||
|
@ -1195,7 +1151,7 @@ block extract-id
|
|||
这里我们不再展示完整的`HeroDetailComponent`了。
|
||||
我们要在它自己的页面中显示英雄详情,并像我们在仪表盘中所做的那样路由到它。
|
||||
|
||||
But we'll throw in a small twist for variety.
|
||||
We'll throw in a small twist for variety.
|
||||
We are keeping the "master/detail" style but shrinking the detail to a "mini", read-only version.
|
||||
When the user selects a hero from the list, we *don't* go to the detail page.
|
||||
We show a *mini-detail* on *this* page instead and make the user click a button to navigate to the *full detail *page.
|
||||
|
@ -1296,25 +1252,25 @@ block heroes-component-cleanup
|
|||
+makeExcerpt('app/heroes.component.ts (revised metadata)', 'metadata')
|
||||
|
||||
:marked
|
||||
Now we can see what's going on as we update the component class along the same lines as the dashboard:
|
||||
### Update the _HeroesComponent_ class.
|
||||
|
||||
现在,我们一下就明白该怎么像仪表盘中那样更新组件类了:
|
||||
The `HeroesComponent` navigates to the `HeroesDetailComponent` in response to a button click.
|
||||
The button's _click_ event is bound to a `gotoDetail` method that navigates _imperatively_
|
||||
by telling the router where to go.
|
||||
|
||||
1. Import the `router`
|
||||
|
||||
1. 导入`router`
|
||||
This approach requires some changes to the component class:
|
||||
|
||||
1. Import the `router` from the Angular router library
|
||||
1. Inject the `router` in the constructor (along with the `HeroService`)
|
||||
1. Implement `gotoDetail` by calling the `router.navigate` method
|
||||
|
||||
1. 把`router`注入到构造函数中(就像`HeroService`那样)
|
||||
|
||||
1. Implement the `gotoDetail` method by calling the `router.navigate` method with a two-part hero-detail link parameters !{_array}.
|
||||
|
||||
1. 实现`gotoDetail`方法:以`HeroDetail`和*链接参数数组*为参数调用`router.navigate`方法。
|
||||
|
||||
Here's the revised component class:
|
||||
|
||||
下面是修改过的组件类:
|
||||
+makeExcerpt('app/heroes.component.ts', 'gotoDetail')
|
||||
:marked
|
||||
Note that we're passing a two-element **link parameters !{_array}**
|
||||
— a path and the route parameter — to
|
||||
the `router.navigate` method just as we did in the `[routerLink]` binding
|
||||
back in the `DashboardComponent`
|
||||
Here's the fully revised `HeroesComponent` class:
|
||||
|
||||
+makeExcerpt('app/heroes.component.ts', 'class')
|
||||
|
||||
|
|
|
@ -5,3 +5,4 @@
|
|||
/ts/latest/guide/style-guide.html # https://github.com/angular/angular.io/issues/2123
|
||||
/ts/latest/guide/upgrade.html # In a transient state until RC6 - @filipe.silva
|
||||
/[jt]s/.*/api/forms/index/NG_VALIDATORS-let.html # RC6 contains broken example tags
|
||||
/dart/latest/tutorial/toh-pt5.html
|
||||
|
|
Loading…
Reference in New Issue