chore: new flat left navigation panel (all language tracks)
This commit is contained in:
parent
133f58c593
commit
746a6649b2
|
@ -0,0 +1,42 @@
|
|||
- var lang = current.path[1]
|
||||
|
||||
nav.side-nav.l-pinned-left.l-layer-4.l-offset-nav
|
||||
|
||||
// SEARCH BAR
|
||||
header.side-nav-search.st-input-wrapper
|
||||
form.st-input-inner
|
||||
label(for="search-io" class="is-hidden") Search Docs
|
||||
input(type="search" id="search-io" placeholder="SEARCH DOCS...")
|
||||
button(class="mobile-trigger button" aria-label="View Docs Menu" ng-click="appCtrl.toggleDocsMenu($event)" md-button) Docs <span class="icon icon-arrow-drop-down"></span>
|
||||
|
||||
div(class="side-nav-secondary" ng-class="appCtrl.showDocsNav ? 'is-visible' : ''")
|
||||
!= partial("../" + lang + "/latest/_nav")
|
||||
|
||||
|
||||
script.
|
||||
// Could put in appCtrl but only needed here and clear here
|
||||
(function highlightSelectedLink() {
|
||||
var leftNav = document.getElementsByClassName('side-nav-secondary')[0];
|
||||
if (!leftNav) {return;}
|
||||
var links = leftNav.getElementsByTagName('a');
|
||||
var path = location.toString();
|
||||
// remove trailing '/'
|
||||
if (path[path.length-1] === '/') {path = path.slice(0, path.length-1);}
|
||||
// remove trailing '/index.html' (11 chars) for matching purposes.
|
||||
if (path.lastIndexOf('/index.html') === path.length-11) {
|
||||
path = path.slice(0, -11);
|
||||
}
|
||||
for (var i=0; i < links.length; i++){
|
||||
// assumes fresh page each time so no need to clear class
|
||||
if (path === links[i].href) {
|
||||
var parent = links[i].parentElement;
|
||||
parent.classList.add('is-selected');
|
||||
|
||||
if(parent.offsetTop > window.innerHeight && parent.scrollIntoView){
|
||||
parent.scrollIntoView(false);
|
||||
// parent.scrollTop();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
})()
|
|
@ -1,25 +0,0 @@
|
|||
nav.side-nav.l-pinned-left.l-layer-4.l-offset-nav
|
||||
|
||||
// SEARCH BAR
|
||||
header.side-nav-search.st-input-wrapper
|
||||
form.st-input-inner
|
||||
label(for="search-io" class="is-hidden") Search Docs
|
||||
input(type="search" id="search-io" placeholder="SEARCH DOCS...")
|
||||
button(class="mobile-trigger button" aria-label="View Docs Menu" ng-click="appCtrl.toggleDocsMenu($event)" md-button) Docs <span class="icon icon-arrow-drop-down"></span>
|
||||
|
||||
|
||||
// PRIMARY NAVIGATION
|
||||
ul(class="side-nav-primary" ng-class="appCtrl.showDocsNav ? 'is-visible' : ''")
|
||||
if current.path[2]
|
||||
for page, slug in public.docs[current.path[1]][current.path[2]]._data
|
||||
|
||||
- var name = page.menuTitle || page.title
|
||||
- var selected = current.path[3] == slug ? 'is-selected':''
|
||||
- var pathSuffix = public.docs[current.path[1]][current.path[2]][slug] ? "/" : ".html"
|
||||
|
||||
li(class="#{selected}") <a href="/docs/#{current.path[1]}/#{current.path[2]}/#{slug}#{pathSuffix}" md-button><span class="side-nav-icon icon-#{page.icon}"></span> #{name}</a>
|
||||
|
||||
|
||||
// SECONDARY NAVIGATION
|
||||
if selected
|
||||
!= partial("_secondary")
|
|
@ -1,41 +0,0 @@
|
|||
- var secondaryPath = public.docs[current.path[1]][current.path[2]][current.path[3]]
|
||||
|
||||
if secondaryPath
|
||||
- var data = secondaryPath._data
|
||||
- var listType = data._listtype
|
||||
- var isOrdered = listType == "ordered" || listType == "alpha"
|
||||
- var ordered = isOrdered ? "is-ordered" : ""
|
||||
- var items = listType == 'api' ? secondaryPath : data
|
||||
- var number = 1
|
||||
|
||||
|
||||
//SECONDARY NAVIGATION
|
||||
ul(class="side-nav-secondary #{ordered}")
|
||||
|
||||
for page, slug in items
|
||||
|
||||
// DEFAULT LIST VALUES
|
||||
- var selected = current.path[4] == slug ? 'is-selected':''
|
||||
- var name = page.title;
|
||||
- var path = "/docs/" + current.path[1] + "/" + current.path[2] + "/" + current.path[3] + "/" + slug + ".html"
|
||||
|
||||
|
||||
if slug != "_listtype" && slug != 'index' && slug != '_contents' && slug != '_data'
|
||||
// API LIST VALUES
|
||||
if listType == 'api'
|
||||
- var name = public.docs[current.path[1]][current.path[2]][current.path[3]][slug]._data["index"]["title"]
|
||||
- var path = "/docs/" + current.path[1] + "/" + current.path[2] + "/" + current.path[3] + "/" + slug
|
||||
|
||||
// ORDERED LIST VALUES
|
||||
if isOrdered
|
||||
- var num = number++
|
||||
- var name = (listType == "ordered") ? num + '. ' + page.title : page.title;
|
||||
|
||||
|
||||
li(class="#{selected}") <a href="#{path}" md-button>#{name}</a>
|
||||
|
||||
|
||||
|
||||
// TERTIARY NAVIGATION
|
||||
if selected
|
||||
!= partial("_tertiary")
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
// TERTIARY NAVIGATION
|
||||
- var tertiaryPath = public.docs[current.path[1]][current.path[2]][current.path[3]][current.path[4]]
|
||||
|
||||
if tertiaryPath
|
||||
- var data = tertiaryPath._data
|
||||
|
||||
ul.side-nav-tertiary
|
||||
for page, slug in data
|
||||
- var name = page.title
|
||||
- var selected = current.path[5] == slug ? 'is-selected':''
|
||||
|
||||
if slug != "index"
|
||||
li(class="#{selected}")<a href="/docs/#{current.path[1]}/#{current.path[2]}/#{current.path[3]}/#{current.path[4]}/#{slug}.html" md-button>#{name}</a>
|
||||
|
|
@ -31,7 +31,7 @@ include ../../../_includes/_util-fns
|
|||
page that needs either of these mixins.
|
||||
|
||||
code-example(language="js").
|
||||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
The syntax for the `makeExample` mixin is:
|
||||
|
|
|
@ -5,7 +5,7 @@ html(lang="en" ng-app="angularIOApp" itemscope itemtype="http://schema.org/Frame
|
|||
|
||||
body(class="l-offset-nav l-offset-side-nav" ng-controller="AppCtrl as appCtrl")
|
||||
!= partial("../_includes/_main-nav")
|
||||
!= partial("_includes/sidenav/_primary")
|
||||
!= partial("_includes/_side-nav")
|
||||
!= partial("../_includes/_hero")
|
||||
!= partial("../_includes/_banner")
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
- var base = '/docs/dart/latest/'
|
||||
|
||||
.nav-blocks
|
||||
.nav-title Tutorial
|
||||
.nav-primary-link
|
||||
a(href='#{base}quickstart.html') 5 Min Quickstart
|
||||
.nav-sub-title Case Study: Tour of Heroes
|
||||
.nav-ordered-lists
|
||||
ol
|
||||
li: a(href='#{base}tutorial') Introduction
|
||||
li: a(href='#{base}tutorial/toh-pt1.html') The Hero Editor
|
||||
li: a(href='#{base}tutorial/toh-pt2.html') Master/Detail
|
||||
li: a(href='#{base}tutorial/toh-pt3.html') Multiple Components
|
||||
li: a(href='#{base}tutorial/toh-pt4.html') Services
|
||||
li: a(href='#{base}tutorial/toh-pt5.html') Routing
|
||||
|
||||
.nav-blocks
|
||||
.nav-title Basics
|
||||
.nav-ordered-lists
|
||||
ol
|
||||
li: a(href='#{base}guide') Overview
|
||||
li: a(href='#{base}guide/architecture.html') Architecture
|
||||
li: a(href='#{base}guide/displaying-data.html') Displaying Data
|
||||
li: a(href='#{base}guide/user-input.html') User Inputs
|
||||
li: a(href='#{base}guide/forms.html') Forms
|
||||
li: a(href='#{base}guide/dependency-injection.html') Dependency Injection
|
||||
li: a(href='#{base}guide/template-syntax.html') Template Syntax
|
||||
li: a(href='#{base}guide/cheatsheet.html') Angular Cheat Sheet
|
||||
.nav-blocks
|
||||
.nav-title Developer Guide
|
||||
.nav-unordered-lists
|
||||
ul
|
||||
li: a(href='#{base}guide/attribute-directives.html') Attribute Directives
|
||||
li: a(href='#{base}guide/hierarchical-dependency-injection.html') Hierarchical Injectors
|
||||
li: a(href='#{base}guide/server-communication.html') Http Client
|
||||
li: a(href='#{base}guide/lifecycle-hooks.html') Lifecycle Hooks
|
||||
li: a(href='#{base}guide/pipes.html') Pipes
|
||||
li: a(href='#{base}guide/router.html') Routing and Navigation
|
||||
li: a(href='#{base}guide/structural-directives.html') Structural Directives
|
||||
li: a(href='#{base}guide/upgrade.html') Upgrading from 1.x
|
||||
.nav-blocks
|
||||
.nav-title Cookbook
|
||||
.nav-unordered-lists
|
||||
ul
|
||||
li: a(href='#{base}cookbook') Overview
|
||||
li: a(href='#{base}cookbook/a1-a2-quick-reference.html') Angular 1 to 2 Quick Ref
|
||||
li: a(href='#{base}cookbook/component-communication.html') Component Interaction
|
||||
.nav-blocks
|
||||
.nav-title Reference
|
||||
.nav-unordered-lists
|
||||
ul
|
||||
li: a(href='#{base}api') API Preview
|
||||
li: a(href='#{base}cheatsheet.html') Angular Cheat Sheet
|
||||
li: a(href='#{base}guide/glossary.html') Glossary
|
||||
.nav-blocks
|
||||
.nav-title Resources
|
||||
.nav-unordered-lists
|
||||
ul
|
||||
li: a(href='#{base}resources.html') Angular Resources
|
||||
li: a(href='#{base}help.html') Help & Support
|
|
@ -0,0 +1 @@
|
|||
include ../../../_includes/_util-fns
|
|
@ -0,0 +1,6 @@
|
|||
.banner
|
||||
p.text-body This cheat sheet is provisional and may change. Angular 2 is currently in Beta.
|
||||
|
||||
article(class="l-content-small grid-fluid docs-content")
|
||||
.cheatsheet
|
||||
ngio-cheatsheet(src='./guide/cheatsheet.json')
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
Angular 2 is a framework to help us build client applications in HTML and
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
We're working on the Dart version of this chapter.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
We're working on the Dart version of this chapter.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
We typically display data in Angular by binding controls in an HTML template
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
<!-- http://plnkr.co/edit/wg154K -->
|
||||
:marked
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
+includeShared('{ts}', 'intro')
|
||||
+includeShared('{ts}', 'a2')
|
||||
+includeShared('{ts}', 'b-c')
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
We're working on the Dart version of this chapter.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
This Developers Guide is a practical guide to Angular for experienced programmers who
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
We're working on the Dart version of this chapter.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
We're working on the Dart version of this chapter.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
We're working on the Dart version of this chapter.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
We're working on the Dart version of this chapter.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
We're working on the Dart version of this chapter.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
+includeShared('{ts}', 'intro')
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
When the user clicks a link, pushes a button, or enters text
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../_includes/_util-fns
|
||||
include _util-fns
|
||||
|
||||
:marked
|
||||
Let's start from zero and build a super simple Angular 2 application in Dart.
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"_listtype": "ordered",
|
||||
|
||||
"index": {
|
||||
"title": "Testing Overview",
|
||||
"intro": "Techniques and practices for testing an Angular 2 app"
|
||||
},
|
||||
|
||||
"jasmine-testing-101": {
|
||||
"title": "Jasmine Testing 101",
|
||||
"intro": "The basics of testing anything with Jasmine"
|
||||
},
|
||||
|
||||
"application-under-test": {
|
||||
"title": "The Application Under Test",
|
||||
"intro": "A quick look at the application we will test"
|
||||
},
|
||||
|
||||
"first-app-tests": {
|
||||
"title": "First App Tests",
|
||||
"intro": "The first test of a simple, non-Angular part of our app"
|
||||
},
|
||||
|
||||
"testing-an-angular-pipe": {
|
||||
"title": "Testing an Angular Pipe",
|
||||
"intro": "We test an Angular-aware part of our app"
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
|
@ -0,0 +1,61 @@
|
|||
- var base = '/docs/js/latest/'
|
||||
|
||||
.nav-blocks
|
||||
.nav-title Tutorial
|
||||
.nav-primary-link
|
||||
a(href='#{base}quickstart.html') 5 Min Quickstart
|
||||
.nav-sub-title Case Study: Tour of Heroes
|
||||
.nav-ordered-lists
|
||||
ol
|
||||
li: a(href='#{base}tutorial') Introduction
|
||||
li: a(href='#{base}tutorial/toh-pt1.html') The Hero Editor
|
||||
li: a(href='#{base}tutorial/toh-pt2.html') Master/Detail
|
||||
li: a(href='#{base}tutorial/toh-pt3.html') Multiple Components
|
||||
li: a(href='#{base}tutorial/toh-pt4.html') Services
|
||||
li: a(href='#{base}tutorial/toh-pt5.html') Routing
|
||||
|
||||
.nav-blocks
|
||||
.nav-title Basics
|
||||
.nav-ordered-lists
|
||||
ol
|
||||
li: a(href='#{base}guide') Overview
|
||||
li: a(href='#{base}guide/architecture.html') Architecture
|
||||
li: a(href='#{base}guide/displaying-data.html') Displaying Data
|
||||
li: a(href='#{base}guide/user-input.html') User Inputs
|
||||
li: a(href='#{base}guide/forms.html') Forms
|
||||
li: a(href='#{base}guide/dependency-injection.html') Dependency Injection
|
||||
li: a(href='#{base}guide/template-syntax.html') Template Syntax
|
||||
li: a(href='#{base}guide/cheatsheet.html') Angular Cheat Sheet
|
||||
.nav-blocks
|
||||
.nav-title Developer Guide
|
||||
.nav-unordered-lists
|
||||
ul
|
||||
li: a(href='#{base}guide/attribute-directives.html') Attribute Directives
|
||||
li: a(href='#{base}guide/hierarchical-dependency-injection.html') Hierarchical Injectors
|
||||
li: a(href='#{base}guide/server-communication.html') Http Client
|
||||
li: a(href='#{base}guide/lifecycle-hooks.html') Lifecycle Hooks
|
||||
li: a(href='#{base}guide/npm-packages.html') npm packages
|
||||
li: a(href='#{base}guide/pipes.html') Pipes
|
||||
li: a(href='#{base}guide/router.html') Routing and Navigation
|
||||
li: a(href='#{base}guide/structural-directives.html') Structural Directives
|
||||
li: a(href='#{base}guide/upgrade.html') Upgrading from 1.x
|
||||
.nav-blocks
|
||||
.nav-title Cookbook
|
||||
.nav-unordered-lists
|
||||
ul
|
||||
li: a(href='#{base}cookbook') Overview
|
||||
li: a(href='#{base}cookbook/a1-a2-quick-reference.html') Angular 1 to 2 Quick Ref
|
||||
li: a(href='#{base}cookbook/component-communication.html') Component Interaction
|
||||
.nav-blocks
|
||||
.nav-title Reference
|
||||
.nav-unordered-lists
|
||||
ul
|
||||
li: a(href='#{base}api') API Preview
|
||||
li: a(href='#{base}cheatsheet.html') Angular Cheat Sheet
|
||||
li: a(href='#{base}guide/glossary.html') Glossary
|
||||
.nav-blocks
|
||||
.nav-title Resources
|
||||
.nav-unordered-lists
|
||||
ul
|
||||
li: a(href='#{base}resources.html') Angular Resources
|
||||
li: a(href='#{base}help.html') Help & Support
|
|
@ -0,0 +1,6 @@
|
|||
.banner
|
||||
p.text-body This cheat sheet is provisional and may change. Angular 2 is currently in Beta.
|
||||
|
||||
article(class="l-content-small grid-fluid docs-content")
|
||||
.cheatsheet
|
||||
ngio-cheatsheet(src='./guide/cheatsheet.json')
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
We’ve all used a form to login, submit a help request, place an order, book a flight,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
+includeShared('{ts}', 'intro')
|
||||
+includeShared('{ts}', 'a2')
|
||||
+includeShared('{ts}', 'b-c')
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
+includeShared('{ts}', 'intro')
|
||||
+includeShared('{ts}', 'how-to-read-1')
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../_includes/_util-fns
|
||||
include _util-fns
|
||||
|
||||
:marked
|
||||
Let's start from zero and build a super simple Angular 2 application in JavaScript.
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"_listtype": "ordered",
|
||||
|
||||
"index": {
|
||||
"title": "Testing Overview",
|
||||
"intro": "Techniques and practices for testing an Angular 2 app"
|
||||
},
|
||||
|
||||
"jasmine-testing-101": {
|
||||
"title": "Jasmine Testing 101",
|
||||
"intro": "The basics of testing anything with Jasmine"
|
||||
},
|
||||
|
||||
"application-under-test": {
|
||||
"title": "The Application Under Test",
|
||||
"intro": "A quick look at the application we will test"
|
||||
},
|
||||
|
||||
"first-app-tests": {
|
||||
"title": "First App Tests",
|
||||
"intro": "The first test of a simple, non-Angular part of our app"
|
||||
},
|
||||
|
||||
"testing-an-angular-pipe": {
|
||||
"title": "Testing an Angular Pipe",
|
||||
"intro": "We test an Angular-aware part of our app"
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
|
@ -0,0 +1,63 @@
|
|||
- var base = '/docs/ts/latest/'
|
||||
|
||||
.nav-blocks
|
||||
.nav-title Tutorial
|
||||
.nav-primary-link
|
||||
a(href='#{base}quickstart.html') 5 Min Quickstart
|
||||
.nav-sub-title Case Study: Tour of Heroes
|
||||
.nav-ordered-lists
|
||||
ol
|
||||
li: a(href='#{base}tutorial') Introduction
|
||||
li: a(href='#{base}tutorial/toh-pt1.html') The Hero Editor
|
||||
li: a(href='#{base}tutorial/toh-pt2.html') Master/Detail
|
||||
li: a(href='#{base}tutorial/toh-pt3.html') Multiple Components
|
||||
li: a(href='#{base}tutorial/toh-pt4.html') Services
|
||||
li: a(href='#{base}tutorial/toh-pt5.html') Routing
|
||||
|
||||
.nav-blocks
|
||||
.nav-title Basics
|
||||
.nav-ordered-lists
|
||||
ol
|
||||
li: a(href='#{base}guide') Overview
|
||||
li: a(href='#{base}guide/architecture.html') Architecture
|
||||
li: a(href='#{base}guide/displaying-data.html') Displaying Data
|
||||
li: a(href='#{base}guide/user-input.html') User Inputs
|
||||
li: a(href='#{base}guide/forms.html') Forms
|
||||
li: a(href='#{base}guide/dependency-injection.html') Dependency Injection
|
||||
li: a(href='#{base}guide/template-syntax.html') Template Syntax
|
||||
li: a(href='#{base}guide/cheatsheet.html') Angular Cheat Sheet
|
||||
.nav-blocks
|
||||
.nav-title Developer Guide
|
||||
.nav-unordered-lists
|
||||
ul
|
||||
li: a(href='#{base}guide/attribute-directives.html') Attribute Directives
|
||||
li: a(href='#{base}guide/hierarchical-dependency-injection.html') Hierarchical Injectors
|
||||
li: a(href='#{base}guide/server-communication.html') Http Client
|
||||
li: a(href='#{base}guide/lifecycle-hooks.html') Lifecycle Hooks
|
||||
li: a(href='#{base}guide/npm-packages.html') npm packages
|
||||
li: a(href='#{base}guide/pipes.html') Pipes
|
||||
li: a(href='#{base}guide/router.html') Routing and Navigation
|
||||
li: a(href='#{base}guide/structural-directives.html') Structural Directives
|
||||
li: a(href='#{base}guide/testing.html') Testing
|
||||
li: a(href='#{base}guide/typescript-configuration.html') TypeScript Configuration
|
||||
li: a(href='#{base}guide/upgrade.html') Upgrading from 1.x
|
||||
.nav-blocks
|
||||
.nav-title Cookbook
|
||||
.nav-unordered-lists
|
||||
ul
|
||||
li: a(href='#{base}cookbook') Overview
|
||||
li: a(href='#{base}cookbook/a1-a2-quick-reference.html') Angular 1 to 2 Quick Ref
|
||||
li: a(href='#{base}cookbook/component-communication.html') Component Interaction
|
||||
.nav-blocks
|
||||
.nav-title Reference
|
||||
.nav-unordered-lists
|
||||
ul
|
||||
li: a(href='#{base}api') API Preview
|
||||
li: a(href='#{base}cheatsheet.html') Angular Cheat Sheet
|
||||
li: a(href='#{base}guide/glossary.html') Glossary
|
||||
.nav-blocks
|
||||
.nav-title Resources
|
||||
.nav-unordered-lists
|
||||
ul
|
||||
li: a(href='#{base}resources.html') Angular Resources
|
||||
li: a(href='#{base}help.html') Help & Support
|
|
@ -0,0 +1,6 @@
|
|||
.banner
|
||||
p.text-body This cheat sheet is provisional and may change. Angular 2 is currently in Beta.
|
||||
|
||||
article(class="l-content-small grid-fluid docs-content")
|
||||
.cheatsheet
|
||||
ngio-cheatsheet(src='./guide/cheatsheet.json')
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
a(id="top")
|
||||
:marked
|
||||
There are many conceptual and syntactical differences between Angular 1 and Angular 2.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
<a id="top"></a>
|
||||
:marked
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
# Angular 2 Cookbook
|
||||
|
|
|
@ -2,15 +2,12 @@
|
|||
"_listtype": "ordered",
|
||||
|
||||
"index": {
|
||||
"title": "Developer Guides"
|
||||
},
|
||||
|
||||
"cheatsheet": {
|
||||
"title": "Angular Cheat Sheet"
|
||||
"title": "Documentation Overview"
|
||||
},
|
||||
|
||||
"architecture": {
|
||||
"title": "Architecture Overview"
|
||||
"title": "Architecture Overview",
|
||||
"intro": "The basic building blocks of Angular 2 applications"
|
||||
},
|
||||
|
||||
"displaying-data": {
|
||||
|
@ -38,14 +35,14 @@
|
|||
"intro": "Learn how to write templates that display data and consume user events with the help of data binding."
|
||||
},
|
||||
|
||||
"pipes": {
|
||||
"title": "Pipes",
|
||||
"intro": "Pipes transform displayed values within a template."
|
||||
"attribute-directives": {
|
||||
"title": "Attribute Directives",
|
||||
"intro": "Attribute directives attach behavior to elements."
|
||||
},
|
||||
|
||||
"router": {
|
||||
"title": "Routing & Navigation",
|
||||
"intro": "Discover the basics of screen navigation with the Angular 2 router."
|
||||
"hierarchical-dependency-injection": {
|
||||
"title": "Hierarchical Injectors",
|
||||
"intro": "Angular's hierarchical dependency injection system supports nested injectors in parallel with the component tree."
|
||||
},
|
||||
|
||||
"server-communication": {
|
||||
|
@ -57,25 +54,30 @@
|
|||
"title": "Lifecycle Hooks",
|
||||
"intro": "Angular calls lifecycle hook methods on directives and components as it creates, changes, and destroys them."
|
||||
},
|
||||
|
||||
"npm-packages": {
|
||||
"title": "Lifecycle Hooks",
|
||||
"intro": "Details of the recommended npm packages and the different kinds of package dependencies"
|
||||
},
|
||||
|
||||
"pipes": {
|
||||
"title": "Pipes",
|
||||
"intro": "Pipes transform displayed values within a template."
|
||||
},
|
||||
|
||||
"attribute-directives": {
|
||||
"title": "Attribute Directives",
|
||||
"intro": "Attribute directives attach behavior to elements."
|
||||
"router": {
|
||||
"title": "Routing & Navigation",
|
||||
"intro": "Discover the basics of screen navigation with the Angular 2 router."
|
||||
},
|
||||
|
||||
"structural-directives": {
|
||||
"title": "Structural Directives",
|
||||
"intro": "Angular has a powerful template engine that lets us easily manipulate the DOM structure of our elements."
|
||||
},
|
||||
|
||||
"hierarchical-dependency-injection": {
|
||||
"title": "Hierarchical Injectors",
|
||||
"intro": "Angular's hierarchical dependency injection system supports nested injectors in parallel with the component tree."
|
||||
},
|
||||
|
||||
"npm-packages": {
|
||||
"title": "npm packages",
|
||||
"intro": "Details of the recommended npm packages and the different kinds of package dependencies"
|
||||
|
||||
"testing": {
|
||||
"title": "Testing",
|
||||
"intro": "Techniques and practices for testing an Angular 2 app"
|
||||
},
|
||||
|
||||
"upgrade": {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
Angular 2 is a framework to help us build client applications in HTML and JavaScript.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
An **Attribute** directive changes the appearance or behavior of a DOM element.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
:marked
|
||||
**Dependency injection** is an important application design pattern.
|
||||
Angular has its own dependency injection framework, and
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
<!-- http://plnkr.co/edit/x9JYbC -->
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
We’ve all used a form to login, submit a help request, place an order, book a flight,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
// #docregion intro
|
||||
:marked
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
:marked
|
||||
We learned the basics of Angular Dependency injection in the
|
||||
[Dependency Injection](./dependency-injection.html) chapter.
|
||||
|
|
|
@ -1,44 +1,84 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
// #docregion intro
|
||||
- var langName = current.path[1] == 'ts' ? 'TypeScript' : 'JavaScript'
|
||||
figure
|
||||
img(src="/resources/images/devguide/intro/people.png" alt="Us" align="left" style="width:200px; margin-left:-40px;margin-right:10px" )
|
||||
:marked
|
||||
The Developer Guide is a practical guide to Angular for experienced programmers who
|
||||
This is a practical guide to Angular for experienced programmers who
|
||||
are building client applications in HTML and #{langName}.
|
||||
|
||||
We are on a journey together to understand how Angular works and, more importantly,
|
||||
how to make it work for us. This chapter begins the journey.
|
||||
how to make it work for us. This overview begins the journey.
|
||||
<br clear="all">
|
||||
// #enddocregion intro
|
||||
|
||||
// #docregion how-to-read-1
|
||||
<a id="how-to-read"></a>
|
||||
<a id="learning-path"></a>
|
||||
:marked
|
||||
# How to Read this Guide
|
||||
# Organization
|
||||
|
||||
The guide consists of chapters devoted to the challenges of building an application and
|
||||
meeting those challenges with Angular.
|
||||
The documentation is divided into major thematic sections, each
|
||||
a collection of chapters devoted to that theme.
|
||||
// #enddocregion how-to-read-1
|
||||
// #docregion how-to-read-2
|
||||
- var top="vertical-align:top"
|
||||
table(width="100%")
|
||||
col(width="15%")
|
||||
col
|
||||
tr(style=top)
|
||||
td <b>Tutorial</b>
|
||||
td
|
||||
:marked
|
||||
A step-by-step, immersive approach to learning Angular.
|
||||
It begins with the [QuickStart](../quickstart.html),
|
||||
the foundation for every chapter and sample in this documentation,
|
||||
followed by the [*Tour of Heroes* tutorial](../tutorial) that
|
||||
introduces the major features of Angular in an application context.
|
||||
tr(style=top)
|
||||
td <b>Basics</b>
|
||||
td
|
||||
:marked
|
||||
The essential ingredients of Angular development.
|
||||
tr(style=top)
|
||||
td <b>Developer Guide</b>
|
||||
td
|
||||
:marked
|
||||
In depth analysis of Angular features and development practices.
|
||||
tr(style=top)
|
||||
td <b>Cookbook</b>
|
||||
td
|
||||
:marked
|
||||
Recipes for specific application challenges, mostly code snippets with a minimum of exposition.
|
||||
tr(style=top)
|
||||
td <b>Reference</b>
|
||||
td
|
||||
:marked
|
||||
Angular-specific reference material, most notably the [API Guide](../api)
|
||||
with its authoritative details about each member in the Angular libraries.
|
||||
tr(style=top)
|
||||
td <b>Resources</b>
|
||||
td
|
||||
:marked
|
||||
Other places to go for help and information.
|
||||
:marked
|
||||
## Learning Path
|
||||
# Learning Path
|
||||
We don't have to read the guide straight through. Most chapters stand on their own.
|
||||
|
||||
There is a learning path for those of us who are new to Angular.
|
||||
We recommend a learning path for those new to Angular.
|
||||
Most of that path runs throught the *Basics* section:
|
||||
|
||||
1. Read the [Architecture Overview](architecture.html) to get the big picture.
|
||||
|
||||
1. Step *outside* the guide and try the [QuickStart](../quickstart.html). The QuickStart is the "Hello, World" of Angular 2.
|
||||
1. Try the [QuickStart](../quickstart.html). The QuickStart is the "Hello, World" of Angular 2.
|
||||
It shows us how to setup the libraries and tools we'll need to write *any* Angular app.
|
||||
|
||||
1. Follow the [Tutorial](../tutorial). The "Tour of Heroes" tutorial takes us step-by-step from where QuickStart leaves off
|
||||
to a simple data-driven app.
|
||||
1. Take the *Tour of Heroes* [Tutorial](../tutorial) which picks up from where the QuickStart leaves off
|
||||
and builds a simple data-driven app.
|
||||
Simple, yes, but with the essential characteristics we'd expect of a professional application:
|
||||
a sensible project structure, data binding, master/detail, services, dependency injection, navigation, and remote data access.
|
||||
|
||||
Return to the developers guide.
|
||||
Return to the *Basics* section and continue in the suggested order:
|
||||
|
||||
1. [Displaying Data](displaying-data.html) explains how to get information on to the screen.
|
||||
|
||||
|
@ -55,7 +95,7 @@ figure
|
|||
// #enddocregion how-to-read-2
|
||||
// #docregion the-rest
|
||||
:marked
|
||||
## Code Samples
|
||||
# Code Samples
|
||||
|
||||
Every chapter includes code snippets that we can reuse in our own applications.
|
||||
These snippets are excerpts from a sample application that accompanies the chapter.
|
||||
|
@ -70,7 +110,7 @@ figure
|
|||
They highlight key points in code rather than explain each step necessary to build the sample.
|
||||
We can always get the full source by way of the live link.
|
||||
|
||||
## Other Resources
|
||||
## References
|
||||
|
||||
The [Cheat Sheet](cheatsheet.html) lists Angular syntax for common scenarios.
|
||||
|
||||
|
@ -78,7 +118,7 @@ figure
|
|||
|
||||
The [API Guide](../api/) is the authority on every public-facing member of the Angular libraries.
|
||||
|
||||
## Feedback
|
||||
# Feedback
|
||||
|
||||
We welcome feedback! Leave a comment by clicking the icon in upper right corner of the banner.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
# Component Lifecycle
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
Angular applications and Angular itself depend upon features and functionality provided by a variety of third-party packages
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
:marked
|
||||
Every application starts out with what seems like a simple task: get data, transform them, and show them to users.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
The Angular ***Component Router*** enables navigation from one [view](./glossary.html#view) to the next
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
:marked
|
||||
[HTTP](https://tools.ietf.org/html/rfc2616) is the primary protocol for browser/server communication.
|
||||
.l-sub-section
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
One of the defining features of a single page application is its manipulation
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
// #docregion intro
|
||||
:marked
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
:marked
|
||||
We write **unit tests** to explore and confirm the **behavior** of parts of our application.
|
||||
|
||||
1. They **guard** against breaking existing code (“regressions”) when we make changes.
|
||||
1. They **clarify** what the code does both when used as intended and when faced with deviant conditions.
|
||||
1. They **reveal** mistakes in design and implementation. Tests force us to look at our code from many angles. When a part of our application seems hard to test, we may have discovered a design flaw, something we can cure now rather than later when it becomes expensive to fix.
|
||||
|
||||
.alert.is-important
|
||||
:marked
|
||||
These testing chapters were written before the Angular 2 Beta release
|
||||
and are scheduled for significant updates.
|
||||
Much of the material remains accurate and relevant but references to
|
||||
specific features of Angular 2 and the Angular 2 testing library
|
||||
may not be correct. Please bear with us.
|
||||
|
||||
a(id="top")
|
||||
:marked
|
||||
# Table of Contents
|
||||
|
||||
1. [Jasmine Testing 101](#jasmine-101)
|
||||
- setup to run Jasmine tests in the browser
|
||||
- basic Jasmine testing skills
|
||||
- write simple Jasmine tests in TypeScript
|
||||
- debug a test in the browser
|
||||
|
||||
1. [The Application Under Test](#aut)
|
||||
|
||||
1. [Test a class](#first-app-tests)
|
||||
- test a simple application class outside of Angular
|
||||
- where to put the test file
|
||||
- load a test file with systemJS
|
||||
|
||||
1. [Test a Pipe](#pipe-testing)
|
||||
- test a simple Angular Pipe class
|
||||
- add the Angular 2 library to the test harness
|
||||
- load multiple test files using system.js
|
||||
|
||||
1. Test an Asynchronous Service (forthcoming)
|
||||
- test an asynchronous service class outside of Angular
|
||||
- write a test plan in code
|
||||
- fake a dependency
|
||||
- master the `catch(fail).then(done)` pattern
|
||||
- move setup to `beforeEach`
|
||||
- test when a dependency fails
|
||||
- control async test timeout
|
||||
|
||||
1. The Angular Test Environment (forthcoming)
|
||||
- the Angular test environment and why we need help
|
||||
- add the Angular Test libraries to the test harness
|
||||
- test the same async service using Angular Dependency Injection
|
||||
- reduce friction with test helpers
|
||||
- introducing spies
|
||||
|
||||
1. Test a Component (forthcoming)
|
||||
- test the component outside of Angular
|
||||
- mock the dependent asynchronous service
|
||||
- simulate interaction with the view (no DOM)
|
||||
- use a spy-promise to control asynchronous test flow
|
||||
|
||||
1. Test a Component in the DOM (forthcoming
|
||||
- test the component inside the Angular test environment
|
||||
- use the `TestComponentBuilder`
|
||||
- more test helpers
|
||||
- interact with the DOM
|
||||
- bind to a mock dependent asynchronous service
|
||||
|
||||
1. Run the tests with karma (forthcoming)
|
||||
|
||||
It’s a big agenda. Fortunately, you can learn a little bit at a time and put each lesson to use.
|
||||
|
||||
a(href="#top").to-top Back to top
|
||||
|
||||
.l-hr
|
||||
a(id="jasmine-101")
|
||||
:marked
|
||||
# Jasmine Testing 101
|
||||
!= partial("../testing/jasmine-testing-101")
|
||||
a(href="#top").to-top Back to top
|
||||
|
||||
.l-hr
|
||||
a(id="aut")
|
||||
:marked
|
||||
# The Application to Test
|
||||
!= partial("../testing/application-under-test")
|
||||
a(href="#top").to-top Back to top
|
||||
|
||||
.l-hr
|
||||
a(id="first-app-tests")
|
||||
:marked
|
||||
# Testing a Class
|
||||
!= partial("../testing/first-app-tests")
|
||||
a(href="#top").to-top Back to top
|
||||
|
||||
.l-hr
|
||||
a(id="pipe-testing")
|
||||
:marked
|
||||
# Testing an Angular Pipe
|
||||
!= partial("../testing/testing-an-angular-pipe")
|
||||
a(href="#top").to-top Back to top
|
||||
|
||||
.alert.is-important
|
||||
:marked
|
||||
The testing chapter is still under development.
|
||||
Please bear with us as we both update and complete it.
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
TypeScript is a primary language for Angular application development.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
Having an existing Angular 1 application doesn't mean that we can't
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
When the user clicks a link, pushes a button, or enters text
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../_includes/_util-fns
|
||||
include _util-fns
|
||||
|
||||
:marked
|
||||
Our QuickStart goal is to build and run a super-simple Angular 2 application in TypeScript.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"_listtype": "ordered",
|
||||
|
||||
"index": {
|
||||
"title": "Testing Guides",
|
||||
"title": "Testing Overview",
|
||||
"intro": "Techniques and practices for testing an Angular 2 app"
|
||||
},
|
||||
|
||||
|
|
|
@ -1,38 +1,33 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
We’ll need an Angular application to test, one as simple as possible while having all the angular features we want to test.
|
||||
We’ll need an Angular application to test, one as simple as possible while having all the angular features we want to test.
|
||||
|
||||
<!-- TODO We have such an app that you can download [here](./#). -->It’s a one-screen variation on the “Tour of Heroes” that should be familiar to you as a reader of this Developers Guide.
|
||||
<!-- TODO We have such an app that you can download [here](./#). -->It’s a one-screen variation on the “Tour of Heroes” that should be familiar to you as a reader of this Developers Guide.
|
||||
|
||||
Our test app displays a list of heroes - all favorites of the user named “Bongo”. It looks like this:
|
||||
Our test app displays a list of heroes - all favorites of the user named “Bongo”. It looks like this:
|
||||
|
||||
figure.image-display
|
||||
img(src='/resources/images/devguide/application-under-test/bongos-heroes.png'
|
||||
style="width:400px;" alt="Bongo's Heroes")
|
||||
img(src='/resources/images/devguide/application-under-test/bongos-heroes.png'
|
||||
style="width:250px;" alt="Bongo's Heroes")
|
||||
|
||||
:marked
|
||||
At the top is a master list of heroes; at the bottom the detail for the current hero. Click a hero in the list to change the current hero. Change the name in the textbox and that name updates everywhere. The *Update* button modifies the `Hero.name` in an arbitrary way and that change also propagates everywhere on screen. The *Delete* button deletes the hero from the list and a new hero becomes current. *Refresh* clears both the list and detail, then restores the original list of heroes.
|
||||
At the top is a master list of heroes; at the bottom the detail for the current hero. Click a hero in the list to change the current hero. Change the name in the textbox and that name updates everywhere. The *Update* button modifies the `Hero.name` in an arbitrary way and that change also propagates everywhere on screen. The *Delete* button deletes the hero from the list and a new hero becomes current. *Refresh* clears both the list and detail, then restores the original list of heroes.
|
||||
|
||||
<!-- TODO You can see a short video of the app in action [here](./#) -->
|
||||
<!-- TODO You can see a short video of the app in action [here](./#) -->
|
||||
|
||||
This simple app illustrates a number of Angular features that we’d like to test.
|
||||
This simple app illustrates a number of Angular features that we’d like to test.
|
||||
|
||||
- A simple service that presents the `username` (“Bongo”)
|
||||
- A dataservice that fetches and caches the list of heroes.
|
||||
- The dataservice depends in turn on another “backend” service that handles the interaction with a remote web api
|
||||
- A master `HeroesComponent` presents the list
|
||||
- The master communicates with a detail component `HeroDetailComponent` about the current hero both through an attribute and an event.
|
||||
- The detail’s template is nested within the master component’s template.
|
||||
- The `name` textbox illustrates two-way databinding
|
||||
- The update button demonstrates that a programmatic change to the databound model propagates to both component views
|
||||
- The delete button triggers an event that is caught by the parent component
|
||||
<!-- TODO - [TBD: need to add a filter and a directive to this sample] -->
|
||||
<!-- TODO - [TBD: need to shoehorn the router in somehow] -->
|
||||
- A simple service that presents the `username` (“Bongo”)
|
||||
- A dataservice that fetches and caches the list of heroes.
|
||||
- The dataservice depends in turn on another “backend” service that handles the interaction with a remote web api
|
||||
- A master `HeroesComponent` presents the list
|
||||
- The master communicates with a detail component `HeroDetailComponent` about the current hero both through an attribute and an event.
|
||||
- The detail’s template is nested within the master component’s template.
|
||||
- The `name` textbox illustrates two-way databinding
|
||||
- The update button demonstrates that a programmatic change to the databound model propagates to both component views
|
||||
- The delete button triggers an event that is caught by the parent component
|
||||
<!-- TODO - [TBD: need to add a filter and a directive to this sample] -->
|
||||
<!-- TODO - [TBD: need to shoehorn the router in somehow] -->
|
||||
|
||||
We’ll examine the implementation details as we evolve our tests.
|
||||
|
||||
.l-main-section
|
||||
:marked
|
||||
## What’s Next?
|
||||
Now that we’re familiar with how the test app works, we’re ready to poke at it with our [first application tests](first-app-tests.html) written in Jasmine.
|
||||
We’ll examine the implementation details as we evolve our tests.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
In this chapter we'll setup the environment for testing our sample application and write a few easy Jasmine tests of the app's simplest parts.
|
||||
|
@ -175,7 +175,10 @@ figure.image-display
|
|||
|
||||
We can't think of a downside. The server doesn't care where they are. They are easy to find and distinguish from application files when named conventionally.
|
||||
|
||||
You may put your tests elsewhere if you wish. We're putting ours inside the app, next to the source files that they test.
|
||||
.l-sub-section
|
||||
:marked
|
||||
You may put your tests elsewhere if you wish.
|
||||
We're putting ours inside the app, next to the source files that they test.
|
||||
|
||||
.l-main-section
|
||||
:marked
|
||||
|
@ -331,6 +334,6 @@ figure.image-display
|
|||
We are able to test a part of our application with simple Jasmine tests.
|
||||
The part was a stand-alone class that made no mention or use of Angular.
|
||||
|
||||
That's not rare but it's not typical either. Most of our application parts make some use of the Angular framework.
|
||||
|
||||
In the [next chapter](testing-an-angular-pipe.html), we'll test a class that does rely on Angular.
|
||||
That's not rare but it's not typical either.
|
||||
Most of our application parts make some use of the Angular framework.
|
||||
Let's test a *pipe* class that does rely on Angular.
|
||||
|
|
|
@ -1,82 +1,18 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
|
||||
:marked
|
||||
We write **unit tests** to explore and confirm the **behavior** of parts of our application.
|
||||
|
||||
We like *having* unit tests for many reasons, three of them in particular:
|
||||
|
||||
1. They **guard** against breaking existing code (“regressions”) when we make changes.
|
||||
1. They **clarify** what the code does both when used as intended and when faced with deviant conditions.
|
||||
1. They **reveal** mistakes in design and implementation. Tests force us to look at our code from many angles. When a part of our application seems hard to test, we may have discovered a design flaw, something we can cure now rather than later when it becomes expensive to fix.
|
||||
|
||||
While we like *having* tests, we don’t always like *making* tests. It’s a bit like the difference between *having* money (yeah!) and *making* money (oof!).
|
||||
|
||||
Our lofty goal in this chapter is make it easy for you to write Angular application tests. If that goal exceeds our reach, we can at least make testing *easier*… and easy enough that you’ll want to write tests for your application.
|
||||
|
||||
.alert.is-important
|
||||
:marked
|
||||
## Content out-of-date
|
||||
|
||||
These testing chapters were written before the Angular 2 Beta release
|
||||
and are scheduled for significant updates.
|
||||
|
||||
Much of the material remains accurate and relevant but references to
|
||||
specific features of Angular 2 and the Angular 2 testing library
|
||||
may not be correct. Please bear with us.
|
||||
:marked
|
||||
## The Testing Spectrum
|
||||
|
||||
Exploring behavior with tests is called “Functional Testing”. There are other important forms of testing too such as acceptance, security, performance, and deployment testing. We concentrate on functional testing in this section on unit testing.
|
||||
|
||||
There is considerable variety within functional testing, a spectrum from short, quick pure unit tests to long running end-to-end tests. We could classify them in broad groups
|
||||
|
||||
figure.image-display
|
||||
img(src='/resources/images/devguide/unit-testing/spectrum.png' alt="Functional Testing Spectrum")
|
||||
|
||||
:marked
|
||||
<table style="box-shadow: none">
|
||||
<tr>
|
||||
<td style="border-bottom: none">Pure unit test</td>
|
||||
<td style="border-bottom: none; width: 80%">We test the part in isolation. Either the part has no dependencies or we fake all of its dependencies during the test.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border-bottom: none">Close-in integration</td>
|
||||
<td style="border-bottom: none">We test a part as it collaborates with closely related parts and/or with the Angular framework. We may fake some of its dependencies.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border-bottom: none">High level integration</td>
|
||||
<td style="border-bottom: none">We test a part as it interacts with many, wide-ranging aspects of the system including the browser DOM. Such tests are often asynchronous which means the test runner must pause until the entire tested sequence completes.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border-bottom: none">Cross network integration</td>
|
||||
<td style="border-bottom: none">A more demanding “high level integration” test that reaches across the network boundary to touch a test server such as tests of a data service that exercise both client and server components.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border-bottom: none">End-to-End (E2E)</td>
|
||||
<td style="border-bottom: none">We simulate the actions of users as they navigate through the application. Such tests strive to investigate the behavior of the application as a whole, replicating the user experience as faithfully as possible.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Each kind of test has its strengths and weaknesses. The tests to the left are typically easier to write, more focused, more robust, and they often run faster than the tests to the right. It’s much easier to create adverse, stressful conditions for a pure unit test than an end-to-end test. We get a lot of value for comparatively little effort. That may be why we will write a lot more unit tests than end-to-end tests.
|
||||
|
||||
On the other hand, the shorter tests can’t reveal the integration problems that may be hiding at the boundaries within the actual application. We can *simulate* problems that we *imagine* might arise. But we will miss the problems in the real system that we didn’t anticipate.
|
||||
|
||||
We need the full spectrum of tests to assure the behavioral quality of the entire application.
|
||||
|
||||
In this Unit Testing section we learn to write tests in all of these categories *except end-to-end*. We cover **end-to-end** tests in a separate section because they require special tools and considerations.
|
||||
|
||||
We’ll begin on the left side of the spectrum, with pure unit tests of simple parts such as the `Hero` model class and a custom pipe named `InitCapsPipe`. Then we work our way to the right as we explore the more complex parts of our application such as components, the router, and remote data access.
|
||||
|
||||
We’ll learn a number of tips and tricks along the way, including:
|
||||
* what’s worth testing and what isn’t
|
||||
* when a test is telling us to rethink our design
|
||||
* how to debug our tests
|
||||
* how to write asynchronous tests
|
||||
* when to mock and how
|
||||
|
||||
## Unit Testing Chapters
|
||||
<!-- TODO This toc feels out of place here -->
|
||||
|
||||
Here is what we’ll learn in the unit testing chapters.
|
||||
|
||||
1. Jasmine Testing 101
|
||||
|
@ -85,6 +21,7 @@ figure.image-display
|
|||
- write simple Jasmine tests in TypeScript
|
||||
- debug a test in the browser
|
||||
1. The Application Under Test
|
||||
|
||||
1. Test a class
|
||||
- test a simple application class outside of Angular
|
||||
- where to put the test file
|
||||
|
@ -121,15 +58,3 @@ figure.image-display
|
|||
1. Run the tests with karma
|
||||
|
||||
It’s a big agenda. Fortunately, you can learn a little bit at a time and put each lesson to use.
|
||||
|
||||
.callout.is-helpful
|
||||
header How to Use This Guide
|
||||
:marked
|
||||
The Unit Testing chapters build upon each other. We recommend reading them in order.
|
||||
We're also assuming that you're already comfortable with basic Angular 2 concepts and the tools
|
||||
we introduced in the [QuickStart](../quickstart.html) and
|
||||
the [Tour of Heroes](../tutorial/) tutorial
|
||||
such as <code>npm</code>, <code>gulp</code>, and <code>live-server</code>.
|
||||
|
||||
:marked
|
||||
[Let’s get started!](jasmine-testing-101.html)
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
We’ll write our tests with the [Jasmine test framework](http://jasmine.github.io/2.3/introduction.html).
|
||||
|
@ -222,6 +222,8 @@ figure.image-display
|
|||
Fix the test (restore the `.not`); the browser should refresh automatically and all tests pass.
|
||||
|
||||
Congratulations … you’ve completed Jasmine testing 101.
|
||||
|
||||
Now that we’re familiar with Jasmine on its own, we’re ready to test an application.
|
||||
|
||||
<!-- TODO
|
||||
.l-main-section
|
||||
|
@ -230,10 +232,3 @@ figure.image-display
|
|||
Learn more about basic Jasmine testing here
|
||||
[Resources TBD](./#)
|
||||
-->
|
||||
|
||||
.l-main-section
|
||||
:marked
|
||||
## What’s Next?
|
||||
Now that we’re familiar with Jasmine on its own, we’re ready to test an application.
|
||||
|
||||
What application? We introduce you to it in the [next chapter](application-under-test.html).
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
We’ll test an Angular pipe in this chapter
|
||||
|
@ -159,5 +159,5 @@ figure.image-display
|
|||
|
||||
What about testing parts that *are themselves asynchronous*?
|
||||
|
||||
In the next chapter we’ll test a service with a public asynchronous method that fetches heroes
|
||||
Let's test a service with a public asynchronous method that fetches heroes
|
||||
from a remote server.
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
# Tour of Heroes: the vision
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
# Once Upon a Time
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
# It Takes Many Heroes
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
Our app is growing.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
# Services
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
# Routing Around the App
|
||||
|
|
|
@ -51,6 +51,12 @@
|
|||
* Page & Element Specific Layouts
|
||||
*
|
||||
*/
|
||||
.l-hr {
|
||||
margin: 0 ($unit * 0.5) ($unit * 5);
|
||||
padding: ($unit * 2) 0;
|
||||
border-bottom: 1px solid $fog;
|
||||
color: $heather;
|
||||
}
|
||||
|
||||
.l-offset-nav {
|
||||
padding-top: 56px;
|
||||
|
@ -251,4 +257,9 @@ button.verbose.on {display: none}
|
|||
/*
|
||||
* Other
|
||||
*/
|
||||
.to-top {margin-top: $unit * 8; display: block;}
|
||||
.to-top {
|
||||
display: block;
|
||||
font-size: $unit * 2;
|
||||
margin-bottom: $unit;
|
||||
margin-top: $unit * 4;
|
||||
}
|
||||
|
|
|
@ -28,12 +28,14 @@
|
|||
height: $unit * 6;
|
||||
border-bottom: 1px solid $fog;
|
||||
position: relative;
|
||||
height: auto; /* flat nav asked for it. why? */
|
||||
|
||||
@media handheld and (max-width: $phone-breakpoint),
|
||||
screen and (max-device-width: $phone-breakpoint),
|
||||
screen and (max-width: $tablet-breakpoint) {
|
||||
border-bottom: none;
|
||||
padding-right: $unit * 14;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
input {
|
||||
|
@ -50,8 +52,8 @@
|
|||
|
||||
.mobile-trigger {
|
||||
position: absolute;
|
||||
top: $unit;
|
||||
right: $unit;
|
||||
top: 0;
|
||||
right: $unit * 0.2;
|
||||
border: none;
|
||||
background: darken($tin, 5%);
|
||||
color: $snow;
|
||||
|
@ -130,92 +132,122 @@
|
|||
}
|
||||
|
||||
|
||||
// SECONDARY SIDENAV BUTTON
|
||||
// SECONDARY SIDENAV
|
||||
.side-nav-secondary {
|
||||
@extend .side-nav-primary;
|
||||
background: $fog;
|
||||
background: $mist;
|
||||
box-shadow: inset 0px 2px 2px rgba($coal, .24);
|
||||
|
||||
@media handheld and (max-width: $phone-breakpoint),
|
||||
screen and (max-device-width: $phone-breakpoint),
|
||||
screen and (max-width: $tablet-breakpoint) {
|
||||
display: none;
|
||||
max-height: ($phone-breakpoint * 0.60);
|
||||
}
|
||||
|
||||
&.is-ordered {
|
||||
|
||||
> li {
|
||||
line-height: 40px;
|
||||
vertical-align: top;
|
||||
|
||||
> a {
|
||||
padding: 0px ($unit * 2) 0px ($unit * 3);
|
||||
text-transform: none;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> li {
|
||||
border-bottom: none;
|
||||
|
||||
&.is-selected {
|
||||
> a {
|
||||
background: transparent;
|
||||
color: $regal;
|
||||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
line-height: ($unit * 5) - 1;
|
||||
padding: 0px ($unit * 2) 0px ($unit * 4);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.side-nav-icon {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 16px;
|
||||
z-index: $layer-1;
|
||||
font-size: 19px;
|
||||
color: $cloud;
|
||||
line-height: 47px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SECONDARY SIDENAV BUTTON
|
||||
.side-nav-tertiary {
|
||||
padding-bottom: ($unit * 1);
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
|
||||
> li {
|
||||
margin: 0px;
|
||||
|
||||
&.is-selected {
|
||||
> a {
|
||||
background: darken($fog, 3%);
|
||||
color: $blueberry;
|
||||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
line-height: ($unit * 3) - 1;
|
||||
font-size: 13px;
|
||||
text-transform: none;
|
||||
text-align: left;
|
||||
margin: 0px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
|
||||
// FLAT NAV (.nav)
|
||||
.nav-blocks {
|
||||
margin: 0 ($unit * 1.5);
|
||||
padding: ($unit * 2) 0;
|
||||
border-bottom: 1px solid $fog;
|
||||
color: $heather;
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
font-weight: 400;
|
||||
padding: 0px $unit 0px ($unit * 7);
|
||||
line-height: 34px;
|
||||
color: $metal;
|
||||
display: block;
|
||||
}
|
||||
|
||||
ol {
|
||||
padding-left: ($unit * 2);
|
||||
margin: 0
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0
|
||||
}
|
||||
|
||||
div, li {
|
||||
&.is-selected {
|
||||
> a {
|
||||
background: white;
|
||||
color: $regal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
min-height: ($unit * 2);
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-blocks:last-child {
|
||||
border: none
|
||||
}
|
||||
|
||||
.nav-title,
|
||||
.nav-sub-title {
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: ($unit * 2);
|
||||
padding: ($unit * 0.5) 0 ($unit * 1) 0;
|
||||
}
|
||||
|
||||
.nav-primary-link {
|
||||
margin-bottom: ($unit * 1);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-sub-title {
|
||||
font-size: ($unit * 1.5);
|
||||
padding: ($unit * 1) 0;
|
||||
}
|
||||
|
||||
.nav-active a {
|
||||
color: $regal;
|
||||
background: $lightgrey;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nav-ordered-lists li a,
|
||||
.nav-unordered-lists li a,
|
||||
.nav-primary-link a {
|
||||
margin-left: ($unit * -3);
|
||||
padding-left: ($unit * 3);
|
||||
padding-top: ($unit * 0.5);
|
||||
padding-bottom: ($unit * 0.5);
|
||||
}
|
||||
|
||||
.nav-blocks li a:hover,
|
||||
.nav-primary-link a:hover {
|
||||
background: $fog;
|
||||
}
|
||||
|
||||
.nav-primary-link a:hover {
|
||||
padding-top: ($unit * 0.5);
|
||||
padding-bottom: ($unit * 0.5);
|
||||
}
|
||||
|
||||
.nav-blocks li a:hover:before,
|
||||
.nav-primary-link a:hover:before {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 0.4em;
|
||||
height: 0.4em;
|
||||
border-right: 0.2em solid $tin;
|
||||
border-top: 0.2em solid $tin;
|
||||
transform: rotate(45deg);
|
||||
right: -5px;
|
||||
margin-top: -3px;
|
||||
margin-right: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue