Merge remote-tracking branch 'origin/master'

# Conflicts:
#	public/_data.json
#	public/_includes/_footer.jade
#	public/_includes/_hero-home.jade
#	public/_includes/_hero.jade
#	public/_includes/_main-nav.jade
#	public/_includes/_util-fns.jade
#	public/docs/_includes/_side-nav.jade
#	public/docs/ts/latest/_data.json
#	public/docs/ts/latest/cookbook/a1-a2-quick-reference.jade
#	public/docs/ts/latest/glossary.jade
#	public/docs/ts/latest/guide/_data.json
#	public/docs/ts/latest/guide/animations.jade
#	public/docs/ts/latest/guide/ngmodule.jade
#	public/docs/ts/latest/guide/router.jade
#	public/docs/ts/latest/guide/security.jade
#	public/docs/ts/latest/guide/server-communication.jade
#	public/docs/ts/latest/guide/style-guide.jade
#	public/docs/ts/latest/guide/testing.jade
#	public/docs/ts/latest/index.jade
#	public/docs/ts/latest/quickstart.jade
#	public/docs/ts/latest/testing/_data.json
#	public/docs/ts/latest/testing/application-under-test.jade
#	public/docs/ts/latest/testing/first-app-tests.jade
#	public/docs/ts/latest/testing/index.jade
#	public/docs/ts/latest/testing/jasmine-testing-101.jade
#	public/docs/ts/latest/testing/testing-an-angular-pipe.jade
#	public/index.jade
#	public/resources/css/main.scss
#	public/resources/css/module/_side-nav.scss
This commit is contained in:
Zhicheng Wang 2016-09-15 15:23:48 +08:00
commit 2417245114
433 changed files with 11422 additions and 13975 deletions

6
.firebaserc Normal file
View File

@ -0,0 +1,6 @@
{
"projects": {
"live": "angular-io",
"ngdocsdev": "ngdocsdev"
}
}

View File

@ -10,7 +10,7 @@ env:
- DBUS_SESSION_BUS_ADDRESS=/dev/null - DBUS_SESSION_BUS_ADDRESS=/dev/null
- DISPLAY=:99.0 - DISPLAY=:99.0
- CHROME_BIN=chromium-browser - CHROME_BIN=chromium-browser
- LATEST_RELEASE=2.0.0-rc.5 - LATEST_RELEASE=2.0.0
- TASK_FLAGS="--dgeni-log=warn" - TASK_FLAGS="--dgeni-log=warn"
matrix: matrix:
- TASK=lint - TASK=lint

View File

@ -91,15 +91,12 @@ var _excludeMatchers = _excludePatterns.map(function(excludePattern){
var _exampleBoilerplateFiles = [ var _exampleBoilerplateFiles = [
'.editorconfig', '.editorconfig',
'a2docs.css', 'a2docs.css',
'karma.conf.js',
'karma-test-shim.js',
'package.json', 'package.json',
'styles.css', 'styles.css',
'systemjs.config.js', 'systemjs.config.js',
'tsconfig.json', 'tsconfig.json',
'tslint.json', 'tslint.json',
'typings.json', 'typings.json'
'wallaby.js'
]; ];
var _exampleDartWebBoilerPlateFiles = ['a2docs.css', 'styles.css']; var _exampleDartWebBoilerPlateFiles = ['a2docs.css', 'styles.css'];
@ -636,7 +633,7 @@ gulp.task('build-dart-api-docs', ['_shred-api-examples', 'dartdoc'], function()
// Using the --build flag will use systemjs.config.plunker.build.js (for preview builds) // Using the --build flag will use systemjs.config.plunker.build.js (for preview builds)
gulp.task('build-plunkers', ['_copy-example-boilerplate'], function() { gulp.task('build-plunkers', ['_copy-example-boilerplate'], function() {
regularPlunker.buildPlunkers(EXAMPLES_PATH, LIVE_EXAMPLES_PATH, { errFn: gutil.log, build: argv.build }); regularPlunker.buildPlunkers(EXAMPLES_PATH, LIVE_EXAMPLES_PATH, { errFn: gutil.log, build: argv.build });
return embeddedPlunker.buildPlunkers(EXAMPLES_PATH, LIVE_EXAMPLES_PATH, { errFn: gutil.log, build: argv.build }); return embeddedPlunker.buildPlunkers(EXAMPLES_PATH, LIVE_EXAMPLES_PATH, { errFn: gutil.log, build: argv.build, targetSelf: argv.targetSelf });
}); });
gulp.task('build-dart-cheatsheet', [], function() { gulp.task('build-dart-cheatsheet', [], function() {
@ -1044,8 +1041,10 @@ function restoreApiHtml() {
const relApiDir = path.join('docs', lang, vers, 'api'); const relApiDir = path.join('docs', lang, vers, 'api');
const wwwApiSubdir = path.join('www', relApiDir); const wwwApiSubdir = path.join('www', relApiDir);
const backupApiSubdir = path.join('www-backup', relApiDir); const backupApiSubdir = path.join('www-backup', relApiDir);
gutil.log(`cp ${backupApiSubdir} ${wwwApiSubdir}`) if (fs.existsSync(backupApiSubdir) || argv.forceSkipApi !== true) {
fs.copySync(backupApiSubdir, wwwApiSubdir); gutil.log(`cp ${backupApiSubdir} ${wwwApiSubdir}`)
fs.copySync(backupApiSubdir, wwwApiSubdir);
}
}); });
} }

View File

@ -391,6 +391,7 @@
"bio": "Ward is an all-around developer with JavaScript, node, and .net chops. He's a frequent conference speaker and podcaster, trainer, Google Developer Expert for Angular, Microsoft MVP, and PluralSight author. He is also president of IdeaBlade, an enterprise software consulting firm and the makers of breeze.js. He would like to get more sleep and spend more time in the mountains.", "bio": "Ward is an all-around developer with JavaScript, node, and .net chops. He's a frequent conference speaker and podcaster, trainer, Google Developer Expert for Angular, Microsoft MVP, and PluralSight author. He is also president of IdeaBlade, an enterprise software consulting firm and the makers of breeze.js. He would like to get more sleep and spend more time in the mountains.",
"type": "Community" "type": "Community"
}, },
"johnpapa": { "johnpapa": {
"name": "John Papa", "name": "John Papa",
"picture": "/resources/images/bios/john-papa.jpg", "picture": "/resources/images/bios/john-papa.jpg",
@ -399,6 +400,7 @@
"bio": "John is a Google Developer Expert, Microsoft Regional Director and MVP, frequent author of courses for Pluralsight, a former technology Evangelist for Microsoft front end teams, and author of the popular Angular Style Guide. He can often be found speaking around the world at keynotes and sessions for many conferences. You can always find John at johnpapa.net or on twitter at @john_papa.", "bio": "John is a Google Developer Expert, Microsoft Regional Director and MVP, frequent author of courses for Pluralsight, a former technology Evangelist for Microsoft front end teams, and author of the popular Angular Style Guide. He can often be found speaking around the world at keynotes and sessions for many conferences. You can always find John at johnpapa.net or on twitter at @john_papa.",
"type": "Community" "type": "Community"
}, },
"martinstaffa": { "martinstaffa": {
"name": "Martin Staffa", "name": "Martin Staffa",
"picture": "/resources/images/bios/martinstaffa.jpg", "picture": "/resources/images/bios/martinstaffa.jpg",
@ -406,6 +408,7 @@
"bio": "Martin is an English major turned web developer who loves frontend stuff. He's been part of the Angular 1 team since 2014. If you can't find him roaming the Github issue queues, he's probably out with his camera somewhere.", "bio": "Martin is an English major turned web developer who loves frontend stuff. He's been part of the Angular 1 team since 2014. If you can't find him roaming the Github issue queues, he's probably out with his camera somewhere.",
"type": "Community" "type": "Community"
}, },
"topherfangio": { "topherfangio": {
"name": "Topher Fangio", "name": "Topher Fangio",
"picture": "/resources/images/bios/topherfangio.jpg", "picture": "/resources/images/bios/topherfangio.jpg",
@ -414,6 +417,7 @@
"bio": "Topher loves the web and how it empowers new forms of creativity, connection and business. He is currently a core contributor on the Angular Material project and sometimes blogs about random things.", "bio": "Topher loves the web and how it empowers new forms of creativity, connection and business. He is currently a core contributor on the Angular Material project and sometimes blogs about random things.",
"type": "Community" "type": "Community"
}, },
"filipesilva": { "filipesilva": {
"name": "Filipe Silva", "name": "Filipe Silva",
"picture": "/resources/images/bios/filipe-silva.jpg", "picture": "/resources/images/bios/filipe-silva.jpg",
@ -422,6 +426,7 @@
"bio": "Filipe is a passion-driven developer that always strives for the most elegant solution for each problem. He is currently an author for Angular.io, a core contributor for Angular-CLI and senior front end engineer at KonnectAgain. When not busy going through PRs, you can find him scouring reddit for new dinner recipes to cook or enjoying a craft beer in Dublin.", "bio": "Filipe is a passion-driven developer that always strives for the most elegant solution for each problem. He is currently an author for Angular.io, a core contributor for Angular-CLI and senior front end engineer at KonnectAgain. When not busy going through PRs, you can find him scouring reddit for new dinner recipes to cook or enjoying a craft beer in Dublin.",
"type": "Community" "type": "Community"
}, },
"teropa": { "teropa": {
"name": "Tero Parviainen", "name": "Tero Parviainen",
"picture": "/resources/images/bios/teropa.jpg", "picture": "/resources/images/bios/teropa.jpg",
@ -430,15 +435,17 @@
"bio": "Tero is an independent software developer and writer. He's been building web applications for his whole professional career, and has almost figured out how to do vertical centering in CSS.", "bio": "Tero is an independent software developer and writer. He's been building web applications for his whole professional career, and has almost figured out how to do vertical centering in CSS.",
"type": "Community" "type": "Community"
}, },
"deborah": {
"deborah": {
"name": "Deborah Kurata", "name": "Deborah Kurata",
"picture": "/resources/images/bios/deborah.jpg", "picture": "/resources/images/bios/deborah.jpg",
"twitter": "deborahkurata", "twitter": "deborahkurata",
"website": "http://blogs.msmvps.com/deborahk/", "website": "http://blogs.msmvps.com/deborahk/",
"bio": "Deborah is an independent software developer and author. She is author of several Pluralsight courses including: 'Angular 2: Getting Started'", "bio": "Deborah is an independent software developer and author. She is author of several Pluralsight courses including: 'Angular 2: Getting Started'",
"type": "Community" "type": "Community"
}, },
"jesusrodriguez": {
"jesusrodriguez": {
"name": "Jesús Rodríguez", "name": "Jesús Rodríguez",
"picture": "/resources/images/bios/jesus-rodriguez.jpg", "picture": "/resources/images/bios/jesus-rodriguez.jpg",
"twitter": "foxandxss", "twitter": "foxandxss",
@ -446,6 +453,7 @@
"bio": "Jesus is an open source lover, a book author and editor, and AngularUI lead developer. He is currently a core contributor to the UI Bootstrap project.", "bio": "Jesus is an open source lover, a book author and editor, and AngularUI lead developer. He is currently a core contributor to the UI Bootstrap project.",
"type": "Community" "type": "Community"
}, },
"torgeirhelgevold": { "torgeirhelgevold": {
"name": "Torgeir Helgevold", "name": "Torgeir Helgevold",
"picture": "/resources/images/bios/torgeirhelgevold.jpg", "picture": "/resources/images/bios/torgeirhelgevold.jpg",
@ -454,6 +462,7 @@
"bio": "Torgeir (Tor) is a front-end architect with a passion for JavaScript development. He is also an author for angular.io and an active tech blogger.", "bio": "Torgeir (Tor) is a front-end architect with a passion for JavaScript development. He is also an author for angular.io and an active tech blogger.",
"type": "Community" "type": "Community"
}, },
"fatimaremtullah": { "fatimaremtullah": {
"name": "Fatima Remtullah", "name": "Fatima Remtullah",
"picture": "/resources/images/bios/fatima.jpg", "picture": "/resources/images/bios/fatima.jpg",
@ -462,6 +471,7 @@
"bio": "Fatima is a Product Designer and Front-End Developer. When she is not nerding out she is probably eating an abundance of cookies.", "bio": "Fatima is a Product Designer and Front-End Developer. When she is not nerding out she is probably eating an abundance of cookies.",
"type": "Community" "type": "Community"
}, },
"eric": { "eric": {
"name": "Eric Jimenez", "name": "Eric Jimenez",
"picture": "/resources/images/bios/eric.jpg", "picture": "/resources/images/bios/eric.jpg",
@ -470,6 +480,7 @@
"bio": "Eric is a gamer, writer, and programmer.", "bio": "Eric is a gamer, writer, and programmer.",
"type": "Community" "type": "Community"
}, },
"mikeryan": { "mikeryan": {
"name": "Mike Ryan", "name": "Mike Ryan",
"picture": "/resources/images/bios/mikeryan.jpg", "picture": "/resources/images/bios/mikeryan.jpg",
@ -477,7 +488,8 @@
"website": "https://medium.com/@MikeRyan52", "website": "https://medium.com/@MikeRyan52",
"bio": "Mike Ryan is a Software Engineer at Synapse Wireless, working on solving challenging problems in the internet-of-things space. He is an advocate of reactive programming and a core contributor to the ngrx project.", "bio": "Mike Ryan is a Software Engineer at Synapse Wireless, working on solving challenging problems in the internet-of-things space. He is an advocate of reactive programming and a core contributor to the ngrx project.",
"type": "Community" "type": "Community"
}, },
"rex": { "rex": {
"name": "Rex Ye", "name": "Rex Ye",
"picture": "/resources/images/bios/rex.jpg", "picture": "/resources/images/bios/rex.jpg",
@ -485,6 +497,7 @@
"bio": "Rex is a full-stack developer. He maintains the Angular.cn website with his old pal Ralph Wang and he plays a key role in bridging between the Chinese Angular community and the world-wide community. He loves playing with flashy new technologies and enjoys the challenge of mastering new skills. His biggest challenge to date is figuring out how to sooth a crying 4-month-old baby.", "bio": "Rex is a full-stack developer. He maintains the Angular.cn website with his old pal Ralph Wang and he plays a key role in bridging between the Chinese Angular community and the world-wide community. He loves playing with flashy new technologies and enjoys the challenge of mastering new skills. His biggest challenge to date is figuring out how to sooth a crying 4-month-old baby.",
"type": "Community" "type": "Community"
}, },
"ralph": { "ralph": {
"name": "Ralph Wang", "name": "Ralph Wang",
"picture": "/resources/images/bios/ralph.jpg", "picture": "/resources/images/bios/ralph.jpg",
@ -492,6 +505,7 @@
"bio": "Ralph(Zhicheng Wang) is a senior consultant at ThoughWorks and also a GDE. He is a technology enthusiast and he is a passionate advocate of “Simplicity, Professionalism and Sharing”. In his eighteen years of R&D career, he worked as tester, R&D engineer, project manager, product manager and CTO. He is looking forward to the birth of his baby.", "bio": "Ralph(Zhicheng Wang) is a senior consultant at ThoughWorks and also a GDE. He is a technology enthusiast and he is a passionate advocate of “Simplicity, Professionalism and Sharing”. In his eighteen years of R&D career, he worked as tester, R&D engineer, project manager, product manager and CTO. He is looking forward to the birth of his baby.",
"type": "Community" "type": "Community"
}, },
"brandonroberts": { "brandonroberts": {
"name": "Brandon Roberts", "name": "Brandon Roberts",
"picture": "/resources/images/bios/brandonroberts.jpg", "picture": "/resources/images/bios/brandonroberts.jpg",
@ -500,12 +514,28 @@
"bio": "Brandon is a front-end developer for a game studio developing web applications for STEM-based learning games. He is also a natural born troubleshooter who helps solve Angular issues on Github and Gitter support channels, particularly dealing with routing. He is also a member of the Angular docs team.", "bio": "Brandon is a front-end developer for a game studio developing web applications for STEM-based learning games. He is also a natural born troubleshooter who helps solve Angular issues on Github and Gitter support channels, particularly dealing with routing. He is also a member of the Angular docs team.",
"type": "Community" "type": "Community"
}, },
"crisbeto": { "crisbeto": {
"name": "Kristiyan Kostadinov", "name": "Kristiyan Kostadinov",
"picture": "/resources/images/bios/crisbeto.jpg", "picture": "/resources/images/bios/crisbeto.jpg",
"website": "http://crisbeto.com/", "website": "http://crisbeto.com/",
"bio": "Kristiyan is a front-end developer, passionate open-source contributor and a core team member on Angular Material.", "bio": "Kristiyan is a front-end developer, passionate open-source contributor and a core team member on Angular Material.",
"type": "Community" "type": "Community"
},
"gkalpak": {
"name": "Georgios Kalpakas",
"picture": "/resources/images/bios/gkalpak.jpg",
"website": "https://github.com/gkalpak",
"bio": "George is a Software Engineer with a passion for chess, robotics and automating stuff. He has a strong need to know how things work (so if you already know, he'd love to have a talk with you). He has been a member of the AngularJS team since 2014. When not doing geeky stuff, he is probably trying to convince his wife and kids to apply programming principles in real life. (Or is it the other way around?)",
"type": "Community"
},
"kapunahelewong": {
"name": "Kapunahele Wong",
"picture": "/resources/images/bios/kapunahelewong.jpg",
"website": " https://github.com/kapunahelewong",
"bio": "Kapunahele is a front-end developer at Capital One. She loves just about anything to do with JavaScript, Angular and electronics. She enjoys mapping Hawaiian star names and constellations to Western ones and loves dancing native Hawaiian hula.",
"type": "Community"
} }
} }
} }

View File

@ -36,19 +36,19 @@
"cross-spawn": "^4.0.0", "cross-spawn": "^4.0.0",
"del": "^2.2.0", "del": "^2.2.0",
"dgeni": "^0.4.0", "dgeni": "^0.4.0",
"dgeni-packages": "^0.15.2", "dgeni-packages": "^0.16.0",
"diff": "^2.1.3", "diff": "^2.1.3",
"fs-extra": "^0.30.0", "fs-extra": "^0.30.0",
"globby": "^4.0.0", "globby": "^4.0.0",
"gulp": "^3.5.6", "gulp": "^3.5.6",
"gulp-env": "0.4.0", "gulp-env": "0.4.0",
"gulp-sass": "^2.3.2",
"gulp-less": "^3.1.0", "gulp-less": "^3.1.0",
"gulp-sass": "^2.3.2",
"gulp-task-listing": "^1.0.1", "gulp-task-listing": "^1.0.1",
"gulp-tslint": "^5.0.0", "gulp-tslint": "^5.0.0",
"gulp-util": "^3.0.6", "gulp-util": "^3.0.6",
"gulp-watch": "^4.3.4", "gulp-watch": "^4.3.4",
"harp": "0.21.0-pre.0", "harp": "git://github.com/filipesilva/harp.git#8da8d3497ddbfcbcbadd8be63e0fd731d7310cc4",
"html2jade": "^0.8.4", "html2jade": "^0.8.4",
"indent-string": "^2.1.0", "indent-string": "^2.1.0",
"jasmine-core": "^2.3.4", "jasmine-core": "^2.3.4",
@ -77,4 +77,4 @@
"jstransformer-marked": "^1.0.1" "jstransformer-marked": "^1.0.1"
}, },
"homepage": "http://angular.io/" "homepage": "http://angular.io/"
} }

View File

@ -8,7 +8,7 @@ else
- var styleguide = "/docs/ts/latest/styleguide.html" - var styleguide = "/docs/ts/latest/styleguide.html"
.main-footer .main-footer
nav.background-blue-grey-900.grid-fluid nav.background-midnight.grid-fluid
.c3.main-footer-branding .c3.main-footer-branding
.logo-inverse-large .logo-inverse-large
@ -70,13 +70,9 @@ else
ul.text-body ul.text-body
li <a href="https://angular.io/" target="_blank">English</a> li <a href="https://angular.io/" target="_blank">English</a>
footer(class="background-steel") footer(class="background-midnight")
p small.text-caption Powered by Google ©2010-2016. Code licensed under an <a href="/license" class="text-snow">MIT-style License</a>. Documentation licensed under <a class="text-snow" href="http://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>.
small.text-caption Powered by Google ©2010-2016. Code licensed under an <a href="/license" class="text-snow">MIT-style License</a>. Documentation licensed under <a class="text-snow" href="http://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>. a(aria-label="View Style Guide" href=styleguide title="Style Guide" class="styleguide-trigger text-snow")
p
small.text-caption.translated-cn Powered by Google ©2010-2016. 代码授权协议:<a href="/license" class="text-snow">MIT式协议</a>。 文档授权协议:<a class="text-snow" href="http://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>.
a(aria-label="View Style Guide" href=styleguide title="Style Guide" class="styleguide-trigger text-snow" md-button)
span.icon-favorite span.icon-favorite
a(aria-label="查看风格指南" href="/docs/ts/latest/styleguide.html" title="风格指南" class="styleguide-trigger text-snow translated-cn" md-button) a(aria-label="查看风格指南" href="/docs/ts/latest/styleguide.html" title="风格指南" class="styleguide-trigger text-snow translated-cn" md-button)
span.icon-favorite span.icon-favorite

View File

@ -1,14 +1,10 @@
header(class="background-sky") header(class="background-sky l-relative")
.hero.background-superhero-paper.is-large
h1.text-headline.hero-logo.translated-cn #{title}
p.translated-cn #{subtitle}
.hero-cta .hero.background-superhero-paper.is-large
a(href="/docs/ts/latest/quickstart.html" class="md-raised button button-large button-plain" md-button) 开始吧! img(class="hero-logo" src='/resources/images/logos/angular2/angular.svg')
h1.text-headline #{title}<br>#{subtitle}
.banner.banner-floaty a(href="/docs/ts/latest/quickstart.html" class="hero-cta md-raised button button-large button-plain" md-button) 开始吧!
.banner-ng-annoucement .announcement-bar.shadow-2.clearfix
div(class="banner-text" align="center") img(src="/resources/images/logos/angular2/angular.svg")
p 报名参加AngularConnect九月英国伦敦! p Angular 2.0最终发布啦!
div(class="banner-button") a(href="http://angularjs.blogspot.com/2016/09/angular2-final.html" target="_blank" class="button " + "md-button") 了解更多
a(href="http://angularconnect.com/?utm_source=angular&utm_medium=banner&utm_campaign=angular-banner" target="_blank" class="button md-button") 立刻注册

View File

@ -13,30 +13,27 @@
if current.path[4] && current.path[3] == 'api' if current.path[4] && current.path[3] == 'api'
- var textFormat = 'is-standard-case' - var textFormat = 'is-standard-case'
header(class="hero background-sky", style=fixHeroCss ? "height:auto" : "") header.hero.background-sky
div(class="inner-header") h1(class="hero-title #{textFormat}") #{headerTitle}
h1(class="hero-title text-display-1 translated-cn #{textFormat}") #{headerTitle}
if useBadges if useBadges
span(class="badges") if stability
if docType span(class="badge is-#{stability}").
span(class="status-badge"). #{capitalize(stability)}
#{renamer(capitalize(docType))} if security
if stability span(class="badge is-deprecated").
span(layout="row" class="status-badge") 安全风险
// badge circle is filled based on stability by matching a css selector in _hero.scss
span(class="status-circle status-#{stability}") //CLEAR FLOAT ELEMENTS
span Stability: #{capitalize(stability)} .clear
if security
span(class="status-badge security-risk-badge").
Security Risk
if subtitle if subtitle
h2.hero-subtitle.text-subhead #{subtitle} h2.hero-subtitle #{subtitle}
else if docType
h2.hero-subtitle #{renamer(capitalize(docType))}
if current.path[3] == 'api' && current.path[1] == 'dart'
block breadcrumbs
else if current.path[3] == 'api' && current.path[1] == 'dart'
block breadcrumbs
//- Show cross-language menu for top-level API page (but not entry pages)
if ! public.docs[current.path[1]][current.path[2]][current.path[3]][current.path[4]]
!= partial("_version-dropdown")
else if current.path[0] == "docs"
!= partial("_version-dropdown")

View File

@ -1,9 +1,8 @@
- var language = current.path[1] || 'ts' - var language = current.path[1] || 'ts'
- if (language !== 'ts' || language !== 'js' || language !== 'dart') { language = 'ts'; } - if (language !== 'ts' || language !== 'js' || language !== 'dart') { language = 'ts'; }
md-toolbar(class="main-nav background-regal l-pinned-top l-layer-5",scroll-y-offset-element) nav.main-nav.l-pinned-top.l-layer-5
nav h1 <a href="/" md-button>Angular <sup>by Google</sup></a>
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> 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>

View File

@ -84,14 +84,14 @@ mixin makeExample(_filePath, region, _title, stylePatterns)
- var format = attributes.format || defaultFormat; - var format = attributes.format || defaultFormat;
- if (attributes.format === '.') format = ''; - if (attributes.format === '.') format = '';
- var avoid = !!attributes.avoid; - var avoid = !!attributes.avoid;
- var avoidClass = avoid ? 'is-anti-pattern' : '';
if (title) div(class="code-example #{avoidClass}")
if (avoid) if (title)
.example-title.avoid AVOID: #{title} header
else h4 #{title}
.example-title #{title} code-example(language="#{language}" format="#{format}")
code-example(language="#{language}" format="#{format}") != styleString(frag, stylePatterns)
!= styleString(frag, stylePatterns)
//- Like makeExample, but: (1) doesn't show line numbers. (2) If region //- Like makeExample, but: (1) doesn't show line numbers. (2) If region
//- is omitted and title is 'foo (r)' then region is taken as 'r'. //- is omitted and title is 'foo (r)' then region is taken as 'r'.
@ -143,17 +143,18 @@ mixin makeJson( filePath, jsonConfig, title, stylePatterns)
- var json = unescapeHtml(frag); - var json = unescapeHtml(frag);
- var jsonExtract = extractJson(json, jsonConfig); - var jsonExtract = extractJson(json, jsonConfig);
- var avoid = !!attributes.avoid; - var avoid = !!attributes.avoid;
- var avoidClass = avoid ? 'is-anti-pattern' : '';
if (title) div(class="code-example #{avoidClass}")
if (avoid) if (title)
.example-title.avoid #{title} header
else h4 #{title}
.example-title #{title} code-example(language="#{language}" format="#{format}")
code-example(language="#{language}" format="#{format}") if (jsonExtract == 'ERROR')
if (jsonExtract == 'ERROR') err ERROR: Unable to extract json using config: "#{jsonConfig.toString()}"
err 错误: 无法通过配置"#{jsonConfig.toString()}"解析JSON err 错误: 无法通过配置"#{jsonConfig.toString()}"解析JSON
else else
!= styleString(jsonExtract, stylePatterns) != styleString(jsonExtract, stylePatterns)
if !jade2ng if !jade2ng
//- Open (and close) an explanation <div>. See QuickStart //- Open (and close) an explanation <div>. See QuickStart

View File

@ -35,11 +35,10 @@ else if current.path[3]
//- VERSION TREE CREATOR MIXIN //- VERSION TREE CREATOR MIXIN
mixin tree(directory, urlPrefix, name, latest) mixin tree(directory, urlPrefix, name, latest)
ul for val, semvar in directory
for val, semvar in directory if semvar !== '.git' && semvar !== '_data'
if semvar !== '.git' && semvar !== '_data' - var libVersion = (semvar == "latest") ? latest : semvar.replace(/\_+/gm, ".")
- var libVersion = (semvar == "latest") ? latest : semvar.replace(/\_+/gm, ".") li <a href="#{urlPrefix}/#{semvar}/#{page}" md-button>#{name} #{libVersion}</a>
li <a href="#{urlPrefix}/#{semvar}/#{page}" md-button>#{name} #{libVersion}</a>
//- BUTTON TITLE GENERATION //- BUTTON TITLE GENERATION
@ -69,7 +68,7 @@ nav.dropdown
div(class="overlay ng-hide" ng-click="appCtrl.toggleVersionMenu($event)" ng-show="appCtrl.showMenu") div(class="overlay ng-hide" ng-click="appCtrl.toggleVersionMenu($event)" ng-show="appCtrl.showMenu")
<!-- DROPDOWN MENU --> <!-- DROPDOWN MENU -->
div(class="dropdown-menu" ng-class="appCtrl.showMenu ? 'is-visible' : ''") ul(class="dropdown-menu" ng-class="appCtrl.showMenu ? 'is-visible' : ''")
mixin tree(public.docs.ts, "/docs/ts", "Angular 2 for TypeScript") mixin tree(public.docs.ts, "/docs/ts", "Angular 2 for TypeScript")
mixin tree(public.docs.js, "/docs/js", "Angular 2 for JavaScript") mixin tree(public.docs.js, "/docs/js", "Angular 2 for JavaScript")
//- Disable cross-language link for API entry pages (but keep for top API search page): //- Disable cross-language link for API entry pages (but keep for top API search page):

View File

@ -13,7 +13,9 @@
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"protractor": "^3.3.0", "protractor": "^3.3.0",
"typings": "^1.0.4" "typings": "^1.0.4",
"ts-node": "^1.3.0",
"typescript": "^2.0.2"
}, },
"repository": {} "repository": {}
} }

View File

@ -289,6 +289,19 @@ describe('Animation Tests', () => {
}); });
}); });
describe('callbacks', () => {
it('fires a callback on start and done', () => {
addActiveHero();
browser.manage().logs().get('browser').then((logs) => {
const animationMessages = logs.filter((log) => {
return log.message.indexOf('Animation') !== -1 ? true : false;
});
expect(animationMessages.length).toBeGreaterThan(0);
});
});
});
function addActiveHero(sleep?: number) { function addActiveHero(sleep?: number) {
sleep = sleep || 500; sleep = sleep || 500;
element(by.buttonText('Add active hero')).click(); element(by.buttonText('Add active hero')).click();

View File

@ -6,7 +6,8 @@ import {
style, style,
animate, animate,
transition, transition,
keyframes keyframes,
AnimationTransitionEvent
} from '@angular/core'; } from '@angular/core';
import { Heroes } from './hero.service'; import { Heroes } from './hero.service';
@ -14,14 +15,18 @@ import { Heroes } from './hero.service';
@Component({ @Component({
moduleId: module.id, moduleId: module.id,
selector: 'hero-list-multistep', selector: 'hero-list-multistep',
// #docregion template
template: ` template: `
<ul> <ul>
<li *ngFor="let hero of heroes" <li *ngFor="let hero of heroes"
(@flyInOut.start)="animationStarted($event)"
(@flyInOut.done)="animationDone($event)"
[@flyInOut]="'in'"> [@flyInOut]="'in'">
{{hero.name}} {{hero.name}}
</li> </li>
</ul> </ul>
`, `,
// #enddocregion template
styleUrls: ['hero-list.component.css'], styleUrls: ['hero-list.component.css'],
/* The element here always has the state "in" when it /* The element here always has the state "in" when it
* is present. We animate two transitions: From void * is present. We animate two transitions: From void
@ -54,4 +59,12 @@ import { Heroes } from './hero.service';
}) })
export class HeroListMultistepComponent { export class HeroListMultistepComponent {
@Input() heroes: Heroes; @Input() heroes: Heroes;
animationStarted(event: AnimationTransitionEvent) {
console.warn('Animation started: ', event);
}
animationDone(event: AnimationTransitionEvent) {
console.warn('Animation done: ', event);
}
} }

View File

@ -0,0 +1,25 @@
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
/* tslint:disable:quotemark */
describe('AOT Compilation', function () {
beforeAll(function () {
browser.get('');
});
it('should load page and click button', function (done) {
let headingSelector = element.all(by.css('h1')).get(0);
expect(headingSelector.getText()).toEqual('My First Angular 2 App');
expect(element.all(by.xpath('//div[text()="Magneta"]')).get(0).isPresent()).toBe(true);
expect(element.all(by.xpath('//div[text()="Bombasto"]')).get(0).isPresent()).toBe(true);
expect(element.all(by.xpath('//div[text()="Magma"]')).get(0).isPresent()).toBe(true);
expect(element.all(by.xpath('//div[text()="Tornado"]')).get(0).isPresent()).toBe(true);
let toggleButton = element.all(by.css('button')).get(0);
toggleButton.click().then(function() {
expect(headingSelector.isPresent()).toBe(false);
done();
});
});
});

View File

@ -0,0 +1,5 @@
**/*.ngfactory.ts
**/*.metadata.json
dist
!app/tsconfig.json
!rollup.js

View File

@ -0,0 +1,7 @@
<!-- #docregion -->
<button (click)="toggleHeading()">Toggle Heading</button>
<h1 *ngIf="showHeading">My First Angular 2 App</h1>
<h3>List of Heroes</h3>
<div *ngFor="let hero of heroes">{{hero}}</div>

View File

@ -0,0 +1,17 @@
// #docregion
// #docregion
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: 'app.component.html'
})
export class AppComponent {
showHeading = true;
heroes = ['Magneta', 'Bombasto', 'Magma', 'Tornado'];
toggleHeading() {
this.showHeading = !this.showHeading;
}
}

View File

@ -0,0 +1,12 @@
// #docregion
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }

View File

@ -0,0 +1,6 @@
// #docregion
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);

View File

@ -0,0 +1,6 @@
// #docregion
import { platformBrowser } from '@angular/platform-browser';
import { AppModuleNgFactory } from '../aot/app/app.module.ngfactory';
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);

View File

@ -0,0 +1,4 @@
{
"build": "build:aot",
"run": "http-server:e2e"
}

View File

@ -0,0 +1,23 @@
<!-- #docregion -->
<!DOCTYPE html>
<html>
<head>
<title>Ahead of time compilation</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
</head>
<!-- #docregion bundle -->
<body>
<my-app>Loading...</my-app>
</body>
<script src="dist/build.js"></script>
<!-- #enddocregion bundle -->
</html>

View File

@ -0,0 +1,25 @@
// #docregion
import rollup from 'rollup'
import nodeResolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs';
import uglify from 'rollup-plugin-uglify'
// #docregion config
export default {
entry: 'app/main.js',
dest: 'dist/build.js', // output a single application bundle
sourceMap: false,
format: 'iife',
plugins: [
nodeResolve({jsnext: true, module: true}),
// #docregion commonjs
commonjs({
include: 'node_modules/rxjs/**',
}),
// #enddocregion commonjs
// #docregion uglify
uglify()
// #enddocregion uglify
]
}
// #enddocregion config

View File

@ -1,7 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"module": "system", "module": "es2015",
"moduleResolution": "node", "moduleResolution": "node",
"sourceMap": true, "sourceMap": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
@ -9,5 +9,16 @@
"removeComments": false, "removeComments": false,
"noImplicitAny": true, "noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true "suppressImplicitAnyIndexErrors": true
} },
"files": [
"app/app.module.ts",
"app/main.ts",
"./typings/index.d.ts"
],
"angularCompilerOptions": {
"genDir": "aot",
"skipMetadataEmit" : true
}
} }

View File

@ -10,7 +10,7 @@
<script src="node_modules/zone.js/dist/zone.js"></script> <script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script> <script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/rxjs/bundles/Rx.umd.js"></script> <script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/@angular/core/bundles/core.umd.js"></script> <script src="node_modules/@angular/core/bundles/core.umd.js"></script>
<script src="node_modules/@angular/common/bundles/common.umd.js"></script> <script src="node_modules/@angular/common/bundles/common.umd.js"></script>
<script src="node_modules/@angular/compiler/bundles/compiler.umd.js"></script> <script src="node_modules/@angular/compiler/bundles/compiler.umd.js"></script>

View File

@ -1,64 +0,0 @@
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describeIf(browser.appIsTs || browser.appIsJs, 'Forms (Deprecated) Tests', function () {
beforeEach(function () {
browser.get('');
});
it('should display correct title', function () {
expect(element.all(by.css('h1')).get(0).getText()).toEqual('Hero Form');
});
it('should not display message before submit', function () {
let ele = element(by.css('h2'));
expect(ele.isDisplayed()).toBe(false);
});
it('should hide form after submit', function () {
let ele = element.all(by.css('h1')).get(0);
expect(ele.isDisplayed()).toBe(true);
let b = element.all(by.css('button[type=submit]')).get(0);
b.click().then(function() {
expect(ele.isDisplayed()).toBe(false);
});
});
it('should display message after submit', function () {
let b = element.all(by.css('button[type=submit]')).get(0);
b.click().then(function() {
expect(element(by.css('h2')).getText()).toContain('You submitted the following');
});
});
it('should hide form after submit', function () {
let alterEgoEle = element.all(by.css('input[ngcontrol=alterEgo]')).get(0);
expect(alterEgoEle.isDisplayed()).toBe(true);
let submitButtonEle = element.all(by.css('button[type=submit]')).get(0);
submitButtonEle.click().then(function() {
expect(alterEgoEle.isDisplayed()).toBe(false);
});
});
it('should reflect submitted data after submit', function () {
let test = 'testing 1 2 3';
let newValue: string;
let alterEgoEle = element.all(by.css('input[ngcontrol=alterEgo]')).get(0);
alterEgoEle.getAttribute('value').then(function(value) {
// alterEgoEle.sendKeys(test);
sendKeys(alterEgoEle, test);
newValue = value + test;
expect(alterEgoEle.getAttribute('value')).toEqual(newValue);
}).then(function() {
let b = element.all(by.css('button[type=submit]')).get(0);
return b.click();
}).then(function() {
let alterEgoTextEle = element(by.cssContainingText('div', 'Alter Ego'));
expect(alterEgoTextEle.isPresent()).toBe(true, 'cannot locate "Alter Ego" label');
let divEle = element(by.cssContainingText('div', newValue));
expect(divEle.isPresent()).toBe(true, 'cannot locate div with this text: ' + newValue);
});
});
});

View File

@ -1,12 +0,0 @@
// #docregion
(function(app) {
app.AppComponent = ng.core
.Component({
selector: 'my-app',
template: '<hero-form></hero-form>',
directives: [app.HeroFormComponent]
})
.Class({
constructor: function() {}
});
})(window.app || (window.app = {}));

View File

@ -1,195 +0,0 @@
<!-- #docplaster -->
<!-- #docregion final -->
<div class="container">
<!-- #docregion edit-div -->
<div [hidden]="submitted">
<h1>Hero Form</h1>
<!-- #docregion ngSubmit -->
<form (ngSubmit)="onSubmit()" #heroForm="ngForm">
<!-- #enddocregion ngSubmit -->
<!-- #enddocregion edit-div -->
<div class="form-group">
<label for="name">Name</label>
<!-- #docregion name-with-error-msg -->
<input type="text" class="form-control" required
[(ngModel)]="model.name"
ngControl="name" #name="ngForm" >
<div [hidden]="name.valid" class="alert alert-danger">
Name is required
</div>
<!-- #enddocregion name-with-error-msg -->
</div>
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control"
[(ngModel)]="model.alterEgo"
ngControl="alterEgo" >
</div>
<div class="form-group">
<label for="power">Hero Power</label>
<select class="form-control" required
[(ngModel)]="model.power"
ngControl="power" #power="ngForm" >
<option *ngFor="let p of powers" [value]="p">{{p}}</option>
</select>
<div [hidden]="power.valid" class="alert alert-danger">
Power is required
</div>
</div>
<!-- #docregion submit-button -->
<button type="submit" class="btn btn-default"
[disabled]="!heroForm.form.valid">Submit</button>
<!-- #enddocregion submit-button -->
</form>
</div>
<!-- #docregion submitted -->
<div [hidden]="!submitted">
<h2>You submitted the following:</h2>
<div class="row">
<div class="col-xs-3">Name</div>
<div class="col-xs-9 pull-left">{{ model.name }}</div>
</div>
<div class="row">
<div class="col-xs-3">Alter Ego</div>
<div class="col-xs-9 pull-left">{{ model.alterEgo }}</div>
</div>
<div class="row">
<div class="col-xs-3">Power</div>
<div class="col-xs-9 pull-left">{{ model.power }}</div>
</div>
<br>
<button class="btn btn-default" (click)="submitted=false">Edit</button>
</div>
<!-- #enddocregion submitted -->
</div>
<!-- #enddocregion final -->
<!-- ==================================================== -->
<div>
<form>
<!-- #docregion edit-div -->
<!-- ... all of the form ... -->
</form>
</div>
<!-- #enddocregion edit-div -->
<!-- ==================================================== -->
<hr>
<style>
.no-style .ng-valid {
border-left: 1px solid #CCC
}
.no-style .ng-invalid {
border-left: 1px solid #CCC
}
</style>
<div class="no-style" style="margin-left: 4px">
<!-- #docregion start -->
<div class="container">
<h1>Hero Form</h1>
<form>
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" required>
</div>
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control">
</div>
<!-- #enddocregion start -->
<!-- #docregion powers -->
<div class="form-group">
<label for="power">Hero Power</label>
<select class="form-control" required>
<option *ngFor="let p of powers" [value]="p">{{p}}</option>
</select>
</div>
<!-- #enddocregion powers -->
<!-- #docregion start -->
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
<!-- #enddocregion start -->
<!-- #enddocregion phase1-->
<!-- ==================================================== -->
<hr>
<!-- #docregion phase2-->
<div class="container">
<h1>Hero Form</h1>
<form>
<!-- #docregion ngModel-2-->
{{diagnostic()}}
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" required
[(ngModel)]="model.name" >
</div>
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control"
[(ngModel)]="model.alterEgo">
</div>
<div class="form-group">
<label for="power">Hero Power</label>
<select class="form-control" required
[(ngModel)]="model.power" >
<option *ngFor="let p of powers" [value]="p">{{p}}</option>
</select>
</div>
<!-- #enddocregion ngModel-2-->
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
<!-- #enddocregion phase2-->
<!-- EXTRA MATERIAL FOR DOCUMENTATION -->
<hr>
<!-- #docregion ngModel-1-->
<input type="text" class="form-control" required
[(ngModel)]="model.name" >
TODO: remove this: {{model.name}}
<!-- #enddocregion ngModel-1-->
<hr>
<!-- #docregion ngModel-3-->
<input type="text" class="form-control" required
[ngModel]="model.name"
(ngModelChange)="model.name = $event" >
TODO: remove this: {{model.name}}
<!-- #enddocregion ngModel-3-->
<hr>
<form>
<!-- #docregion ngControl-1 -->
<input type="text" class="form-control" required
[(ngModel)]="model.name"
ngControl="name" >
<!-- #enddocregion ngControl-1 -->
<hr>
<!-- #docregion ngControl-2 -->
<input type="text" class="form-control" required
[(ngModel)]="model.name"
ngControl="name" #spy >
<br>TODO: remove this: {{spy.className}}
<!-- #enddocregion ngControl-2 -->
</form>
<div>
<hr>
Name via form.controls = {{showFormControls(heroForm)}}
</div>
</div>

View File

@ -1,52 +0,0 @@
// #docplaster
// #docregion
// #docregion first, final
(function(app) {
app.HeroFormComponent = ng.core
.Component({
selector: 'hero-form',
templateUrl: 'app/hero-form.component.html'
})
.Class({
// #docregion submitted
constructor: function() {
// #enddocregion submitted
this.powers = ['Really Smart', 'Super Flexible',
'Super Hot', 'Weather Changer'
];
this.model = new app.Hero(18, 'Dr IQ', this.powers[0],
'Chuck Overstreet');
// #docregion submitted
this.submitted = false;
},
onSubmit: function() {
this.submitted = true;
},
// #enddocregion submitted
// #enddocregion final
// TODO: Remove this when we're done
diagnostic: function() {
return JSON.stringify(this.model);
},
// #enddocregion first
//////// DO NOT SHOW IN DOCS ////////
// Reveal in html:
// AlterEgo via form.controls = {{showFormControls(hf)}}
showFormControls: function(form) {
return form.controls['alterEgo'] &&
// #docregion form-controls
form.controls['name'].value; // Dr. IQ
// #enddocregion form-controls
},
/////////////////////////////
// #docregion first, final
});
// #enddocregion first, final
})(window.app || (window.app = {}));

View File

@ -1,11 +0,0 @@
// #docregion
(function(app) {
app.Hero = Hero;
function Hero(id, name, power, alterEgo) {
this.id = id;
this.name = name;
this.power = power;
this.alterEgo = alterEgo;
}
})(window.app || (window.app = {}));

View File

@ -1,6 +0,0 @@
// #docregion
(function(app) {
document.addEventListener('DOMContentLoaded', function() {
ng.platformBrowserDynamic.bootstrap(app.AppComponent);
});
})(window.app || (window.app = {}));

View File

@ -1,9 +0,0 @@
/* #docregion */
.ng-valid[required] {
border-left: 5px solid #42A948; /* green */
}
.ng-invalid {
border-left: 5px solid #a94442; /* red */
}
/* #enddocregion */

View File

@ -1,45 +0,0 @@
<!DOCTYPE html>
<!-- #docplaster -->
<!-- #docregion -->
<html>
<head>
<title>Hero Form</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- #docregion bootstrap -->
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">
<!-- #enddocregion bootstrap -->
<!-- #docregion styles -->
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="forms.css">
<!-- #enddocregion styles -->
<!-- IE required polyfill -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/rxjs/bundles/Rx.umd.js"></script>
<script src="node_modules/@angular/core/bundles/core.umd.js"></script>
<script src="node_modules/@angular/common/bundles/common.umd.js"></script>
<script src="node_modules/@angular/compiler/bundles/compiler.umd.js"></script>
<script src="node_modules/@angular/platform-browser/bundles/platform-browser.umd.js"></script>
<script src="node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js"></script>
<!-- #docregion scripts-hero, scripts-hero-form -->
<script src='app/hero.js'></script>
<!-- #enddocregion scripts-hero -->
<script src='app/hero-form.component.js'></script>
<!-- #enddocregion scripts-hero-form -->
<!-- #docregion scripts, scripts-hero, scripts-hero-form -->
<script src='app/app.component.js'></script>
<script src='app/main.js'></script>
<!-- #enddocregion scripts, scripts-hero, scripts-hero-form -->
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>

View File

@ -1,4 +0,0 @@
{
"description": "Forms",
"files":["app/**/*.js", "**/*.html", "**/*.css"]
}

View File

@ -1,10 +0,0 @@
// #docregion
import { Component } from '@angular/core';
import { HeroFormComponent } from './hero-form.component';
@Component({
selector: 'my-app',
template: '<hero-form></hero-form>',
directives: [HeroFormComponent]
})
export class AppComponent { }

View File

@ -1,208 +0,0 @@
<!-- #docplaster -->
<!-- #docregion final -->
<div class="container">
<!-- #docregion edit-div -->
<div [hidden]="submitted">
<h1>Hero Form</h1>
<!-- #docregion ngSubmit -->
<form *ngIf="active" (ngSubmit)="onSubmit()" #heroForm="ngForm">
<!-- #enddocregion ngSubmit -->
<!-- #enddocregion edit-div -->
<div class="form-group">
<!-- #docregion name-with-error-msg -->
<label for="name">Name</label>
<input type="text" class="form-control" required
[(ngModel)]="model.name"
ngControl="name" #name="ngForm" >
<!-- #docregion hidden-error-msg -->
<div [hidden]="name.valid || name.pristine" class="alert alert-danger">
<!-- #enddocregion hidden-error-msg -->
Name is required
</div>
<!-- #enddocregion name-with-error-msg -->
</div>
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control"
[(ngModel)]="model.alterEgo"
ngControl="alterEgo" >
</div>
<div class="form-group">
<label for="power">Hero Power</label>
<select class="form-control" required
[(ngModel)]="model.power"
ngControl="power" #power="ngForm" >
<option *ngFor="let p of powers" [value]="p">{{p}}</option>
</select>
<div [hidden]="power.valid || power.pristine" class="alert alert-danger">
Power is required
</div>
</div>
<!-- #docregion submit-button -->
<button type="submit" class="btn btn-default" [disabled]="!heroForm.form.valid">Submit</button>
<!-- #enddocregion submit-button -->
<!-- #docregion new-hero-button -->
<button type="button" class="btn btn-default" (click)="newHero()">New Hero</button>
<!-- #enddocregion new-hero-button -->
<!-- #enddocregion final -->
<!-- NOT SHOWN IN DOCS -->
<div>
<hr>
Name via form.controls = {{showFormControls(heroForm)}}
</div>
<!-- - -->
<!-- #docregion final -->
</form>
</div>
<!-- #docregion submitted -->
<div [hidden]="!submitted">
<h2>You submitted the following:</h2>
<div class="row">
<div class="col-xs-3">Name</div>
<div class="col-xs-9 pull-left">{{ model.name }}</div>
</div>
<div class="row">
<div class="col-xs-3">Alter Ego</div>
<div class="col-xs-9 pull-left">{{ model.alterEgo }}</div>
</div>
<div class="row">
<div class="col-xs-3">Power</div>
<div class="col-xs-9 pull-left">{{ model.power }}</div>
</div>
<br>
<button class="btn btn-default" (click)="submitted=false">Edit</button>
</div>
<!-- #enddocregion submitted -->
</div>
<!-- #enddocregion final -->
<!-- ==================================================== -->
<div>
<form>
<!-- #docregion edit-div -->
<!-- ... all of the form ... -->
</form>
</div>
<!-- #enddocregion edit-div -->
<!-- ==================================================== -->
<hr>
<style>
.no-style .ng-valid {
border-left: 1px solid #CCC
}
.no-style .ng-invalid {
border-left: 1px solid #CCC
}
</style>
<div class="no-style" style="margin-left: 4px">
<!-- #docregion start -->
<div class="container">
<h1>Hero Form</h1>
<form>
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" required>
</div>
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control">
</div>
<!-- #enddocregion start -->
<!-- #docregion powers -->
<div class="form-group">
<label for="power">Hero Power</label>
<select class="form-control" required>
<option *ngFor="let p of powers" [value]="p">{{p}}</option>
</select>
</div>
<!-- #enddocregion powers -->
<!-- #docregion start -->
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
<!-- #enddocregion start -->
<!-- #enddocregion phase1-->
<!-- ==================================================== -->
<hr>
<!-- #docregion phase2-->
<div class="container">
<h1>Hero Form</h1>
<form>
<!-- #docregion ngModel-2-->
{{diagnostic}}
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" required
[(ngModel)]="model.name" >
</div>
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control"
[(ngModel)]="model.alterEgo">
</div>
<div class="form-group">
<label for="power">Hero Power</label>
<select class="form-control" required
[(ngModel)]="model.power" >
<option *ngFor="let p of powers" [value]="p">{{p}}</option>
</select>
</div>
<!-- #enddocregion ngModel-2-->
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
<!-- #enddocregion phase2-->
<!-- EXTRA MATERIAL FOR DOCUMENTATION -->
<hr>
<!-- #docregion ngModel-1-->
<input type="text" class="form-control" required
[(ngModel)]="model.name" >
TODO: remove this: {{model.name}}
<!-- #enddocregion ngModel-1-->
<hr>
<!-- #docregion ngModel-3-->
<input type="text" class="form-control" required
[ngModel]="model.name"
(ngModelChange)="model.name = $event" >
TODO: remove this: {{model.name}}
<!-- #enddocregion ngModel-3-->
<hr>
<!-- #docregion form-active -->
<form *ngIf="active">
<!-- #enddocregion form-active -->
<!-- #docregion ngControl-1 -->
<input type="text" class="form-control" required
[(ngModel)]="model.name"
ngControl="name" >
<!-- #enddocregion ngControl-1 -->
<hr>
<!-- #docregion ngControl-2 -->
<input type="text" class="form-control" required
[(ngModel)]="model.name"
ngControl="name" #spy >
<br>TODO: remove this: {{spy.className}}
<!-- #enddocregion ngControl-2 -->
</form>
</div>

View File

@ -1,66 +0,0 @@
// #docplaster
// #docregion
// #docregion first, final
import { Component } from '@angular/core';
import { NgForm } from '@angular/common';
import { Hero } from './hero';
@Component({
selector: 'hero-form',
templateUrl: 'app/hero-form.component.html'
})
export class HeroFormComponent {
powers = ['Really Smart', 'Super Flexible',
'Super Hot', 'Weather Changer'];
model = new Hero(18, 'Dr IQ', this.powers[0], 'Chuck Overstreet');
// #docregion submitted
submitted = false;
onSubmit() { this.submitted = true; }
// #enddocregion submitted
// #enddocregion final
// TODO: Remove this when we're done
get diagnostic() { return JSON.stringify(this.model); }
// #enddocregion first
// #docregion final
// Reset the form with a new hero AND restore 'pristine' class state
// by toggling 'active' flag which causes the form
// to be removed/re-added in a tick via NgIf
// TODO: Workaround until NgForm has a reset method (#6822)
// #docregion new-hero
active = true;
// #docregion new-hero-v1
newHero() {
this.model = new Hero(42, '', '');
// #enddocregion new-hero-v1
this.active = false;
setTimeout(() => this.active = true, 0);
// #docregion new-hero-v1
}
// #enddocregion new-hero-v1
// #enddocregion new-hero
// #enddocregion final
//////// NOT SHOWN IN DOCS ////////
// Reveal in html:
// Name via form.controls = {{showFormControls(heroForm)}}
showFormControls(form: NgForm) {
return form && form.controls['name'] &&
// #docregion form-controls
form.controls['name'].value; // Dr. IQ
// #enddocregion form-controls
}
/////////////////////////////
// #docregion first, final
}
// #enddocregion first, final

View File

@ -1,11 +0,0 @@
// #docregion
export class Hero {
constructor(
public id: number,
public name: string,
public power: string,
public alterEgo?: string
) { }
}

View File

@ -1,6 +0,0 @@
// #docregion
import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component';
bootstrap(AppComponent);

View File

@ -1,9 +0,0 @@
/* #docregion */
.ng-valid[required] {
border-left: 5px solid #42A948; /* green */
}
.ng-invalid {
border-left: 5px solid #a94442; /* red */
}
/* #enddocregion */

View File

@ -1,34 +0,0 @@
<!DOCTYPE html>
<!-- #docregion -->
<html>
<head>
<title>Hero Form</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- #docregion bootstrap -->
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">
<!-- #enddocregion bootstrap -->
<!-- #docregion styles -->
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="forms.css">
<!-- #enddocregion styles -->
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>

View File

@ -1,7 +0,0 @@
{
"description": "Forms-Deprecated",
"files":[
"!**/*.d.ts",
"!**/*.js"
]
}

View File

@ -20,7 +20,7 @@
<script src="node_modules/zone.js/dist/zone.js"></script> <script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script> <script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/rxjs/bundles/Rx.umd.js"></script> <script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/@angular/core/bundles/core.umd.js"></script> <script src="node_modules/@angular/core/bundles/core.umd.js"></script>
<script src="node_modules/@angular/common/bundles/common.umd.js"></script> <script src="node_modules/@angular/common/bundles/common.umd.js"></script>
<script src="node_modules/@angular/compiler/bundles/compiler.umd.js"></script> <script src="node_modules/@angular/compiler/bundles/compiler.umd.js"></script>

View File

@ -11,10 +11,10 @@
<!-- Polyfill(s) for older browsers --> <!-- Polyfill(s) for older browsers -->
<script src="https://unpkg.com/core-js/client/shim.min.js"></script> <script src="https://unpkg.com/core-js/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js@0.6.17"></script> <script src="https://unpkg.com/zone.js@0.6.23"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.3"></script> <script src="https://unpkg.com/reflect-metadata@0.1.3"></script>
<script src="https://unpkg.com/systemjs@0.19.27/dist/system.src.js"></script> <script src="https://unpkg.com/systemjs@0.19.27/dist/system.src.js"></script>
<script src="https://unpkg.com/typescript@1.8.10/lib/typescript.js"></script> <script src="https://unpkg.com/typescript@2.0.2/lib/typescript.js"></script>
<!-- 2. Configure SystemJS --> <!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script> <script src="systemjs.config.js"></script>

View File

@ -12,10 +12,10 @@
<!-- Polyfill(s) for older browsers --> <!-- Polyfill(s) for older browsers -->
<script src="https://unpkg.com/core-js/client/shim.min.js"></script> <script src="https://unpkg.com/core-js/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js@0.6.17"></script> <script src="https://unpkg.com/zone.js@0.6.23"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.3"></script> <script src="https://unpkg.com/reflect-metadata@0.1.3"></script>
<script src="https://unpkg.com/systemjs@0.19.27/dist/system.src.js"></script> <script src="https://unpkg.com/systemjs@0.19.27/dist/system.src.js"></script>
<script src="https://unpkg.com/typescript@1.8.10/lib/typescript.js"></script> <script src="https://unpkg.com/typescript@2.0.2/lib/typescript.js"></script>
<!-- 2. Configure SystemJS --> <!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script> <script src="systemjs.config.js"></script>

View File

@ -12,10 +12,10 @@
<!-- Polyfill(s) for older browsers --> <!-- Polyfill(s) for older browsers -->
<script src="https://unpkg.com/core-js/client/shim.min.js"></script> <script src="https://unpkg.com/core-js/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js@0.6.17"></script> <script src="https://unpkg.com/zone.js@0.6.23"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.3"></script> <script src="https://unpkg.com/reflect-metadata@0.1.3"></script>
<script src="https://unpkg.com/systemjs@0.19.27/dist/system.src.js"></script> <script src="https://unpkg.com/systemjs@0.19.27/dist/system.src.js"></script>
<script src="https://unpkg.com/typescript@1.8.10/lib/typescript.js"></script> <script src="https://unpkg.com/typescript@2.0.2/lib/typescript.js"></script>
<!-- 2. Configure SystemJS --> <!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script> <script src="systemjs.config.js"></script>

View File

@ -1,50 +0,0 @@
// /*global jasmine, __karma__, window*/
Error.stackTraceLimit = Infinity;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
__karma__.loaded = function () {
};
function isJsFile(path) {
return path.slice(-3) == '.js';
}
function isSpecFile(path) {
return /\.spec\.js$/.test(path);
}
function isBuiltFile(path) {
var builtPath = '/base/app/';
return isJsFile(path) && (path.substr(0, builtPath.length) == builtPath);
}
var allSpecFiles = Object.keys(window.__karma__.files)
.filter(isSpecFile)
.filter(isBuiltFile);
System.config({
baseURL: '/base',
packageWithIndex: true // sadly, we can't use umd packages (yet?)
});
System.import('systemjs.config.js')
.then(() => Promise.all([
System.import('@angular/core/testing'),
System.import('@angular/platform-browser-dynamic/testing')
]))
.then((providers) => {
var coreTesting = providers[0];
var browserTesting = providers[1];
coreTesting.TestBed.initTestEnvironment(
browserTesting.BrowserDynamicTestingModule,
browserTesting.platformBrowserDynamicTesting());
})
.then(function () {
// Finally, load all spec files.
// This will run the tests directly.
return Promise.all(
allSpecFiles.map(function (moduleName) {
return System.import(moduleName);
}));
})
.then(__karma__.start, __karma__.error);

View File

@ -19,33 +19,39 @@
"start:webpack": "webpack-dev-server --inline --progress --port 8080", "start:webpack": "webpack-dev-server --inline --progress --port 8080",
"test:webpack": "karma start karma.webpack.conf.js", "test:webpack": "karma start karma.webpack.conf.js",
"build:webpack": "rimraf dist && webpack --config config/webpack.prod.js --bail", "build:webpack": "rimraf dist && webpack --config config/webpack.prod.js --bail",
"build:cli": "ng build" "build:cli": "ng build",
"build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup.js"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@angular/common": "2.0.0-rc.6", "@angular/common": "2.0.0",
"@angular/compiler": "2.0.0-rc.6", "@angular/compiler": "2.0.0",
"@angular/compiler-cli": "0.6.0", "@angular/compiler-cli": "0.6.2",
"@angular/core": "2.0.0-rc.6", "@angular/core": "2.0.0",
"@angular/forms": "2.0.0-rc.6", "@angular/forms": "2.0.0",
"@angular/http": "2.0.0-rc.6", "@angular/http": "2.0.0",
"@angular/platform-browser": "2.0.0-rc.6", "@angular/platform-browser": "2.0.0",
"@angular/platform-browser-dynamic": "2.0.0-rc.6", "@angular/platform-browser-dynamic": "2.0.0",
"@angular/router": "3.0.0-rc.2", "@angular/platform-server": "2.0.0",
"@angular/upgrade": "2.0.0-rc.6", "@angular/router": "3.0.0",
"angular2-in-memory-web-api": "0.0.18", "@angular/upgrade": "2.0.0",
"angular2-in-memory-web-api": "0.0.20",
"bootstrap": "^3.3.6", "bootstrap": "^3.3.6",
"core-js": "^2.4.1", "core-js": "^2.4.1",
"reflect-metadata": "^0.1.3", "reflect-metadata": "^0.1.3",
"rxjs": "5.0.0-beta.11", "rollup": "^0.34.13",
"rollup-plugin-node-resolve": "^2.0.0",
"rollup-plugin-uglify": "^1.0.1",
"rxjs": "5.0.0-beta.12",
"systemjs": "0.19.27", "systemjs": "0.19.27",
"zone.js": "^0.6.17" "zone.js": "^0.6.23"
}, },
"devDependencies": { "devDependencies": {
"angular-cli": "^1.0.0-beta.5", "angular-cli": "^1.0.0-beta.5",
"angular2-template-loader": "^0.4.0", "angular2-template-loader": "^0.4.0",
"awesome-typescript-loader": "^2.2.4",
"canonical-path": "0.0.2", "canonical-path": "0.0.2",
"concurrently": "^2.2.0", "concurrently": "^2.2.0",
"css-loader": "^0.23.1", "css-loader": "^0.23.1",
@ -60,6 +66,7 @@
"karma-cli": "^1.0.1", "karma-cli": "^1.0.1",
"karma-htmlfile-reporter": "^0.3.4", "karma-htmlfile-reporter": "^0.3.4",
"karma-jasmine": "^1.0.2", "karma-jasmine": "^1.0.2",
"karma-jasmine-html-reporter": "^0.2.2",
"karma-phantomjs-launcher": "^1.0.2", "karma-phantomjs-launcher": "^1.0.2",
"karma-sourcemap-loader": "^0.3.7", "karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^1.8.0", "karma-webpack": "^1.8.0",
@ -70,11 +77,12 @@
"protractor": "^3.3.0", "protractor": "^3.3.0",
"raw-loader": "^0.5.1", "raw-loader": "^0.5.1",
"rimraf": "^2.5.2", "rimraf": "^2.5.2",
"rollup-plugin-commonjs": "^4.1.0",
"style-loader": "^0.13.1", "style-loader": "^0.13.1",
"ts-loader": "^0.8.2", "ts-loader": "^0.8.2",
"ts-node": "^0.7.3", "ts-node": "^1.3.0",
"tslint": "^3.15.1", "tslint": "^3.15.1",
"typescript": "^1.8.10", "typescript": "^2.0.2",
"typings": "^1.3.2", "typings": "^1.3.2",
"webpack": "^1.13.0", "webpack": "^1.13.0",
"webpack-dev-server": "^1.14.1", "webpack-dev-server": "^1.14.1",

View File

@ -16,7 +16,7 @@
<script src="node_modules/zone.js/dist/zone.js"></script> <script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script> <script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/rxjs/bundles/Rx.umd.js"></script> <script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/@angular/core/bundles/core.umd.js"></script> <script src="node_modules/@angular/core/bundles/core.umd.js"></script>
<script src="node_modules/@angular/common/bundles/common.umd.js"></script> <script src="node_modules/@angular/common/bundles/common.umd.js"></script>
<script src="node_modules/@angular/compiler/bundles/compiler.umd.js"></script> <script src="node_modules/@angular/compiler/bundles/compiler.umd.js"></script>

View File

@ -7,23 +7,22 @@
}, },
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@angular/common": "2.0.0-rc.6", "@angular/common": "2.0.0",
"@angular/compiler": "2.0.0-rc.6", "@angular/compiler": "2.0.0",
"@angular/core": "2.0.0-rc.6", "@angular/core": "2.0.0",
"@angular/forms": "2.0.0-rc.6", "@angular/forms": "2.0.0",
"@angular/http": "2.0.0-rc.6", "@angular/http": "2.0.0",
"@angular/platform-browser": "2.0.0-rc.6", "@angular/platform-browser": "2.0.0",
"@angular/platform-browser-dynamic": "2.0.0-rc.6", "@angular/platform-browser-dynamic": "2.0.0",
"@angular/router": "3.0.0-rc.2", "@angular/router": "3.0.0",
"@angular/router-deprecated": "2.0.0-rc.2", "@angular/upgrade": "2.0.0",
"@angular/upgrade": "2.0.0-rc.6",
"core-js": "^2.4.1", "core-js": "^2.4.1",
"reflect-metadata": "0.1.3", "reflect-metadata": "^0.1.3",
"rxjs": "5.0.0-beta.11", "rxjs": "5.0.0-beta.12",
"zone.js": "0.6.17", "zone.js": "^0.6.23",
"angular2-in-memory-web-api": "0.0.18", "angular2-in-memory-web-api": "0.0.20",
"bootstrap": "^3.3.6" "bootstrap": "^3.3.6"
}, },
"devDependencies": { "devDependencies": {

View File

@ -11,30 +11,29 @@
}, },
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@angular/common": "2.0.0-rc.6", "@angular/common": "2.0.0",
"@angular/compiler": "2.0.0-rc.6", "@angular/compiler": "2.0.0",
"@angular/compiler-cli": "0.6.0", "@angular/core": "2.0.0",
"@angular/core": "2.0.0-rc.6", "@angular/forms": "2.0.0",
"@angular/forms": "2.0.0-rc.6", "@angular/http": "2.0.0",
"@angular/http": "2.0.0-rc.6", "@angular/platform-browser": "2.0.0",
"@angular/platform-browser": "2.0.0-rc.6", "@angular/platform-browser-dynamic": "2.0.0",
"@angular/platform-browser-dynamic": "2.0.0-rc.6", "@angular/router": "3.0.0",
"@angular/router": "3.0.0-rc.2", "@angular/upgrade": "2.0.0",
"@angular/upgrade": "2.0.0-rc.6",
"core-js": "^2.4.1", "core-js": "^2.4.1",
"reflect-metadata": "^0.1.3", "reflect-metadata": "^0.1.3",
"rxjs": "5.0.0-beta.11", "rxjs": "5.0.0-beta.12",
"systemjs": "0.19.27", "systemjs": "0.19.27",
"zone.js": "^0.6.17", "zone.js": "^0.6.23",
"angular2-in-memory-web-api": "0.0.18", "angular2-in-memory-web-api": "0.0.20",
"bootstrap": "^3.3.6" "bootstrap": "^3.3.6"
}, },
"devDependencies": { "devDependencies": {
"concurrently": "^2.2.0", "concurrently": "^2.2.0",
"lite-server": "^2.2.2", "lite-server": "^2.2.2",
"typescript": "^1.8.10", "typescript": "^2.0.2",
"typings":"^1.3.2" "typings":"^1.3.2"
} }
} }

View File

@ -2,6 +2,6 @@
"globalDependencies": { "globalDependencies": {
"core-js": "registry:dt/core-js#0.0.0+20160725163759", "core-js": "registry:dt/core-js#0.0.0+20160725163759",
"jasmine": "registry:dt/jasmine#2.2.0+20160621224255", "jasmine": "registry:dt/jasmine#2.2.0+20160621224255",
"node": "registry:dt/node#6.0.0+20160831021119" "node": "registry:dt/node#6.0.0+20160909174046"
} }
} }

View File

@ -1,127 +0,0 @@
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Router', function () {
beforeAll(function () {
browser.get('');
});
function getPageStruct() {
let hrefEles = element.all(by.css('my-app a'));
return {
hrefs: hrefEles,
routerParent: element(by.css('my-app > undefined')),
routerTitle: element(by.css('my-app > undefined > h2')),
crisisHref: hrefEles.get(0),
crisisList: element.all(by.css('my-app > undefined > undefined li')),
crisisDetail: element(by.css('my-app > undefined > undefined > div')),
crisisDetailTitle: element(by.css('my-app > undefined > undefined > div > h3')),
heroesHref: hrefEles.get(1),
heroesList: element.all(by.css('my-app > undefined li')),
heroDetail: element(by.css('my-app > undefined > div')),
heroDetailTitle: element(by.css('my-app > undefined > div > h3')),
};
}
it('should be able to see the start screen', function () {
let page = getPageStruct();
expect(page.hrefs.count()).toEqual(2, 'should be two dashboard choices');
expect(page.crisisHref.getText()).toEqual('Crisis Center');
expect(page.heroesHref.getText()).toEqual('Heroes');
});
it('should be able to see crises center items', function () {
let page = getPageStruct();
expect(page.crisisList.count()).toBe(4, 'should be 4 crisis center entries at start');
});
it('should be able to see hero items', function () {
let page = getPageStruct();
page.heroesHref.click().then(function() {
expect(page.routerTitle.getText()).toContain('HEROES');
expect(page.heroesList.count()).toBe(6, 'should be 6 heroes');
});
});
it('should be able to toggle the views', function () {
let page = getPageStruct();
page.crisisHref.click().then(function() {
expect(page.crisisList.count()).toBe(4, 'should be 4 crisis center entries');
return page.heroesHref.click();
}).then(function() {
expect(page.heroesList.count()).toBe(6, 'should be 6 heroes');
});
});
it('should be able to edit and save details from the crisis center view', function () {
crisisCenterEdit(2, true);
});
it('should be able to edit and cancel details from the crisis center view', function () {
crisisCenterEdit(3, false);
});
it('should be able to edit and save details from the heroes view', function () {
let page = getPageStruct();
let heroEle: protractor.ElementFinder;
let heroText: string;
page.heroesHref.click().then(function() {
heroEle = page.heroesList.get(4);
return heroEle.getText();
}).then(function(text) {
expect(text.length).toBeGreaterThan(0, 'should have some text');
// remove leading id from text
heroText = text.substr(text.indexOf(' ')).trim();
return heroEle.click();
}).then(function() {
expect(page.heroesList.count()).toBe(0, 'should no longer see crisis center entries');
expect(page.heroDetail.isPresent()).toBe(true, 'should be able to see crisis detail');
expect(page.heroDetailTitle.getText()).toContain(heroText);
let inputEle = page.heroDetail.element(by.css('input'));
return sendKeys(inputEle, '-foo');
}).then(function() {
expect(page.heroDetailTitle.getText()).toContain(heroText + '-foo');
let buttonEle = page.heroDetail.element(by.css('button'));
return buttonEle.click();
}).then(function() {
expect(heroEle.getText()).toContain(heroText + '-foo');
});
});
function crisisCenterEdit(index: number, shouldSave: boolean) {
let page = getPageStruct();
let crisisEle: protractor.ElementFinder;
let crisisText: string;
page.crisisHref.click()
.then(function () {
crisisEle = page.crisisList.get(index);
return crisisEle.getText();
}).then(function (text) {
expect(text.length).toBeGreaterThan(0, 'should have some text');
// remove leading id from text
crisisText = text.substr(text.indexOf(' ')).trim();
return crisisEle.click();
}).then(function () {
expect(page.crisisList.count()).toBe(0, 'should no longer see crisis center entries');
expect(page.crisisDetail.isPresent()).toBe(true, 'should be able to see crisis detail');
expect(page.crisisDetailTitle.getText()).toContain(crisisText);
let inputEle = page.crisisDetail.element(by.css('input'));
return sendKeys(inputEle, '-foo');
}).then(function () {
expect(page.crisisDetailTitle.getText()).toContain(crisisText + '-foo');
let buttonEle = page.crisisDetail.element(by.cssContainingText('button', shouldSave ? 'Save' : 'Cancel'));
return buttonEle.click();
}).then(function () {
if (shouldSave) {
expect(crisisEle.getText()).toContain(crisisText + '-foo');
} else {
expect(crisisEle.getText()).not.toContain(crisisText + '-foo');
}
});
}
});

View File

@ -1,43 +0,0 @@
/* First version */
// #docplaster
// #docregion
import { Component } from '@angular/core';
// #docregion import-router
import { RouteConfig, ROUTER_DIRECTIVES } from '@angular/router-deprecated';
// #enddocregion import-router
import { CrisisListComponent } from './crisis-list.component';
import { HeroListComponent } from './hero-list.component';
@Component({
selector: 'my-app',
// #docregion template
template: `
<h1>Component Router (Deprecated)</h1>
<nav>
<a [routerLink]="['CrisisCenter']">Crisis Center</a>
<a [routerLink]="['Heroes']">Heroes</a>
</nav>
<router-outlet></router-outlet>
`,
// #enddocregion template
directives: [ROUTER_DIRECTIVES]
})
// #enddocregion
/*
// #docregion route-config
@Component({ ... })
// #enddocregion route-config
*/
// #docregion
// #docregion route-config
@RouteConfig([
// #docregion route-defs
{path: '/crisis-center', name: 'CrisisCenter', component: CrisisListComponent},
{path: '/heroes', name: 'Heroes', component: HeroListComponent}
// #enddocregion route-defs
])
export class AppComponent { }
// #enddocregion route-config
// #enddocregion

View File

@ -1,58 +0,0 @@
/* Second Heroes version */
// #docplaster
// #docregion
import { Component } from '@angular/core';
import { RouteConfig, ROUTER_DIRECTIVES } from '@angular/router-deprecated';
import { CrisisListComponent } from './crisis-list.component';
// #enddocregion
/*
// Apparent Milestone 2 imports
// #docregion
// #docregion hero-import
import { HeroListComponent } from './heroes/hero-list.component';
import { HeroDetailComponent } from './heroes/hero-detail.component';
import { HeroService } from './heroes/hero.service';
// #enddocregion hero-import
// #enddocregion
*/
// Actual Milestone 2 imports
import { HeroListComponent } from './heroes/hero-list.component.1';
import { HeroDetailComponent } from './heroes/hero-detail.component.1';
import { HeroService } from './heroes/hero.service';
// #docregion
@Component({
selector: 'my-app',
template: `
<h1>Component Router (Deprecated)</h1>
<nav>
<a [routerLink]="['CrisisCenter']">Crisis Center</a>
<a [routerLink]="['Heroes']">Heroes</a>
</nav>
<router-outlet></router-outlet>
`,
providers: [HeroService],
directives: [ROUTER_DIRECTIVES]
})
// #enddocregion
/*
// #docregion route-config
@Component({ ... })
// #enddocregion route-config
*/
// #docregion
// #docregion route-config
@RouteConfig([
// #docregion route-defs
{path: '/crisis-center', name: 'CrisisCenter', component: CrisisListComponent},
{path: '/heroes', name: 'Heroes', component: HeroListComponent},
// #docregion hero-detail-route
{path: '/hero/:id', name: 'HeroDetail', component: HeroDetailComponent}
// #enddocregion hero-detail-route
// #enddocregion route-defs
])
export class AppComponent { }
// #enddocregion route-config
// #enddocregion

View File

@ -1,52 +0,0 @@
// #docplaster
import { Component } from '@angular/core';
import { RouteConfig, ROUTER_DIRECTIVES } from '@angular/router-deprecated';
import { CrisisCenterComponent } from './crisis-center/crisis-center.component.1';
import { DialogService } from './dialog.service';
import { HeroService } from './heroes/hero.service';
@Component({
selector: 'my-app',
// #enddocregion
/* Typical link
// #docregion h-anchor
<a [routerLink]="['Heroes']">Heroes</a>
// #enddocregion h-anchor
*/
/* Incomplete Crisis Center link when CC lacks a default
// #docregion cc-anchor-fail
// The link now fails with a "non-terminal link" error
// #docregion cc-anchor-w-default
<a [routerLink]="['CrisisCenter']">Crisis Center</a>
// #enddocregion cc-anchor-w-default
// #enddocregion cc-anchor-fail
*/
/* Crisis Center link when CC lacks a default
// #docregion cc-anchor-no-default
<a [routerLink]="['CrisisCenter', 'CrisisList']">Crisis Center</a>
// #enddocregion cc-anchor-no-default
*/
/* Crisis Center Detail link
// #docregion Dragon-anchor
<a [routerLink]="['CrisisCenter', 'CrisisDetail', {id:1}]">Dragon Crisis</a>
// #enddocregion Dragon-anchor
*/
// #docregion template
template: `
<h1 class="title">Component Router (Deprecated)</h1>
<nav>
<a [routerLink]="['CrisisCenter', 'CrisisList']">Crisis Center</a>
<a [routerLink]="['CrisisCenter', 'CrisisDetail', {id:1}]">Dragon Crisis</a>
<a [routerLink]="['CrisisCenter', 'CrisisDetail', {id:2}]">Shark Crisis</a>
</nav>
<router-outlet></router-outlet>
`,
// #enddocregion template
providers: [DialogService, HeroService],
directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
{path: '/crisis-center/...', name: 'CrisisCenter', component: CrisisCenterComponent},
])
export class AppComponent { }

View File

@ -1,44 +0,0 @@
// #docplaster
// #docregion
import { Component } from '@angular/core';
import { RouteConfig, ROUTER_DIRECTIVES } from '@angular/router-deprecated';
import { CrisisCenterComponent } from './crisis-center/crisis-center.component';
import { HeroListComponent } from './heroes/hero-list.component';
import { HeroDetailComponent } from './heroes/hero-detail.component';
import { DialogService } from './dialog.service';
import { HeroService } from './heroes/hero.service';
@Component({
selector: 'my-app',
// #docregion template
template: `
<h1 class="title">Component Router (Deprecated)</h1>
<nav>
<a [routerLink]="['CrisisCenter']">Crisis Center</a>
<a [routerLink]="['Heroes']">Heroes</a>
</nav>
<router-outlet></router-outlet>
`,
// #enddocregion template
providers: [DialogService, HeroService],
directives: [ROUTER_DIRECTIVES]
})
// #docregion route-config
@RouteConfig([
// #docregion route-config-cc
{ // Crisis Center child route
path: '/crisis-center/...',
name: 'CrisisCenter',
component: CrisisCenterComponent,
useAsDefault: true
},
// #enddocregion route-config-cc
{path: '/heroes', name: 'Heroes', component: HeroListComponent},
{path: '/hero/:id', name: 'HeroDetail', component: HeroDetailComponent},
])
// #enddocregion route-config
export class AppComponent { }

View File

@ -1,28 +0,0 @@
import { Component } from '@angular/core';
import { RouteConfig, RouterOutlet } from '@angular/router-deprecated';
import { CrisisListComponent } from './crisis-list.component.1';
import { CrisisDetailComponent } from './crisis-detail.component.1';
import { CrisisService } from './crisis.service';
// #docregion minus-imports
@Component({
template: `
<h2>CRISIS CENTER</h2>
<router-outlet></router-outlet>
`,
directives: [RouterOutlet],
// #docregion providers
providers: [CrisisService]
// #enddocregion providers
})
// #docregion route-config
@RouteConfig([
// #docregion default-route
{path: '/', name: 'CrisisList', component: CrisisListComponent, useAsDefault: true},
// #enddocregion default-route
{path: '/:id', name: 'CrisisDetail', component: CrisisDetailComponent}
])
// #enddocregion route-config
export class CrisisCenterComponent { }
// #enddocregion minus-imports

View File

@ -1,22 +0,0 @@
// #docregion
import { Component } from '@angular/core';
import { RouteConfig, RouterOutlet } from '@angular/router-deprecated';
import { CrisisListComponent } from './crisis-list.component';
import { CrisisDetailComponent } from './crisis-detail.component';
import { CrisisService } from './crisis.service';
@Component({
template: `
<h2>CRISIS CENTER</h2>
<router-outlet></router-outlet>
`,
directives: [RouterOutlet],
providers: [CrisisService]
})
@RouteConfig([
{path: '/', name: 'CrisisList', component: CrisisListComponent, useAsDefault: true},
{path: '/:id', name: 'CrisisDetail', component: CrisisDetailComponent}
])
export class CrisisCenterComponent { }
// #enddocregion

View File

@ -1,95 +0,0 @@
// #docplaster
// #docregion
import { Component, OnInit } from '@angular/core';
import { RouteParams, Router } from '@angular/router-deprecated';
// #docregion routerCanDeactivate
import { CanDeactivate, ComponentInstruction } from '@angular/router-deprecated';
import { DialogService } from '../dialog.service';
// #enddocregion routerCanDeactivate
import { Crisis, CrisisService } from './crisis.service';
@Component({
// #docregion template
template: `
<div *ngIf="crisis">
<h3>"{{editName}}"</h3>
<div>
<label>Id: </label>{{crisis.id}}</div>
<div>
<label>Name: </label>
<input [(ngModel)]="editName" placeholder="name"/>
</div>
<p>
<button (click)="save()">Save</button>
<button (click)="cancel()">Cancel</button>
</p>
</div>
`,
// #enddocregion template
styles: ['input {width: 20em}']
})
// #docregion routerCanDeactivate, cancel-save
export class CrisisDetailComponent implements OnInit, CanDeactivate {
crisis: Crisis;
editName: string;
// #enddocregion routerCanDeactivate, cancel-save
constructor(
private service: CrisisService,
private router: Router,
private routeParams: RouteParams,
private dialog: DialogService
) { }
// #docregion ngOnInit
ngOnInit() {
let id = +this.routeParams.get('id');
this.service.getCrisis(id).then(crisis => {
if (crisis) {
this.editName = crisis.name;
this.crisis = crisis;
} else { // id not found
this.gotoCrises();
}
});
}
// #enddocregion ngOnInit
// #docregion routerCanDeactivate
routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction): any {
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged.
if (!this.crisis || this.crisis.name === this.editName) {
return true;
}
// Otherwise ask the user with the dialog service and return its
// promise which resolves to true or false when the user decides
return this.dialog.confirm('Discard changes?');
}
// #enddocregion routerCanDeactivate
// #docregion cancel-save
cancel() {
this.editName = this.crisis.name;
this.gotoCrises();
}
save() {
this.crisis.name = this.editName;
this.gotoCrises();
}
// #enddocregion cancel-save
// #docregion gotoCrises
gotoCrises() {
// Like <a [routerLink]="['CrisisList']">Crisis Center</a
this.router.navigate(['CrisisList']);
}
// #enddocregion gotoCrises
// #docregion routerCanDeactivate, cancel-save
}
// #enddocregion routerCanDeactivate, cancel-save
// #enddocregion

View File

@ -1,85 +0,0 @@
// #docplaster
// #docregion
import { Component, OnInit } from '@angular/core';
import { RouteParams, Router } from '@angular/router-deprecated';
import { CanDeactivate, ComponentInstruction } from '@angular/router-deprecated';
import { Crisis, CrisisService } from './crisis.service';
import { DialogService } from '../dialog.service';
@Component({
template: `
<div *ngIf="crisis">
<h3>"{{editName}}"</h3>
<div>
<label>Id: </label>{{crisis.id}}</div>
<div>
<label>Name: </label>
<input [(ngModel)]="editName" placeholder="name"/>
</div>
<p>
<button (click)="save()">Save</button>
<button (click)="cancel()">Cancel</button>
</p>
</div>
`,
styles: ['input {width: 20em}']
})
export class CrisisDetailComponent implements OnInit, CanDeactivate {
crisis: Crisis;
editName: string;
constructor(
private service: CrisisService,
private router: Router,
private routeParams: RouteParams,
private _dialog: DialogService
) { }
ngOnInit() {
let id = +this.routeParams.get('id');
this.service.getCrisis(id).then(crisis => {
if (crisis) {
this.editName = crisis.name;
this.crisis = crisis;
} else { // id not found
this.gotoCrises();
}
});
}
routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction): any {
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged.
if (!this.crisis || this.crisis.name === this.editName) {
return true;
}
// Otherwise ask the user with the dialog service and return its
// promise which resolves to true or false when the user decides
return this._dialog.confirm('Discard changes?');
}
cancel() {
this.editName = this.crisis.name;
this.gotoCrises();
}
save() {
this.crisis.name = this.editName;
this.gotoCrises();
}
// #docregion gotoCrises
gotoCrises() {
let crisisId = this.crisis ? this.crisis.id : null;
// Pass along the hero id if available
// so that the CrisisListComponent can select that hero.
// Add a totally useless `foo` parameter for kicks.
// #docregion gotoCrises-navigate
this.router.navigate(['CrisisList', {id: crisisId, foo: 'foo'} ]);
// #enddocregion gotoCrises-navigate
}
// #enddocregion gotoCrises
}

View File

@ -1,37 +0,0 @@
// #docplaster
// #docregion
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router-deprecated';
import { Crisis, CrisisService } from './crisis.service';
@Component({
// #docregion template
template: `
<ul class="items">
<li *ngFor="let crisis of crises"
(click)="onSelect(crisis)">
<span class="badge">{{crisis.id}}</span> {{crisis.name}}
</li>
</ul>
`,
// #enddocregion template
})
export class CrisisListComponent implements OnInit {
crises: Crisis[];
constructor(
private service: CrisisService,
private router: Router) {}
ngOnInit() {
this.service.getCrises().then(crises => this.crises = crises);
}
// #docregion select
onSelect(crisis: Crisis) {
this.router.navigate(['CrisisDetail', { id: crisis.id }] );
}
// #enddocregion select
}

View File

@ -1,41 +0,0 @@
// #docplaster
// #docregion
import { Component, OnInit } from '@angular/core';
import { RouteParams, Router } from '@angular/router-deprecated';
import { Crisis, CrisisService } from './crisis.service';
@Component({
template: `
<ul class="items">
<li *ngFor="let crisis of crises"
[class.selected]="isSelected(crisis)"
(click)="onSelect(crisis)">
<span class="badge">{{crisis.id}}</span> {{crisis.name}}
</li>
</ul>
`,
})
export class CrisisListComponent implements OnInit {
crises: Crisis[];
private selectedId: number;
constructor(
private service: CrisisService,
private router: Router,
routeParams: RouteParams) {
this.selectedId = +routeParams.get('id');
}
isSelected(crisis: Crisis) { return crisis.id === this.selectedId; }
ngOnInit() {
this.service.getCrises().then(crises => this.crises = crises);
}
onSelect(crisis: Crisis) {
this.router.navigate( ['CrisisDetail', { id: crisis.id }] );
}
}

View File

@ -1,40 +0,0 @@
// #docplaster
// #docregion
import { Injectable } from '@angular/core';
export class Crisis {
constructor(public id: number, public name: string) { }
}
let crises = [
new Crisis(1, 'Dragon Burning Cities'),
new Crisis(2, 'Sky Rains Great White Sharks'),
new Crisis(3, 'Giant Asteroid Heading For Earth'),
new Crisis(4, 'Procrastinators Meeting Delayed Again'),
];
let crisesPromise = Promise.resolve(crises);
@Injectable()
export class CrisisService {
getCrises() { return crisesPromise; }
getCrisis(id: number | string) {
return crisesPromise
.then(crises => crises.find(c => c.id === +id));
}
// #enddocregion
static nextCrisisId = 100;
addCrisis(name: string) {
name = name.trim();
if (name) {
let crisis = new Crisis(CrisisService.nextCrisisId++, name);
crisesPromise.then(crises => crises.push(crisis));
}
}
// #docregion
}
// #enddocregion

View File

@ -1,10 +0,0 @@
// Initial empty version
// #docregion
import { Component } from '@angular/core';
@Component({
template: `
<h2>CRISIS CENTER</h2>
<p>Get your crisis here</p>`
})
export class CrisisListComponent { }

View File

@ -1,18 +0,0 @@
// #docregion
import { Injectable } from '@angular/core';
/**
* Async modal dialog service
* DialogService makes this app easier to test by faking this service.
* TODO: better modal implementation that doesn't use window.confirm
*/
@Injectable()
export class DialogService {
/**
* Ask user to confirm an action. `message` explains the action and choices.
* Returns promise resolving to `true`=confirm or `false`=cancel
*/
confirm(message?: string) {
return new Promise<boolean>((resolve, reject) =>
resolve(window.confirm(message || 'Is it OK?')));
};
}

View File

@ -1,10 +0,0 @@
/// Initial empty version
// #docregion
import { Component } from '@angular/core';
@Component({
template: `
<h2>HEROES</h2>
<p>Get your heroes here</p>`
})
export class HeroListComponent { }

View File

@ -1,47 +0,0 @@
// #docregion
import { Component, OnInit } from '@angular/core';
import { RouteParams, Router } from '@angular/router-deprecated';
import { Hero, HeroService } from './hero.service';
@Component({
template: `
<h2>HEROES</h2>
<div *ngIf="hero">
<h3>"{{hero.name}}"</h3>
<div>
<label>Id: </label>{{hero.id}}</div>
<div>
<label>Name: </label>
<input [(ngModel)]="hero.name" placeholder="name"/>
</div>
<p>
<button (click)="gotoHeroes()">Back</button>
</p>
</div>
`,
})
export class HeroDetailComponent implements OnInit {
hero: Hero;
// #docregion ctor
constructor(
private router: Router,
private routeParams: RouteParams,
private service: HeroService) {}
// #enddocregion ctor
// #docregion ngOnInit
ngOnInit() {
let id = this.routeParams.get('id');
this.service.getHero(id).then(hero => this.hero = hero);
}
// #enddocregion ngOnInit
// #docregion gotoHeroes
gotoHeroes() {
// Like <a [routerLink]="['Heroes']">Heroes</a>
this.router.navigate(['Heroes']);
}
// #enddocregion gotoHeroes
}

View File

@ -1,52 +0,0 @@
// #docregion
import { Component, OnInit } from '@angular/core';
import { RouteParams, Router } from '@angular/router-deprecated';
import { Hero, HeroService } from './hero.service';
@Component({
template: `
<h2>HEROES</h2>
<div *ngIf="hero">
<h3>"{{hero.name}}"</h3>
<div>
<label>Id: </label>{{hero.id}}</div>
<div>
<label>Name: </label>
<input [(ngModel)]="hero.name" placeholder="name"/>
</div>
<p>
<button (click)="gotoHeroes()">Back</button>
</p>
</div>
`,
})
export class HeroDetailComponent implements OnInit {
hero: Hero;
// #docregion ctor
constructor(
private router: Router,
private routeParams: RouteParams,
private service: HeroService) {}
// #enddocregion ctor
// #docregion ngOnInit
ngOnInit() {
let id = this.routeParams.get('id');
this.service.getHero(id).then(hero => this.hero = hero);
}
// #enddocregion ngOnInit
// #docregion gotoHeroes
gotoHeroes() {
let heroId = this.hero ? this.hero.id : null;
// Pass along the hero id if available
// so that the HeroList component can select that hero.
// Add a totally useless `foo` parameter for kicks.
// #docregion gotoHeroes-navigate
this.router.navigate(['Heroes', {id: heroId, foo: 'foo'} ]);
// #enddocregion gotoHeroes-navigate
}
// #enddocregion gotoHeroes
}

View File

@ -1,50 +0,0 @@
// #docplaster
// #docregion
// TODO SOMEDAY: Feature Componetized like HeroCenter
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router-deprecated';
import { Hero, HeroService } from './hero.service';
@Component({
// #docregion template
template: `
<h2>HEROES</h2>
<ul class="items">
<li *ngFor="let hero of heroes"
(click)="onSelect(hero)">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
</ul>
`
// #enddocregion template
})
export class HeroListComponent implements OnInit {
heroes: Hero[];
// #docregion ctor
constructor(
private router: Router,
private service: HeroService) { }
// #enddocregion ctor
ngOnInit() {
this.service.getHeroes().then(heroes => this.heroes = heroes);
}
// #docregion select
onSelect(hero: Hero) {
// #docregion nav-to-detail
this.router.navigate( ['HeroDetail', { id: hero.id }] );
// #enddocregion nav-to-detail
}
// #enddocregion select
}
// #enddocregion
/* A link parameters array
// #docregion link-parameters-array
['HeroDetail', { id: hero.id }] // {id: 15}
// #enddocregion link-parameters-array
*/

View File

@ -1,56 +0,0 @@
// #docplaster
// TODO SOMEDAY: Feature Componetized like CrisisCenter
// #docregion
import { Component, OnInit } from '@angular/core';
// #docregion import-route-params
import { RouteParams, Router } from '@angular/router-deprecated';
// #enddocregion import-route-params
import { Hero, HeroService } from './hero.service';
@Component({
// #docregion template
template: `
<h2>HEROES</h2>
<ul class="items">
<li *ngFor="let hero of heroes"
[class.selected]="isSelected(hero)"
(click)="onSelect(hero)">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
</ul>
`
// #enddocregion template
})
export class HeroListComponent implements OnInit {
heroes: Hero[];
// #docregion ctor
private selectedId: number;
constructor(
private service: HeroService,
private router: Router,
routeParams: RouteParams) {
this.selectedId = +routeParams.get('id');
}
// #enddocregion ctor
// #docregion isSelected
isSelected(hero: Hero) { return hero.id === this.selectedId; }
// #enddocregion isSelected
// #docregion select
onSelect(hero: Hero) {
this.router.navigate( ['HeroDetail', { id: hero.id }] );
}
// #enddocregion select
ngOnInit() {
this.service.getHeroes().then(heroes => this.heroes = heroes);
}
}
// #enddocregion

View File

@ -1,27 +0,0 @@
// #docregion
import { Injectable } from '@angular/core';
export class Hero {
constructor(public id: number, public name: string) { }
}
let HEROES = [
new Hero(11, 'Mr. Nice'),
new Hero(12, 'Narco'),
new Hero(13, 'Bombasto'),
new Hero(14, 'Celeritas'),
new Hero(15, 'Magneta'),
new Hero(16, 'RubberMan')
];
let heroesPromise = Promise.resolve(HEROES);
@Injectable()
export class HeroService {
getHeroes() { return heroesPromise; }
getHero(id: number | string) {
return heroesPromise
.then(heroes => heroes.find(h => h.id === +id));
}
}

View File

@ -1,24 +0,0 @@
/* First version */
// #docplaster
// #docregion all
import { bootstrap } from '@angular/platform-browser-dynamic';
import { ROUTER_PROVIDERS } from '@angular/router-deprecated';
import { AppComponent } from './app.component';
// #enddocregion all
/* Can't use AppComponent ... but display as if we can
// #docregion all
bootstrap(AppComponent, [
// #enddocregion all
*/
// Actually use the v.1 component
import { AppComponent as ac } from './app.component.1';
bootstrap(ac, [
// #docregion all
ROUTER_PROVIDERS
]);
// #enddocregion all

View File

@ -1,31 +0,0 @@
/* Second version */
// For Milestone #2
// Also includes digression on HashPathStrategy (not used in the final app)
// #docplaster
// #docregion
import { bootstrap } from '@angular/platform-browser-dynamic';
import { ROUTER_PROVIDERS } from '@angular/router-deprecated';
// Add these symbols to override the `LocationStrategy`
import { LocationStrategy,
HashLocationStrategy } from '@angular/common';
import { AppComponent } from './app.component';
// #enddocregion
/* Can't use AppComponent ... but display as if we can
// #docregion
bootstrap(AppComponent, [
// #enddocregion
*/
// Actually use the v.2 component
import { AppComponent as ac } from './app.component.2';
bootstrap(ac, [
// #docregion
ROUTER_PROVIDERS,
{ provide: LocationStrategy, useClass: HashLocationStrategy } // .../#/crisis-center/
]);
// #enddocregion

View File

@ -1,7 +0,0 @@
// #docregion
import { bootstrap } from '@angular/platform-browser-dynamic';
import { ROUTER_PROVIDERS } from '@angular/router-deprecated';
import { AppComponent } from './app.component.3';
bootstrap(AppComponent, [ROUTER_PROVIDERS]);

View File

@ -1,7 +0,0 @@
// #docregion
import { bootstrap } from '@angular/platform-browser-dynamic';
import { ROUTER_PROVIDERS } from '@angular/router-deprecated';
import { AppComponent } from './app.component';
bootstrap(AppComponent, [ROUTER_PROVIDERS]);

View File

@ -1,33 +0,0 @@
<!DOCTYPE html>
<!-- #docregion -->
<html>
<head>
<!-- #docregion base-href -->
<base href="/">
<!-- #enddocregion base-href -->
<title>Router (Deprecated) Sample v.1</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app/main.1') // <----- ONLY CHANGE
.then(null, console.error.bind(console));
</script>
</head>
<body>
<h1>Milestone 1</h1>
<my-app>loading...</my-app>
</body>
</html>
<!-- #enddocregion -->

View File

@ -1,31 +0,0 @@
<!DOCTYPE html>
<!-- #docregion -->
<html>
<head>
<base href="/">
<title>Router (Deprecated) Sample v.2</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app/main.2') // <----- ONLY CHANGE
.then(null, console.error.bind(console));
</script>
</head>
<body>
<h1>Milestone 2</h1>
<my-app>loading...</my-app>
</body>
</html>
<!-- #enddocregion -->

View File

@ -1,31 +0,0 @@
<!DOCTYPE html>
<!-- #docregion -->
<html>
<head>
<base href="/">
<title>Router (Deprecated) Sample v.3</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app/main.3') // <----- ONLY CHANGE
.then(null, console.error.bind(console));
</script>
</head>
<body>
<h1>Milestone 3</h1>
<my-app>loading...</my-app>
</body>
</html>
<!-- #enddocregion -->

View File

@ -1,12 +0,0 @@
{
"description": "Router (Deprecated Beta)",
"files":[
"!**/*.d.ts",
"!**/*.js",
"!**/*.[1,2,3].*",
"!app/crisis-list.component.ts",
"!app/hero-list.component.ts",
"!app/crisis-center/add-crisis.component.ts"
],
"tags": ["router", "deprecated"]
}

View File

@ -16,8 +16,8 @@ describe('Router', function () {
crisisHref: hrefEles.get(0), crisisHref: hrefEles.get(0),
crisisList: element.all(by.css('my-app > ng-component > ng-component li')), crisisList: element.all(by.css('my-app > ng-component > ng-component li')),
crisisDetail: element(by.css('my-app > ng-component > ng-component > div')), crisisDetail: element(by.css('my-app > ng-component > ng-component > ng-component > div')),
crisisDetailTitle: element(by.css('my-app > ng-component > ng-component > div > h3')), crisisDetailTitle: element(by.css('my-app > ng-component > ng-component > ng-component > div > h3')),
heroesHref: hrefEles.get(1), heroesHref: hrefEles.get(1),
heroesList: element.all(by.css('my-app > ng-component li')), heroesList: element.all(by.css('my-app > ng-component li')),
@ -34,7 +34,7 @@ describe('Router', function () {
expect(page.hrefs.count()).toEqual(4, 'should be 4 dashboard choices'); expect(page.hrefs.count()).toEqual(4, 'should be 4 dashboard choices');
expect(page.crisisHref.getText()).toEqual('Crisis Center'); expect(page.crisisHref.getText()).toEqual('Crisis Center');
expect(page.heroesHref.getText()).toEqual('Heroes'); expect(page.heroesHref.getText()).toEqual('Heroes');
expect(page.adminHref.getText()).toEqual('Crisis Admin'); expect(page.adminHref.getText()).toEqual('Admin');
expect(page.loginHref.getText()).toEqual('Login'); expect(page.loginHref.getText()).toEqual('Login');
}); });
@ -118,7 +118,6 @@ describe('Router', function () {
crisisText = text.substr(text.indexOf(' ')).trim(); crisisText = text.substr(text.indexOf(' ')).trim();
return crisisEle.click(); return crisisEle.click();
}).then(function () { }).then(function () {
expect(page.crisisList.count()).toBe(0, 'should no longer see crisis center entries');
expect(page.crisisDetail.isPresent()).toBe(true, 'should be able to see crisis detail'); expect(page.crisisDetail.isPresent()).toBe(true, 'should be able to see crisis detail');
expect(page.crisisDetailTitle.getText()).toContain(crisisText); expect(page.crisisDetailTitle.getText()).toContain(crisisText);
let inputEle = page.crisisDetail.element(by.css('input')); let inputEle = page.crisisDetail.element(by.css('input'));

View File

@ -0,0 +1,9 @@
// #docregion
import { Component } from '@angular/core';
@Component({
template: `
<p>Dashboard</p>
`
})
export class AdminDashboardComponent { }

View File

@ -6,15 +6,14 @@ import 'rxjs/add/operator/map';
@Component({ @Component({
template: ` template: `
<h3>CRISIS ADMINISTRATION</h3> <p>Dashboard</p>
<p>Manage your crises here</p>
<p>Session ID: {{ sessionId | async }}</p> <p>Session ID: {{ sessionId | async }}</p>
<a id="anchor"></a> <a id="anchor"></a>
<p>Token: {{ token | async }}</p> <p>Token: {{ token | async }}</p>
` `
}) })
export class CrisisAdminComponent implements OnInit { export class AdminDashboardComponent implements OnInit {
sessionId: Observable<string>; sessionId: Observable<string>;
token: Observable<string>; token: Observable<string>;

View File

@ -0,0 +1,17 @@
// #docregion
import { Component } from '@angular/core';
@Component({
template: `
<h3>ADMIN</h3>
<nav>
<a routerLink="./" routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }">Dashboard</a>
<a routerLink="./crises" routerLinkActive="active">Manage Crises</a>
<a routerLink="./heroes" routerLinkActive="active">Manage Heroes</a>
</nav>
<router-outlet></router-outlet>
`
})
export class AdminComponent {
}

View File

@ -0,0 +1,28 @@
// #docplaster
// #docregion
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AdminComponent } from './admin.component';
import { AdminDashboardComponent } from './admin-dashboard.component';
import { ManageCrisesComponent } from './manage-crises.component';
import { ManageHeroesComponent } from './manage-heroes.component';
import { adminRouting } from './admin.routing';
@NgModule({
imports: [
CommonModule,
adminRouting
],
declarations: [
AdminComponent,
AdminDashboardComponent,
ManageCrisesComponent,
ManageHeroesComponent
]
})
// #docregion admin-module-export
export class AdminModule {}
// #enddocregion admin-module-export
// #enddocregion

View File

@ -0,0 +1,31 @@
// #docplaster
// #docregion
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AdminComponent } from './admin.component';
import { AdminDashboardComponent } from './admin-dashboard.component';
import { ManageCrisesComponent } from './manage-crises.component';
import { ManageHeroesComponent } from './manage-heroes.component';
// #docregion admin-routes
const adminRoutes: Routes = [
{
path: 'admin',
component: AdminComponent,
children: [
{
path: '',
children: [
{ path: 'crises', component: ManageCrisesComponent },
{ path: 'heroes', component: ManageHeroesComponent },
{ path: '', component: AdminDashboardComponent }
]
}
]
}
];
export const adminRouting: ModuleWithProviders = RouterModule.forChild(adminRoutes);
// #enddocregion admin-routes
// #enddocregion

View File

@ -0,0 +1,37 @@
// #docplaster
// #docregion
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AdminComponent } from './admin.component';
import { AdminDashboardComponent } from './admin-dashboard.component';
import { ManageCrisesComponent } from './manage-crises.component';
import { ManageHeroesComponent } from './manage-heroes.component';
// #docregion admin-route, can-activate-child
import { AuthGuard } from '../auth-guard.service';
const adminRoutes: Routes = [
{
path: 'admin',
component: AdminComponent,
canActivate: [AuthGuard],
children: [
{
path: '',
children: [
{ path: 'crises', component: ManageCrisesComponent },
{ path: 'heroes', component: ManageHeroesComponent },
{ path: '', component: AdminDashboardComponent }
],
// #enddocregion admin-route
// #docregion can-activate-child
canActivateChild: [AuthGuard]
// #docregion admin-route
}
]
}
];
export const adminRouting: ModuleWithProviders = RouterModule.forChild(adminRoutes);
// #enddocregion

View File

@ -0,0 +1,35 @@
// #docplaster
// #docregion
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AdminComponent } from './admin.component';
import { AdminDashboardComponent } from './admin-dashboard.component';
import { ManageCrisesComponent } from './manage-crises.component';
import { ManageHeroesComponent } from './manage-heroes.component';
// #docregion admin-route
import { AuthGuard } from '../auth-guard.service';
// #docregion can-activate-child
const adminRoutes: Routes = [
{
path: 'admin',
component: AdminComponent,
canActivate: [AuthGuard],
children: [
{
path: '',
canActivateChild: [AuthGuard],
children: [
{ path: 'crises', component: ManageCrisesComponent },
{ path: 'heroes', component: ManageHeroesComponent },
{ path: '', component: AdminDashboardComponent }
]
}
]
}
];
export const adminRouting: ModuleWithProviders = RouterModule.forChild(adminRoutes);
// #enddocregion

View File

@ -0,0 +1,34 @@
// #docplaster
// #docregion
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AdminComponent } from './admin.component';
import { AdminDashboardComponent } from './admin-dashboard.component';
import { ManageCrisesComponent } from './manage-crises.component';
import { ManageHeroesComponent } from './manage-heroes.component';
// #docregion admin-route
import { AuthGuard } from '../auth-guard.service';
const adminRoutes: Routes = [
{
path: '',
component: AdminComponent,
canActivate: [AuthGuard],
children: [
{
path: '',
canActivateChild: [AuthGuard],
children: [
{ path: 'crises', component: ManageCrisesComponent },
{ path: 'heroes', component: ManageHeroesComponent },
{ path: '', component: AdminDashboardComponent }
]
}
]
}
];
export const adminRouting: ModuleWithProviders = RouterModule.forChild(adminRoutes);
// #enddocregion

View File

@ -3,8 +3,7 @@ import { Component } from '@angular/core';
@Component({ @Component({
template: ` template: `
<h3>CRISIS ADMINISTRATION</h3>
<p>Manage your crises here</p> <p>Manage your crises here</p>
` `
}) })
export class CrisisAdminComponent { } export class ManageCrisesComponent { }

View File

@ -0,0 +1,9 @@
// #docregion
import { Component } from '@angular/core';
@Component({
template: `
<p>Manage your heroes here</p>
`
})
export class ManageHeroesComponent { }

View File

@ -6,7 +6,7 @@ import { Component } from '@angular/core';
selector: 'my-app', selector: 'my-app',
// #docregion template // #docregion template
template: ` template: `
<h1>Component Router</h1> <h1>Angular Router</h1>
<nav> <nav>
<a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a> <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
<a routerLink="/heroes" routerLinkActive="active">Heroes</a> <a routerLink="/heroes" routerLinkActive="active">Heroes</a>

View File

@ -7,7 +7,7 @@ import { Component } from '@angular/core';
@Component({ @Component({
selector: 'my-app', selector: 'my-app',
template: ` template: `
<h1>Component Router</h1> <h1>Angular Router</h1>
<nav> <nav>
<a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a> <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
<a routerLink="/heroes" routerLinkActive="active">Heroes</a> <a routerLink="/heroes" routerLinkActive="active">Heroes</a>

View File

@ -1,7 +1,7 @@
/* tslint:disable:no-unused-variable */ /* tslint:disable:no-unused-variable */
// #docplaster // #docplaster
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
@Component({ @Component({
selector: 'my-app', selector: 'my-app',
@ -36,7 +36,7 @@ import { Router } from '@angular/router';
*/ */
// #docregion template // #docregion template
template: ` template: `
<h1 class="title">Component Router</h1> <h1 class="title">Angular Router</h1>
<nav> <nav>
<a [routerLink]="['/crisis-center']">Crisis Center</a> <a [routerLink]="['/crisis-center']">Crisis Center</a>
<a [routerLink]="['/crisis-center/1', { foo: 'foo' }]">Dragon Crisis</a> <a [routerLink]="['/crisis-center/1', { foo: 'foo' }]">Dragon Crisis</a>

View File

@ -1,16 +1,15 @@
// #docregion // #docregion
import { Component } from '@angular/core'; import { Component } from '@angular/core';
@Component({ @Component({
selector: 'my-app', selector: 'my-app',
// #docregion template // #docregion template
template: ` template: `
<h1 class="title">Component Router</h1> <h1 class="title">Angular Router</h1>
<nav> <nav>
<a routerLink="/crisis-center" routerLinkActive="active" <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
[routerLinkActiveOptions]="{ exact: true }">Crisis Center</a>
<a routerLink="/heroes" routerLinkActive="active">Heroes</a> <a routerLink="/heroes" routerLinkActive="active">Heroes</a>
<a routerLink="/crisis-center/admin" routerLinkActive="active">Crisis Admin</a> <a routerLink="/admin" routerLinkActive="active">Admin</a>
</nav> </nav>
<router-outlet></router-outlet> <router-outlet></router-outlet>
` `

View File

@ -1,17 +1,16 @@
// #docplaster // #docplaster
// #docregion // #docregion
import { Component } from '@angular/core'; import { Component } from '@angular/core';
@Component({ @Component({
selector: 'my-app', selector: 'my-app',
// #docregion template // #docregion template
template: ` template: `
<h1 class="title">Component Router</h1> <h1 class="title">Angular Router</h1>
<nav> <nav>
<a routerLink="/crisis-center" routerLinkActive="active" <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
[routerLinkActiveOptions]="{ exact: true }">Crisis Center</a>
<a routerLink="/heroes" routerLinkActive="active">Heroes</a> <a routerLink="/heroes" routerLinkActive="active">Heroes</a>
<a routerLink="/crisis-center/admin" routerLinkActive="active">Crisis Admin</a> <a routerLink="/admin" routerLinkActive="active">Admin</a>
<a routerLink="/login" routerLinkActive="active">Login</a> <a routerLink="/login" routerLinkActive="active">Login</a>
</nav> </nav>
<router-outlet></router-outlet> <router-outlet></router-outlet>

Some files were not shown because too many files have changed in this diff Show More