Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
15090a8ad4 | |||
8575e3f71c | |||
90b0713e32 | |||
d56b7ed96d | |||
db5e5067a0 | |||
0020dad595 | |||
c2d31fb01e | |||
65d49d5c94 | |||
3a99af2696 | |||
503fd1fbaf | |||
4c74dba2f3 | |||
33df13ad65 | |||
ce18c68eca | |||
2d5623911a | |||
a0b30e5dfb | |||
76a920651c | |||
ef6609a723 | |||
c0dcb342f3 | |||
8a9a5ecdd7 | |||
12c5ead39c | |||
3db6b6ca7a | |||
e894f5c399 | |||
8524187869 | |||
f7422a9607 | |||
cf0a9e0730 | |||
8e5beb024f | |||
576d6d8f86 |
12
CHANGELOG.md
12
CHANGELOG.md
@ -1,3 +1,15 @@
|
|||||||
|
<a name="4.2.1"></a>
|
||||||
|
## [4.2.1](https://github.com/angular/angular/compare/4.2.0-rc.2...4.2.1) (2017-06-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
|
||||||
|
* **compiler:** don’t write summaries for jit by default ([d3a5f1a](https://github.com/angular/angular/commit/d3a5f1a))
|
||||||
|
* **http:** move destructuring inside {Request,Response}Options ctor ([c2d31fb](https://github.com/angular/angular/commit/c2d31fb)), closes [#16663](https://github.com/angular/angular/issues/16663)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="4.2.0"></a>
|
<a name="4.2.0"></a>
|
||||||
# [4.2.0](https://github.com/angular/angular/compare/4.2.0-rc.2...4.2.0) salubrious-stratagem (2017-06-08)
|
# [4.2.0](https://github.com/angular/angular/compare/4.2.0-rc.2...4.2.0) salubrious-stratagem (2017-06-08)
|
||||||
|
|
||||||
|
3
aio/content/examples/.gitignore
vendored
3
aio/content/examples/.gitignore
vendored
@ -52,6 +52,9 @@ dist/
|
|||||||
!aot/index.html
|
!aot/index.html
|
||||||
!rollup-config.js
|
!rollup-config.js
|
||||||
|
|
||||||
|
# i18n
|
||||||
|
!i18n/src/systemjs-text-plugin.js
|
||||||
|
|
||||||
# testing
|
# testing
|
||||||
!testing/src/browser-test-shim.js
|
!testing/src/browser-test-shim.js
|
||||||
!testing/karma*.js
|
!testing/karma*.js
|
||||||
|
1
aio/content/examples/animations/.gitignore
vendored
1
aio/content/examples/animations/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
**/*.js
|
|
@ -44,7 +44,7 @@ import { Heroes } from './hero.service';
|
|||||||
animate('0.2s ease-in')
|
animate('0.2s ease-in')
|
||||||
]),
|
]),
|
||||||
transition('* => void', [
|
transition('* => void', [
|
||||||
animate('0.2s 10 ease-out', style({
|
animate('0.2s 10s ease-out', style({
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
transform: 'translateX(100%)'
|
transform: 'translateX(100%)'
|
||||||
}))
|
}))
|
||||||
|
7
aio/content/examples/aot-compiler/.gitignore
vendored
7
aio/content/examples/aot-compiler/.gitignore
vendored
@ -1,7 +0,0 @@
|
|||||||
**/*.ngfactory.ts
|
|
||||||
**/*.ngsummary.json
|
|
||||||
**/*.shim.ngstyle.ts
|
|
||||||
**/*.metadata.json
|
|
||||||
dist
|
|
||||||
!app/tsconfig.json
|
|
||||||
!rollup-config.js
|
|
45
aio/content/examples/cli-quickstart/.gitignore
vendored
45
aio/content/examples/cli-quickstart/.gitignore
vendored
@ -1,45 +0,0 @@
|
|||||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
|
||||||
|
|
||||||
# compiled output
|
|
||||||
/dist
|
|
||||||
/tmp
|
|
||||||
|
|
||||||
# dependencies
|
|
||||||
/node_modules
|
|
||||||
|
|
||||||
# IDEs and editors
|
|
||||||
/.idea
|
|
||||||
.project
|
|
||||||
.classpath
|
|
||||||
.c9/
|
|
||||||
*.launch
|
|
||||||
.settings/
|
|
||||||
*.sublime-workspace
|
|
||||||
|
|
||||||
# IDE - VSCode
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/settings.json
|
|
||||||
!.vscode/tasks.json
|
|
||||||
!.vscode/launch.json
|
|
||||||
!.vscode/extensions.json
|
|
||||||
|
|
||||||
# misc
|
|
||||||
/.sass-cache
|
|
||||||
/connect.lock
|
|
||||||
/coverage/*
|
|
||||||
/libpeerconnection.log
|
|
||||||
npm-debug.log
|
|
||||||
testem.log
|
|
||||||
/typings
|
|
||||||
|
|
||||||
# e2e
|
|
||||||
/e2e/*.js
|
|
||||||
/e2e/*.map
|
|
||||||
|
|
||||||
#System Files
|
|
||||||
.DS_Store
|
|
||||||
Thumbs.db
|
|
||||||
|
|
||||||
!src/styles.css
|
|
||||||
!karma.conf.js
|
|
||||||
!protractor.conf.js
|
|
@ -1,116 +0,0 @@
|
|||||||
/* #docregion , quickstart, toh */
|
|
||||||
/* Master Styles */
|
|
||||||
h1 {
|
|
||||||
color: #369;
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
font-size: 250%;
|
|
||||||
}
|
|
||||||
h2, h3 {
|
|
||||||
color: #444;
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
font-weight: lighter;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
margin: 2em;
|
|
||||||
}
|
|
||||||
/* #enddocregion quickstart */
|
|
||||||
body, input[text], button {
|
|
||||||
color: #888;
|
|
||||||
font-family: Cambria, Georgia;
|
|
||||||
}
|
|
||||||
/* #enddocregion toh */
|
|
||||||
a {
|
|
||||||
cursor: pointer;
|
|
||||||
cursor: hand;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
font-family: Arial;
|
|
||||||
background-color: #eee;
|
|
||||||
border: none;
|
|
||||||
padding: 5px 10px;
|
|
||||||
border-radius: 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
cursor: hand;
|
|
||||||
}
|
|
||||||
button:hover {
|
|
||||||
background-color: #cfd8dc;
|
|
||||||
}
|
|
||||||
button:disabled {
|
|
||||||
background-color: #eee;
|
|
||||||
color: #aaa;
|
|
||||||
cursor: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Navigation link styles */
|
|
||||||
nav a {
|
|
||||||
padding: 5px 10px;
|
|
||||||
text-decoration: none;
|
|
||||||
margin-right: 10px;
|
|
||||||
margin-top: 10px;
|
|
||||||
display: inline-block;
|
|
||||||
background-color: #eee;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
nav a:visited, a:link {
|
|
||||||
color: #607D8B;
|
|
||||||
}
|
|
||||||
nav a:hover {
|
|
||||||
color: #039be5;
|
|
||||||
background-color: #CFD8DC;
|
|
||||||
}
|
|
||||||
nav a.active {
|
|
||||||
color: #039be5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* items class */
|
|
||||||
.items {
|
|
||||||
margin: 0 0 2em 0;
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0;
|
|
||||||
width: 24em;
|
|
||||||
}
|
|
||||||
.items li {
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
left: 0;
|
|
||||||
background-color: #EEE;
|
|
||||||
margin: .5em;
|
|
||||||
padding: .3em 0;
|
|
||||||
height: 1.6em;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
.items li:hover {
|
|
||||||
color: #607D8B;
|
|
||||||
background-color: #DDD;
|
|
||||||
left: .1em;
|
|
||||||
}
|
|
||||||
.items li.selected {
|
|
||||||
background-color: #CFD8DC;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
.items li.selected:hover {
|
|
||||||
background-color: #BBD8DC;
|
|
||||||
}
|
|
||||||
.items .text {
|
|
||||||
position: relative;
|
|
||||||
top: -3px;
|
|
||||||
}
|
|
||||||
.items .badge {
|
|
||||||
display: inline-block;
|
|
||||||
font-size: small;
|
|
||||||
color: white;
|
|
||||||
padding: 0.8em 0.7em 0 0.7em;
|
|
||||||
background-color: #607D8B;
|
|
||||||
line-height: 1em;
|
|
||||||
position: relative;
|
|
||||||
left: -1px;
|
|
||||||
top: -4px;
|
|
||||||
height: 1.8em;
|
|
||||||
margin-right: .8em;
|
|
||||||
border-radius: 4px 0 0 4px;
|
|
||||||
}
|
|
||||||
/* #docregion toh */
|
|
||||||
/* everywhere else */
|
|
||||||
* {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
**/*.js
|
|
1
aio/content/examples/deployment/.gitignore
vendored
1
aio/content/examples/deployment/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
!systemjs.config.server.js
|
|
6
aio/content/examples/i18n/.gitignore
vendored
6
aio/content/examples/i18n/.gitignore
vendored
@ -1,6 +0,0 @@
|
|||||||
**/*.ngfactory.ts
|
|
||||||
**/*.metadata.json
|
|
||||||
dist
|
|
||||||
!app/tsconfig.json
|
|
||||||
!rollup.js
|
|
||||||
!src/systemjs-text-plugin.js
|
|
47
aio/content/examples/router/src/app.css
Normal file
47
aio/content/examples/router/src/app.css
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* items class */
|
||||||
|
.items {
|
||||||
|
margin: 0 0 2em 0;
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
width: 24em;
|
||||||
|
}
|
||||||
|
.items li {
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
left: 0;
|
||||||
|
background-color: #EEE;
|
||||||
|
margin: .5em;
|
||||||
|
padding: .3em 0;
|
||||||
|
height: 1.6em;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.items li:hover {
|
||||||
|
color: #607D8B;
|
||||||
|
background-color: #DDD;
|
||||||
|
left: .1em;
|
||||||
|
}
|
||||||
|
.items li.selected {
|
||||||
|
background-color: #CFD8DC;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.items li.selected:hover {
|
||||||
|
background-color: #BBD8DC;
|
||||||
|
}
|
||||||
|
.items .text {
|
||||||
|
position: relative;
|
||||||
|
top: -3px;
|
||||||
|
}
|
||||||
|
.items .badge {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: small;
|
||||||
|
color: white;
|
||||||
|
padding: 0.8em 0.7em 0 0.7em;
|
||||||
|
background-color: #607D8B;
|
||||||
|
line-height: 1em;
|
||||||
|
position: relative;
|
||||||
|
left: -1px;
|
||||||
|
top: -4px;
|
||||||
|
height: 1.8em;
|
||||||
|
margin-right: .8em;
|
||||||
|
border-radius: 4px 0 0 4px;
|
||||||
|
}
|
@ -10,6 +10,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" href="styles.css">
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
<link rel="stylesheet" href="app.css">
|
||||||
|
|
||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||||
|
2
aio/content/examples/styleguide/.gitignore
vendored
2
aio/content/examples/styleguide/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
*.js
|
|
||||||
!systemjs.custom.js
|
|
1
aio/content/examples/testing/.gitignore
vendored
1
aio/content/examples/testing/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
!src/browser-test-shim.js
|
|
22
aio/content/examples/toh-pt5/src/styles.1.css
Normal file
22
aio/content/examples/toh-pt5/src/styles.1.css
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* Master Styles */
|
||||||
|
h1 {
|
||||||
|
color: #369;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
font-size: 250%;
|
||||||
|
}
|
||||||
|
h2, h3 {
|
||||||
|
color: #444;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
font-weight: lighter;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 2em;
|
||||||
|
}
|
||||||
|
body, input[text], button {
|
||||||
|
color: #888;
|
||||||
|
font-family: Cambria, Georgia;
|
||||||
|
}
|
||||||
|
/* everywhere else */
|
||||||
|
* {
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
}
|
8
aio/content/examples/universal/.gitignore
vendored
8
aio/content/examples/universal/.gitignore
vendored
@ -1,8 +0,0 @@
|
|||||||
aot/**/*.ts
|
|
||||||
**/*.ngfactory.ts
|
|
||||||
**/*.ngsummary.json
|
|
||||||
**/*.metadata.json
|
|
||||||
**/*.js
|
|
||||||
dist
|
|
||||||
!app/tsconfig.json
|
|
||||||
!/*.js
|
|
@ -1 +0,0 @@
|
|||||||
!karma.conf.ajs.js
|
|
@ -1,8 +0,0 @@
|
|||||||
aot/**/*
|
|
||||||
!aot/index.html
|
|
||||||
dist
|
|
||||||
!app/tsconfig.json
|
|
||||||
!rollup-config.js
|
|
||||||
!karma.conf.ajs.js
|
|
||||||
!copy-dist-files.js
|
|
||||||
!systemjs.config.1.js
|
|
@ -1 +0,0 @@
|
|||||||
!tsconfig.json
|
|
5
aio/content/examples/webpack/.gitignore
vendored
5
aio/content/examples/webpack/.gitignore
vendored
@ -1,5 +0,0 @@
|
|||||||
dist
|
|
||||||
!karma.webpack.conf.js
|
|
||||||
!webpack.config.js
|
|
||||||
!config/*
|
|
||||||
!public/css/styles.css
|
|
@ -9,14 +9,14 @@
|
|||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/common": "~4.0.0",
|
"@angular/common": "~4.2.0",
|
||||||
"@angular/compiler": "~4.0.0",
|
"@angular/compiler": "~4.2.0",
|
||||||
"@angular/core": "~4.0.0",
|
"@angular/core": "~4.2.0",
|
||||||
"@angular/forms": "~4.0.0",
|
"@angular/forms": "~4.2.0",
|
||||||
"@angular/http": "~4.0.0",
|
"@angular/http": "~4.2.0",
|
||||||
"@angular/platform-browser": "~4.0.0",
|
"@angular/platform-browser": "~4.2.0",
|
||||||
"@angular/platform-browser-dynamic": "~4.0.0",
|
"@angular/platform-browser-dynamic": "~4.2.0",
|
||||||
"@angular/router": "~4.0.0",
|
"@angular/router": "~4.2.0",
|
||||||
"core-js": "^2.4.1",
|
"core-js": "^2.4.1",
|
||||||
"rxjs": "5.0.1",
|
"rxjs": "5.0.1",
|
||||||
"zone.js": "^0.8.4"
|
"zone.js": "^0.8.4"
|
||||||
|
@ -38,7 +38,7 @@ This page introduces modules; the [Angular modules](guide/ngmodule) page covers
|
|||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
Every Angular app has at least one Angular module class, [the _root module_](guide/appmodule "AppModule: the root module"),
|
Every Angular app has at least one Angular module class, [the _root module_](guide/bootstrapping "AppModule: the root module"),
|
||||||
conventionally named `AppModule`.
|
conventionally named `AppModule`.
|
||||||
|
|
||||||
While the _root module_ may be the only module in a small application, most apps have many more
|
While the _root module_ may be the only module in a small application, most apps have many more
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# AppModule: the root module
|
# Bootstrapping
|
||||||
|
|
||||||
An Angular module class describes how the application parts fit together.
|
An Angular module class describes how the application parts fit together.
|
||||||
Every application has at least one Angular module, the _root_ module
|
Every application has at least one Angular module, the _root_ module
|
||||||
that you [bootstrap](guide/appmodule#main) to launch the application.
|
that you [bootstrap](guide/bootstrapping#main) to launch the application.
|
||||||
You can call it anything you want. The conventional name is `AppModule`.
|
You can call it anything you want. The conventional name is `AppModule`.
|
||||||
|
|
||||||
The [setup](guide/setup) instructions produce a new project with the following minimal `AppModule`.
|
The [setup](guide/setup) instructions produce a new project with the following minimal `AppModule`.
|
||||||
@ -10,7 +10,6 @@ You'll evolve this module as your application grows.
|
|||||||
|
|
||||||
|
|
||||||
<code-example path="setup/src/app/app.module.ts" title="src/app/app.module.ts" linenums="false">
|
<code-example path="setup/src/app/app.module.ts" title="src/app/app.module.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
@ -26,7 +25,7 @@ The `@NgModule` decorator identifies `AppModule` as an Angular module class (als
|
|||||||
* **_bootstrap_** — the _root_ component that Angular creates and inserts into the `index.html` host web page.
|
* **_bootstrap_** — the _root_ component that Angular creates and inserts into the `index.html` host web page.
|
||||||
|
|
||||||
The [Angular Modules (NgModule)](guide/ngmodule) guide dives deeply into the details of Angular modules.
|
The [Angular Modules (NgModule)](guide/ngmodule) guide dives deeply into the details of Angular modules.
|
||||||
All you need to know at the moment is a few basics about these three properties.
|
All you need to know at the moment is a few basics about these three properties.
|
||||||
|
|
||||||
|
|
||||||
{@a imports}
|
{@a imports}
|
||||||
@ -35,7 +34,7 @@ All you need to know at the moment is a few basics about these three properties.
|
|||||||
### The _imports_ array
|
### The _imports_ array
|
||||||
|
|
||||||
Angular modules are a way to consolidate features that belong together into discrete units.
|
Angular modules are a way to consolidate features that belong together into discrete units.
|
||||||
Many features of Angular itself are organized as Angular modules.
|
Many features of Angular itself are organized as Angular modules.
|
||||||
HTTP services are in the `HttpModule`. The router is in the `RouterModule`.
|
HTTP services are in the `HttpModule`. The router is in the `RouterModule`.
|
||||||
Eventually you may create a feature module.
|
Eventually you may create a feature module.
|
||||||
|
|
||||||
@ -67,7 +66,7 @@ are unrelated and have completely different jobs.
|
|||||||
|
|
||||||
The _JavaScript_ `import` statements give you access to symbols _exported_ by other files
|
The _JavaScript_ `import` statements give you access to symbols _exported_ by other files
|
||||||
so you can reference them within _this_ file.
|
so you can reference them within _this_ file.
|
||||||
You add `import` statements to almost every application file.
|
You add `import` statements to almost every application file.
|
||||||
They have nothing to do with Angular and Angular knows nothing about them.
|
They have nothing to do with Angular and Angular knows nothing about them.
|
||||||
|
|
||||||
The _module's_ `imports` array appears _exclusively_ in the `@NgModule` metadata object.
|
The _module's_ `imports` array appears _exclusively_ in the `@NgModule` metadata object.
|
||||||
@ -86,10 +85,10 @@ that the application needs to function properly.
|
|||||||
You tell Angular which components belong to the `AppModule` by listing it in the module's `declarations` array.
|
You tell Angular which components belong to the `AppModule` by listing it in the module's `declarations` array.
|
||||||
As you create more components, you'll add them to `declarations`.
|
As you create more components, you'll add them to `declarations`.
|
||||||
|
|
||||||
You must declare _every_ component in an `NgModule` class.
|
You must declare _every_ component in an `NgModule` class.
|
||||||
If you use a component without declaring it, you'll see a clear error message in the browser console.
|
If you use a component without declaring it, you'll see a clear error message in the browser console.
|
||||||
|
|
||||||
You'll learn to create two other kinds of classes —
|
You'll learn to create two other kinds of classes —
|
||||||
[directives](guide/attribute-directives) and [pipes](guide/pipes) —
|
[directives](guide/attribute-directives) and [pipes](guide/pipes) —
|
||||||
that you must also add to the `declarations` array.
|
that you must also add to the `declarations` array.
|
||||||
|
|
||||||
@ -98,7 +97,7 @@ that you must also add to the `declarations` array.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
**Only _declarables_** — _components_, _directives_ and _pipes_ — belong in the `declarations` array.
|
**Only _declarables_** — _components_, _directives_ and _pipes_ — belong in the `declarations` array.
|
||||||
Do not put any other kind of class in `declarations`; _not_ `NgModule` classes, _not_ service classes, _not_ model classes.
|
Do not put any other kind of class in `declarations`; _not_ `NgModule` classes, _not_ service classes, _not_ model classes.
|
||||||
|
|
||||||
|
|
||||||
@ -111,14 +110,14 @@ Do not put any other kind of class in `declarations`; _not_ `NgModule` classes,
|
|||||||
|
|
||||||
### The _bootstrap_ array
|
### The _bootstrap_ array
|
||||||
|
|
||||||
You launch the application by [_bootstrapping_](guide/appmodule#main) the root `AppModule`.
|
You launch the application by [_bootstrapping_](guide/bootstrapping#main) the root `AppModule`.
|
||||||
Among other things, the _bootstrapping_ process creates the component(s) listed in the `bootstrap` array
|
Among other things, the _bootstrapping_ process creates the component(s) listed in the `bootstrap` array
|
||||||
and inserts each one into the browser DOM.
|
and inserts each one into the browser DOM.
|
||||||
|
|
||||||
Each bootstrapped component is the base of its own tree of components.
|
Each bootstrapped component is the base of its own tree of components.
|
||||||
Inserting a bootstrapped component usually triggers a cascade of component creations that fill out that tree.
|
Inserting a bootstrapped component usually triggers a cascade of component creations that fill out that tree.
|
||||||
|
|
||||||
While you can put more than one component tree on a host web page, that's not typical.
|
While you can put more than one component tree on a host web page, that's not typical.
|
||||||
Most applications have only one component tree and they bootstrap a single _root_ component.
|
Most applications have only one component tree and they bootstrap a single _root_ component.
|
||||||
|
|
||||||
You can call the one _root_ component anything you want but most developers call it `AppComponent`.
|
You can call the one _root_ component anything you want but most developers call it `AppComponent`.
|
||||||
@ -143,7 +142,7 @@ The variations depend upon how you want to compile the application and where you
|
|||||||
In the beginning, you will compile the application dynamically with the _Just-in-Time (JIT)_ compiler
|
In the beginning, you will compile the application dynamically with the _Just-in-Time (JIT)_ compiler
|
||||||
and you'll run it in a browser. You can learn about other options later.
|
and you'll run it in a browser. You can learn about other options later.
|
||||||
|
|
||||||
The recommended place to bootstrap a JIT-compiled browser application is in a separate file
|
The recommended place to bootstrap a JIT-compiled browser application is in a separate file
|
||||||
in the `src` folder named `src/main.ts`
|
in the `src` folder named `src/main.ts`
|
||||||
|
|
||||||
<code-example path="setup/src/main.ts" title="src/main.ts" linenums="false">
|
<code-example path="setup/src/main.ts" title="src/main.ts" linenums="false">
|
||||||
@ -156,10 +155,10 @@ This code creates a browser platform for dynamic (JIT) compilation and
|
|||||||
bootstraps the `AppModule` described above.
|
bootstraps the `AppModule` described above.
|
||||||
|
|
||||||
The _bootstrapping_ process sets up the execution environment,
|
The _bootstrapping_ process sets up the execution environment,
|
||||||
digs the _root_ `AppComponent` out of the module's `bootstrap` array,
|
digs the _root_ `AppComponent` out of the module's `bootstrap` array,
|
||||||
creates an instance of the component and inserts it within the element tag identified by the component's `selector`.
|
creates an instance of the component and inserts it within the element tag identified by the component's `selector`.
|
||||||
|
|
||||||
The `AppComponent` selector — here and in most documentation samples — is `my-app`
|
The `AppComponent` selector — here and in most documentation samples — is `my-app`
|
||||||
so Angular looks for a `<my-app>` tag in the `index.html` like this one ...
|
so Angular looks for a `<my-app>` tag in the `index.html` like this one ...
|
||||||
|
|
||||||
<code-example path="setup/src/index.html" region="my-app" title="setup/src/index.html" linenums="false">
|
<code-example path="setup/src/index.html" region="my-app" title="setup/src/index.html" linenums="false">
|
@ -1,617 +0,0 @@
|
|||||||
# CLI QuickStart
|
|
||||||
|
|
||||||
Good tools make application development quicker and easier to maintain than
|
|
||||||
if you did everything by hand.
|
|
||||||
|
|
||||||
The [**Angular CLI**](https://cli.angular.io/) is a **_command line interface_** tool
|
|
||||||
that can create a project, add files, and perform a variety of ongoing development tasks such
|
|
||||||
as testing, bundling, and deployment.
|
|
||||||
|
|
||||||
The goal in this guide is to build and run a simple Angular
|
|
||||||
application in TypeScript, using the Angular CLI
|
|
||||||
while adhering to the [Style Guide](guide/styleguide) recommendations that
|
|
||||||
benefit _every_ Angular project.
|
|
||||||
|
|
||||||
By the end of the chapter, you'll have a basic understanding of development with the CLI
|
|
||||||
and a foundation for both these documentation samples and for real world applications.
|
|
||||||
|
|
||||||
<!--
|
|
||||||
|
|
||||||
You'll pursue these ends in the following high-level steps:
|
|
||||||
|
|
||||||
1. [Set up](guide/cli-quickstart#devenv) the development environment.
|
|
||||||
2. [Create](guide/cli-quickstart#create-proj) a new project and skeleton application.
|
|
||||||
3. [Serve](guide/cli-quickstart#serve) the application.
|
|
||||||
4. [Edit](guide/cli-quickstart#first-component) the application.
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
And you can also <a href="generated/zips/cli-quickstart/cli-quickstart.zip" target="_blank">download the example.</a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='devenv'>
|
|
||||||
Step 1. Set up the Development Environment
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
You need to set up your development environment before you can do anything.
|
|
||||||
|
|
||||||
Install **[Node.js® and npm](https://nodejs.org/en/download/)**
|
|
||||||
if they are not already on your machine.
|
|
||||||
|
|
||||||
<div class="l-sub-section">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**Verify that you are running at least node `6.9.x` and npm `3.x.x`**
|
|
||||||
by running `node -v` and `npm -v` in a terminal/console window.
|
|
||||||
Older versions produce errors, but newer versions are fine.
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Then **install the [Angular CLI](https://github.com/angular/angular-cli)** globally.
|
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
|
||||||
npm install -g @angular/cli
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='create-proj'>
|
|
||||||
Step 2. Create a new project
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Open a terminal window.
|
|
||||||
|
|
||||||
|
|
||||||
Generate a new project and skeleton application by running the following commands:
|
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
|
||||||
ng new my-app
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="l-sub-section">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Patience please.
|
|
||||||
It takes time to set up a new project, most of it spent installing npm packages.
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='serve'>
|
|
||||||
Step 3: Serve the application
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Go to the project directory and launch the server.
|
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
|
||||||
cd my-app
|
|
||||||
ng serve --open
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
The `ng serve` command launches the server, watches your files,
|
|
||||||
and rebuilds the app as you make changes to those files.
|
|
||||||
|
|
||||||
Using the `--open` (or just `-o`) option will automatically open your browser
|
|
||||||
on `http://localhost:4200/`.
|
|
||||||
|
|
||||||
Your app greets you with a message:
|
|
||||||
|
|
||||||
|
|
||||||
<figure>
|
|
||||||
<img src='generated/images/guide/cli-quickstart/app-works.png' alt="The app works!">
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='first-component'>
|
|
||||||
Step 4: Edit your first Angular component
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
The CLI created the first Angular component for you.
|
|
||||||
This is the _root component_ and it is named `app-root`.
|
|
||||||
You can find it in `./src/app/app.component.ts`.
|
|
||||||
|
|
||||||
|
|
||||||
Open the component file and change the `title` property from _app works!_ to _My First Angular App_:
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cli-quickstart/src/app/app.component.ts" region="title" title="src/app/app.component.ts" linenums="false"></code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
The browser reloads automatically with the revised title. That's nice, but it could look better.
|
|
||||||
|
|
||||||
Open `src/app/app.component.css` and give the component some style.
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cli-quickstart/src/app/app.component.css" title="src/app/app.component.css" linenums="false"></code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<figure>
|
|
||||||
<img src='generated/images/guide/cli-quickstart/my-first-app.png' alt="Output of QuickStart app">
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Looking good!
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## What's next?
|
|
||||||
That's about all you'd expect to do in a "Hello, World" app.
|
|
||||||
|
|
||||||
You're ready to take the [Tour of Heroes Tutorial](tutorial) and build
|
|
||||||
a small application that demonstrates the great things you can build with Angular.
|
|
||||||
|
|
||||||
Or you can stick around a bit longer to learn about the files in your brand new project.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Project file review
|
|
||||||
|
|
||||||
An Angular CLI project is the foundation for both quick experiments and enterprise solutions.
|
|
||||||
|
|
||||||
The first file you should check out is `README.md`.
|
|
||||||
It has some basic information on how to use CLI commands.
|
|
||||||
Whenever you want to know more about how Angular CLI works make sure to visit
|
|
||||||
[the Angular CLI repository](https://github.com/angular/angular-cli) and
|
|
||||||
[Wiki](https://github.com/angular/angular-cli/wiki).
|
|
||||||
|
|
||||||
Some of the generated files might be unfamiliar to you.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### The `src` folder
|
|
||||||
Your app lives in the `src` folder.
|
|
||||||
All Angular components, templates, styles, images, and anything else your app needs go here.
|
|
||||||
Any files outside of this folder are meant to support building your app.
|
|
||||||
|
|
||||||
|
|
||||||
<div class='filetree'>
|
|
||||||
<div class='file'>src</div>
|
|
||||||
<div class='children'>
|
|
||||||
<div class='file'>app</div>
|
|
||||||
<div class='children'>
|
|
||||||
<div class='file'>app.component.css</div>
|
|
||||||
<div class='file'>app.component.html</div>
|
|
||||||
<div class="file">app.component.spec.ts</div>
|
|
||||||
<div class="file">app.component.ts</div>
|
|
||||||
<div class="file">app.module.ts</div>
|
|
||||||
</div>
|
|
||||||
<div class="file">assets</div>
|
|
||||||
<div class='children'>
|
|
||||||
<div class="file">.gitkeep</div>
|
|
||||||
</div>
|
|
||||||
<div class="file">environments</div>
|
|
||||||
<div class='children'>
|
|
||||||
<div class="file">environment.prod.ts</div>
|
|
||||||
<div class="file">environment.ts</div>
|
|
||||||
</div>
|
|
||||||
<div class="file">favicon.ico</div>
|
|
||||||
<div class="file">index.html</div>
|
|
||||||
<div class="file">main.ts</div>
|
|
||||||
<div class="file">polyfills.ts</div>
|
|
||||||
<div class="file">styles.css</div>
|
|
||||||
<div class="file">test.ts</div>
|
|
||||||
<div class="file">tsconfig.app.json</div>
|
|
||||||
<div class="file">tsconfig.spec.json</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
td, th {vertical-align: top}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<table width="100%">
|
|
||||||
<col width="20%">
|
|
||||||
</col>
|
|
||||||
<col width="80%">
|
|
||||||
</col>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
File
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
Purpose
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`app/app.component.{ts,html,css,spec.ts}`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
Defines the `AppComponent` along with an HTML template, CSS stylesheet, and a unit test.
|
|
||||||
It is the **root** component of what will become a tree of nested components
|
|
||||||
as the application evolves.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`app/app.module.ts`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
Defines `AppModule`, the [root module](guide/appmodule "AppModule: the root module") that tells Angular how to assemble the application.
|
|
||||||
Right now it declares only the `AppComponent`.
|
|
||||||
Soon there will be more components to declare.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`assets/*`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
A folder where you can put images and anything else to be copied wholesale
|
|
||||||
when you build your application.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`environments/*`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
This folder contains one file for each of your destination environments,
|
|
||||||
each exporting simple configuration variables to use in your application.
|
|
||||||
The files are replaced on-the-fly when you build your app.
|
|
||||||
You might use a different API endpoint for development than you do for production
|
|
||||||
or maybe different analytics tokens.
|
|
||||||
You might even use some mock services.
|
|
||||||
Either way, the CLI has you covered.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`favicon.ico`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
Every site wants to look good on the bookmark bar.
|
|
||||||
Get started with your very own Angular icon.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`index.html`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
The main HTML page that is served when someone visits your site.
|
|
||||||
Most of the time you'll never need to edit it.
|
|
||||||
The CLI automatically adds all `js` and `css` files when building your app so you
|
|
||||||
never need to add any `<script>` or `<link>` tags here manually.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`main.ts`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
The main entry point for your app.
|
|
||||||
Compiles the application with the [JIT compiler](guide/glossary#jit)
|
|
||||||
and bootstraps the application's root module (`AppModule`) to run in the browser.
|
|
||||||
You can also use the [AOT compiler](guide/glossary#ahead-of-time-aot-compilation)
|
|
||||||
without changing any code by passing in `--aot` to `ng build` or `ng serve`.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`polyfills.ts`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
Different browsers have different levels of support of the web standards.
|
|
||||||
Polyfills help normalize those differences.
|
|
||||||
You should be pretty safe with `core-js` and `zone.js`, but be sure to check out
|
|
||||||
the [Browser Support guide](guide/browser-support) for more information.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`styles.css`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
Your global styles go here.
|
|
||||||
Most of the time you'll want to have local styles in your components for easier maintenance,
|
|
||||||
but styles that affect all of your app need to be in a central place.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`test.ts`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
This is the main entry point for your unit tests.
|
|
||||||
It has some custom configuration that might be unfamiliar, but it's not something you'll
|
|
||||||
need to edit.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`tsconfig.{app|spec}.json`
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
TypeScript compiler configuration for the Angular app (`tsconfig.app.json`)
|
|
||||||
and for the unit tests (`tsconfig.spec.json`).
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
### The root folder
|
|
||||||
|
|
||||||
The `src/` folder is just one of the items inside the project's root folder.
|
|
||||||
Other files help you build, test, maintain, document, and deploy the app.
|
|
||||||
These files go in the root folder next to `src/`.
|
|
||||||
|
|
||||||
|
|
||||||
<div class='filetree'>
|
|
||||||
<div class="file">my-app</div>
|
|
||||||
<div class='children'>
|
|
||||||
<div class="file">e2e</div>
|
|
||||||
<div class='children'>
|
|
||||||
<div class="file">app.e2e-spec.ts</div>
|
|
||||||
<div class="file">app.po.ts</div>
|
|
||||||
<div class="file">tsconfig.e2e.json</div>
|
|
||||||
</div>
|
|
||||||
<div class="file">node_modules/...</div>
|
|
||||||
<div class="file">src/...</div>
|
|
||||||
<div class="file">.angular-cli.json</div>
|
|
||||||
<div class="file">.editorconfig</div>
|
|
||||||
<div class="file">.gitignore</div>
|
|
||||||
<div class="file">karma.conf.js</div>
|
|
||||||
<div class="file">package.json</div>
|
|
||||||
<div class="file">protractor.conf.js</div>
|
|
||||||
<div class="file">README.md</div>
|
|
||||||
<div class="file">tsconfig.json</div>
|
|
||||||
<div class="file">tslint.json</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
td, th {vertical-align: top}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<table width="100%">
|
|
||||||
<col width="20%">
|
|
||||||
</col>
|
|
||||||
<col width="80%">
|
|
||||||
</col>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
File
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
Purpose
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`e2e/`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
Inside `e2e/` live the End-to-End tests.
|
|
||||||
They shouldn't be inside `src/` because e2e tests are really a separate app that
|
|
||||||
just so happens to test your main app.
|
|
||||||
That's also why they have their own `tsconfig.e2e.json`.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`node_modules/`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`Node.js` creates this folder and puts all third party modules listed in
|
|
||||||
`package.json` inside of it.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`.angular-cli.json`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
Configuration for Angular CLI.
|
|
||||||
In this file you can set several defaults and also configure what files are included
|
|
||||||
when your project is build.
|
|
||||||
Check out the official documentation if you want to know more.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`.editorconfig`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
Simple configuration for your editor to make sure everyone that uses your project
|
|
||||||
has the same basic configuration.
|
|
||||||
Most editors support an `.editorconfig` file.
|
|
||||||
See http://editorconfig.org for more information.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`.gitignore`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
Git configuration to make sure autogenerated files are not commited to source control.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`karma.conf.js`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
Unit test configuration for the [Karma test runner](https://karma-runner.github.io),
|
|
||||||
used when running `ng test`.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`package.json`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`npm` configuration listing the third party packages your project uses.
|
|
||||||
You can also add your own [custom scripts](https://docs.npmjs.com/misc/scripts) here.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`protractor.conf.js`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
End-to-end test configuration for [Protractor](http://www.protractortest.org/),
|
|
||||||
used when running `ng e2e`.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`README.md`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
Basic documentation for your project, pre-filled with CLI command information.
|
|
||||||
Make sure to enhance it with project documentation so that anyone
|
|
||||||
checking out the repo can build your app!
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`tsconfig.json`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
TypeScript compiler configuration for your IDE to pick up and give you helpful tooling.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
`tslint.json`
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
Linting configuration for [TSLint](https://palantir.github.io/tslint/) together with
|
|
||||||
[Codelyzer](http://codelyzer.com/), used when running `ng lint`.
|
|
||||||
Linting helps keep your code style consistent.
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div class="l-sub-section">
|
|
||||||
|
|
||||||
### Next Step
|
|
||||||
|
|
||||||
If you're new to Angular, continue with the
|
|
||||||
[tutorial](tutorial "Tour of Heroes tutorial").
|
|
||||||
You can skip the "Setup" step since you're already using the Angular CLI setup.
|
|
||||||
|
|
||||||
</div>
|
|
@ -12,7 +12,7 @@ making some of them public so external components can use them.
|
|||||||
And there are many more options covered here.
|
And there are many more options covered here.
|
||||||
|
|
||||||
Before reading this page, read the
|
Before reading this page, read the
|
||||||
[The Root Module](guide/appmodule) page, which introduces NgModules and the essentials
|
[The Root Module](guide/bootstrapping) page, which introduces NgModules and the essentials
|
||||||
of creating and maintaining a single root `AppModule` for the entire application.
|
of creating and maintaining a single root `AppModule` for the entire application.
|
||||||
|
|
||||||
This page covers NgModules in greater depth.
|
This page covers NgModules in greater depth.
|
||||||
|
@ -1,79 +1,617 @@
|
|||||||
<h1 class="no-toc">QuickStart</h1>
|
# QuickStart
|
||||||
|
|
||||||
Angular applications are made up of _components_.
|
Good tools make application development quicker and easier to maintain than
|
||||||
A _component_ is the combination of an HTML template and a component class that controls a portion of the screen. Here is an example of a component that displays a simple string:
|
if you did everything by hand.
|
||||||
|
|
||||||
|
The [**Angular CLI**](https://cli.angular.io/) is a **_command line interface_** tool
|
||||||
|
that can create a project, add files, and perform a variety of ongoing development tasks such
|
||||||
|
as testing, bundling, and deployment.
|
||||||
|
|
||||||
|
The goal in this guide is to build and run a simple Angular
|
||||||
|
application in TypeScript, using the Angular CLI
|
||||||
|
while adhering to the [Style Guide](guide/styleguide) recommendations that
|
||||||
|
benefit _every_ Angular project.
|
||||||
|
|
||||||
|
By the end of the chapter, you'll have a basic understanding of development with the CLI
|
||||||
|
and a foundation for both these documentation samples and for real world applications.
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
You'll pursue these ends in the following high-level steps:
|
||||||
|
|
||||||
|
1. [Set up](guide/cli-quickstart#devenv) the development environment.
|
||||||
|
2. [Create](guide/cli-quickstart#create-proj) a new project and skeleton application.
|
||||||
|
3. [Serve](guide/cli-quickstart#serve) the application.
|
||||||
|
4. [Edit](guide/cli-quickstart#first-component) the application.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
And you can also <a href="generated/zips/cli-quickstart/cli-quickstart.zip" target="_blank">download the example.</a>
|
||||||
|
|
||||||
|
|
||||||
<code-example path="quickstart/src/app/app.component.ts" title="src/app/app.component.ts" linenums="false">
|
|
||||||
|
<h2 id='devenv'>
|
||||||
|
Step 1. Set up the Development Environment
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
You need to set up your development environment before you can do anything.
|
||||||
|
|
||||||
|
Install **[Node.js® and npm](https://nodejs.org/en/download/)**
|
||||||
|
if they are not already on your machine.
|
||||||
|
|
||||||
|
<div class="l-sub-section">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Verify that you are running at least node `6.9.x` and npm `3.x.x`**
|
||||||
|
by running `node -v` and `npm -v` in a terminal/console window.
|
||||||
|
Older versions produce errors, but newer versions are fine.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Then **install the [Angular CLI](https://github.com/angular/angular-cli)** globally.
|
||||||
|
|
||||||
|
|
||||||
|
<code-example language="sh" class="code-shell">
|
||||||
|
npm install -g @angular/cli
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id='create-proj'>
|
||||||
|
Step 2. Create a new project
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Open a terminal window.
|
||||||
|
|
||||||
|
|
||||||
|
Generate a new project and skeleton application by running the following commands:
|
||||||
|
|
||||||
|
|
||||||
|
<code-example language="sh" class="code-shell">
|
||||||
|
ng new my-app
|
||||||
|
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="l-sub-section">
|
<div class="l-sub-section">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Try this **<live-example noDownload>QuickStart example on Plunker</live-example>** without installing anything.
|
Patience please.
|
||||||
Try it locally with the [***QuickStart seed***](guide/setup "Setup for local development with the QuickStart seed")
|
It takes time to set up a new project, most of it spent installing npm packages.
|
||||||
and prepare for development of a real Angular application.
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Every component begins with an `@Component` [decorator](guide/glossary#decorator '"decorator" explained')
|
|
||||||
function that takes a _metadata_ object. The metadata object describes how the HTML template and component class work together.
|
|
||||||
|
|
||||||
The `selector` property tells Angular to display the component inside a custom `<my-app>` tag in the `index.html`.
|
<h2 id='serve'>
|
||||||
|
Step 3: Serve the application
|
||||||
|
</h2>
|
||||||
|
|
||||||
<code-example path="quickstart/src/index.html" region="my-app" title="index.html (inside <body>)" linenums="false">
|
|
||||||
|
|
||||||
|
Go to the project directory and launch the server.
|
||||||
|
|
||||||
|
|
||||||
|
<code-example language="sh" class="code-shell">
|
||||||
|
cd my-app
|
||||||
|
ng serve --open
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
The `template` property defines a message inside an `<h1>` header.
|
The `ng serve` command launches the server, watches your files,
|
||||||
The message starts with "Hello" and ends with `{{name}}`,
|
and rebuilds the app as you make changes to those files.
|
||||||
which is an Angular [interpolation binding](guide/displaying-data) expression.
|
|
||||||
At runtime, Angular replaces `{{name}}` with the value of the component's `name` property.
|
Using the `--open` (or just `-o`) option will automatically open your browser
|
||||||
Interpolation binding is one of many Angular features you'll discover in this documentation.
|
on `http://localhost:4200/`.
|
||||||
|
|
||||||
|
Your app greets you with a message:
|
||||||
|
|
||||||
|
|
||||||
In the example, change the component class's `name` property from `'Angular'` to `'World'` and see what happens.
|
<figure>
|
||||||
|
<img src='generated/images/guide/cli-quickstart/app-works.png' alt="The app works!">
|
||||||
|
</figure>
|
||||||
<div class="callout is-helpful">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<header>
|
|
||||||
A word about TypeScript
|
<h2 id='first-component'>
|
||||||
</header>
|
Step 4: Edit your first Angular component
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<p>
|
The CLI created the first Angular component for you.
|
||||||
This example is written in <a href="http://www.typescriptlang.org/" title="TypeScript">TypeScript</a>, a superset of JavaScript. Angular
|
This is the _root component_ and it is named `app-root`.
|
||||||
uses TypeScript because its types make it easy to support developer productivity with tooling. You can also write Angular code in JavaScript; [this guide](guide/ts-to-js] explains how.
|
You can find it in `./src/app/app.component.ts`.
|
||||||
|
|
||||||
</p>
|
|
||||||
|
Open the component file and change the `title` property from _app works!_ to _My First Angular App_:
|
||||||
|
|
||||||
|
|
||||||
|
<code-example path="cli-quickstart/src/app/app.component.ts" region="title" title="src/app/app.component.ts" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
The browser reloads automatically with the revised title. That's nice, but it could look better.
|
||||||
|
|
||||||
|
Open `src/app/app.component.css` and give the component some style.
|
||||||
|
|
||||||
|
|
||||||
|
<code-example path="cli-quickstart/src/app/app.component.css" title="src/app/app.component.css" linenums="false"></code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<img src='generated/images/guide/cli-quickstart/my-first-app.png' alt="Output of QuickStart app">
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Looking good!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## What's next?
|
||||||
|
That's about all you'd expect to do in a "Hello, World" app.
|
||||||
|
|
||||||
|
You're ready to take the [Tour of Heroes Tutorial](tutorial) and build
|
||||||
|
a small application that demonstrates the great things you can build with Angular.
|
||||||
|
|
||||||
|
Or you can stick around a bit longer to learn about the files in your brand new project.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Project file review
|
||||||
|
|
||||||
|
An Angular CLI project is the foundation for both quick experiments and enterprise solutions.
|
||||||
|
|
||||||
|
The first file you should check out is `README.md`.
|
||||||
|
It has some basic information on how to use CLI commands.
|
||||||
|
Whenever you want to know more about how Angular CLI works make sure to visit
|
||||||
|
[the Angular CLI repository](https://github.com/angular/angular-cli) and
|
||||||
|
[Wiki](https://github.com/angular/angular-cli/wiki).
|
||||||
|
|
||||||
|
Some of the generated files might be unfamiliar to you.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### The `src` folder
|
||||||
|
Your app lives in the `src` folder.
|
||||||
|
All Angular components, templates, styles, images, and anything else your app needs go here.
|
||||||
|
Any files outside of this folder are meant to support building your app.
|
||||||
|
|
||||||
|
|
||||||
|
<div class='filetree'>
|
||||||
|
<div class='file'>src</div>
|
||||||
|
<div class='children'>
|
||||||
|
<div class='file'>app</div>
|
||||||
|
<div class='children'>
|
||||||
|
<div class='file'>app.component.css</div>
|
||||||
|
<div class='file'>app.component.html</div>
|
||||||
|
<div class="file">app.component.spec.ts</div>
|
||||||
|
<div class="file">app.component.ts</div>
|
||||||
|
<div class="file">app.module.ts</div>
|
||||||
|
</div>
|
||||||
|
<div class="file">assets</div>
|
||||||
|
<div class='children'>
|
||||||
|
<div class="file">.gitkeep</div>
|
||||||
|
</div>
|
||||||
|
<div class="file">environments</div>
|
||||||
|
<div class='children'>
|
||||||
|
<div class="file">environment.prod.ts</div>
|
||||||
|
<div class="file">environment.ts</div>
|
||||||
|
</div>
|
||||||
|
<div class="file">favicon.ico</div>
|
||||||
|
<div class="file">index.html</div>
|
||||||
|
<div class="file">main.ts</div>
|
||||||
|
<div class="file">polyfills.ts</div>
|
||||||
|
<div class="file">styles.css</div>
|
||||||
|
<div class="file">test.ts</div>
|
||||||
|
<div class="file">tsconfig.app.json</div>
|
||||||
|
<div class="file">tsconfig.spec.json</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
td, th {vertical-align: top}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<table width="100%">
|
||||||
|
<col width="20%">
|
||||||
|
</col>
|
||||||
|
<col width="80%">
|
||||||
|
</col>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
File
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Purpose
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`app/app.component.{ts,html,css,spec.ts}`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
Defines the `AppComponent` along with an HTML template, CSS stylesheet, and a unit test.
|
||||||
|
It is the **root** component of what will become a tree of nested components
|
||||||
|
as the application evolves.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`app/app.module.ts`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
Defines `AppModule`, the [root module](guide/bootstrapping "AppModule: the root module") that tells Angular how to assemble the application.
|
||||||
|
Right now it declares only the `AppComponent`.
|
||||||
|
Soon there will be more components to declare.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`assets/*`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
A folder where you can put images and anything else to be copied wholesale
|
||||||
|
when you build your application.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`environments/*`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
This folder contains one file for each of your destination environments,
|
||||||
|
each exporting simple configuration variables to use in your application.
|
||||||
|
The files are replaced on-the-fly when you build your app.
|
||||||
|
You might use a different API endpoint for development than you do for production
|
||||||
|
or maybe different analytics tokens.
|
||||||
|
You might even use some mock services.
|
||||||
|
Either way, the CLI has you covered.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`favicon.ico`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
Every site wants to look good on the bookmark bar.
|
||||||
|
Get started with your very own Angular icon.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`index.html`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
The main HTML page that is served when someone visits your site.
|
||||||
|
Most of the time you'll never need to edit it.
|
||||||
|
The CLI automatically adds all `js` and `css` files when building your app so you
|
||||||
|
never need to add any `<script>` or `<link>` tags here manually.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`main.ts`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
The main entry point for your app.
|
||||||
|
Compiles the application with the [JIT compiler](guide/glossary#jit)
|
||||||
|
and bootstraps the application's root module (`AppModule`) to run in the browser.
|
||||||
|
You can also use the [AOT compiler](guide/glossary#ahead-of-time-aot-compilation)
|
||||||
|
without changing any code by passing in `--aot` to `ng build` or `ng serve`.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`polyfills.ts`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
Different browsers have different levels of support of the web standards.
|
||||||
|
Polyfills help normalize those differences.
|
||||||
|
You should be pretty safe with `core-js` and `zone.js`, but be sure to check out
|
||||||
|
the [Browser Support guide](guide/browser-support) for more information.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`styles.css`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
Your global styles go here.
|
||||||
|
Most of the time you'll want to have local styles in your components for easier maintenance,
|
||||||
|
but styles that affect all of your app need to be in a central place.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`test.ts`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
This is the main entry point for your unit tests.
|
||||||
|
It has some custom configuration that might be unfamiliar, but it's not something you'll
|
||||||
|
need to edit.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`tsconfig.{app|spec}.json`
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
TypeScript compiler configuration for the Angular app (`tsconfig.app.json`)
|
||||||
|
and for the unit tests (`tsconfig.spec.json`).
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
### The root folder
|
||||||
|
|
||||||
|
The `src/` folder is just one of the items inside the project's root folder.
|
||||||
|
Other files help you build, test, maintain, document, and deploy the app.
|
||||||
|
These files go in the root folder next to `src/`.
|
||||||
|
|
||||||
|
|
||||||
|
<div class='filetree'>
|
||||||
|
<div class="file">my-app</div>
|
||||||
|
<div class='children'>
|
||||||
|
<div class="file">e2e</div>
|
||||||
|
<div class='children'>
|
||||||
|
<div class="file">app.e2e-spec.ts</div>
|
||||||
|
<div class="file">app.po.ts</div>
|
||||||
|
<div class="file">tsconfig.e2e.json</div>
|
||||||
|
</div>
|
||||||
|
<div class="file">node_modules/...</div>
|
||||||
|
<div class="file">src/...</div>
|
||||||
|
<div class="file">.angular-cli.json</div>
|
||||||
|
<div class="file">.editorconfig</div>
|
||||||
|
<div class="file">.gitignore</div>
|
||||||
|
<div class="file">karma.conf.js</div>
|
||||||
|
<div class="file">package.json</div>
|
||||||
|
<div class="file">protractor.conf.js</div>
|
||||||
|
<div class="file">README.md</div>
|
||||||
|
<div class="file">tsconfig.json</div>
|
||||||
|
<div class="file">tslint.json</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
td, th {vertical-align: top}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<table width="100%">
|
||||||
|
<col width="20%">
|
||||||
|
</col>
|
||||||
|
<col width="80%">
|
||||||
|
</col>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
File
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Purpose
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`e2e/`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
Inside `e2e/` live the End-to-End tests.
|
||||||
|
They shouldn't be inside `src/` because e2e tests are really a separate app that
|
||||||
|
just so happens to test your main app.
|
||||||
|
That's also why they have their own `tsconfig.e2e.json`.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`node_modules/`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`Node.js` creates this folder and puts all third party modules listed in
|
||||||
|
`package.json` inside of it.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`.angular-cli.json`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
Configuration for Angular CLI.
|
||||||
|
In this file you can set several defaults and also configure what files are included
|
||||||
|
when your project is build.
|
||||||
|
Check out the official documentation if you want to know more.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`.editorconfig`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
Simple configuration for your editor to make sure everyone that uses your project
|
||||||
|
has the same basic configuration.
|
||||||
|
Most editors support an `.editorconfig` file.
|
||||||
|
See http://editorconfig.org for more information.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`.gitignore`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
Git configuration to make sure autogenerated files are not commited to source control.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`karma.conf.js`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
Unit test configuration for the [Karma test runner](https://karma-runner.github.io),
|
||||||
|
used when running `ng test`.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`package.json`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`npm` configuration listing the third party packages your project uses.
|
||||||
|
You can also add your own [custom scripts](https://docs.npmjs.com/misc/scripts) here.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`protractor.conf.js`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
End-to-end test configuration for [Protractor](http://www.protractortest.org/),
|
||||||
|
used when running `ng e2e`.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`README.md`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
Basic documentation for your project, pre-filled with CLI command information.
|
||||||
|
Make sure to enhance it with project documentation so that anyone
|
||||||
|
checking out the repo can build your app!
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`tsconfig.json`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
TypeScript compiler configuration for your IDE to pick up and give you helpful tooling.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
`tslint.json`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
Linting configuration for [TSLint](https://palantir.github.io/tslint/) together with
|
||||||
|
[Codelyzer](http://codelyzer.com/), used when running `ng lint`.
|
||||||
|
Linting helps keep your code style consistent.
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
<div class="l-sub-section">
|
<div class="l-sub-section">
|
||||||
|
|
||||||
|
### Next Step
|
||||||
|
|
||||||
|
If you're new to Angular, continue with the
|
||||||
### Next step
|
[tutorial](tutorial "Tour of Heroes tutorial").
|
||||||
|
You can skip the "Setup" step since you're already using the Angular CLI setup.
|
||||||
Start the [**tutorial**](tutorial "Tour of Heroes tutorial").
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
{@a develop-locally}
|
{@a develop-locally}
|
||||||
|
|
||||||
The <live-example name=quickstart>QuickStart live-coding</live-example> example is an Angular _playground_.
|
The <live-example name=quickstart>QuickStart live-coding</live-example> example is an Angular _playground_.
|
||||||
It's not where you'd develop a real application.
|
It's not where you'd develop a real application.
|
||||||
You [should develop locally](guide/setup#why-locally "Why develop locally") on your own machine ... and that's also how we think you should learn Angular.
|
You [should develop locally](guide/setup#why-locally "Why develop locally") on your own machine ... and that's also how we think you should learn Angular.
|
||||||
|
|
||||||
Setting up a new project on your machine is quick and easy with the **QuickStart seed**,
|
Setting up a new project on your machine is quick and easy with the **QuickStart seed**,
|
||||||
maintained [on github](https://github.com/angular/quickstart "Install the github QuickStart repo").
|
maintained [on github](https://github.com/angular/quickstart "Install the github QuickStart repo").
|
||||||
|
|
||||||
|
|
||||||
Make sure you have [node and npm installed](guide/setup#install-prerequisites "What if you don't have node and npm?").
|
Make sure you have [node and npm installed](guide/setup#install-prerequisites "What if you don't have node and npm?").
|
||||||
@ -124,7 +124,7 @@ Open a terminal window in the project folder and enter the following commands fo
|
|||||||
|
|
||||||
The **QuickStart seed** contains the same application as the QuickStart playground.
|
The **QuickStart seed** contains the same application as the QuickStart playground.
|
||||||
But its true purpose is to provide a solid foundation for _local_ development.
|
But its true purpose is to provide a solid foundation for _local_ development.
|
||||||
Consequently, there are _many more files_ in the project folder on your machine,
|
Consequently, there are _many more files_ in the project folder on your machine,
|
||||||
most of which you can [learn about later](guide/setup-systemjs-anatomy "Setup Anatomy").
|
most of which you can [learn about later](guide/setup-systemjs-anatomy "Setup Anatomy").
|
||||||
|
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ Focus on the following three TypeScript (`.ts`) files in the **`/src`** folder.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
All guides and cookbooks have _at least these core files_.
|
All guides and cookbooks have _at least these core files_.
|
||||||
Each file has a distinct purpose and evolves independently as the application grows.
|
Each file has a distinct purpose and evolves independently as the application grows.
|
||||||
|
|
||||||
Files outside `src/` concern building, deploying, and testing your app.
|
Files outside `src/` concern building, deploying, and testing your app.
|
||||||
@ -239,7 +239,7 @@ The following are all in `src/`
|
|||||||
|
|
||||||
Defines the same `AppComponent` as the one in the QuickStart playground.
|
Defines the same `AppComponent` as the one in the QuickStart playground.
|
||||||
It is the **root** component of what will become a tree of nested components
|
It is the **root** component of what will become a tree of nested components
|
||||||
as the application evolves.
|
as the application evolves.
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
@ -253,7 +253,7 @@ The following are all in `src/`
|
|||||||
<td>
|
<td>
|
||||||
|
|
||||||
|
|
||||||
Defines `AppModule`, the [root module](guide/appmodule "AppModule: the root module") that tells Angular how to assemble the application.
|
Defines `AppModule`, the [root module](guide/bootstrapping "AppModule: the root module") that tells Angular how to assemble the application.
|
||||||
Right now it declares only the `AppComponent`.
|
Right now it declares only the `AppComponent`.
|
||||||
Soon there will be more components to declare.
|
Soon there will be more components to declare.
|
||||||
</td>
|
</td>
|
||||||
@ -270,7 +270,7 @@ The following are all in `src/`
|
|||||||
|
|
||||||
|
|
||||||
Compiles the application with the [JIT compiler](guide/glossary#jit) and
|
Compiles the application with the [JIT compiler](guide/glossary#jit) and
|
||||||
[bootstraps](guide/appmodule#main "bootstrap the application")
|
[bootstraps](guide/bootstrapping#main "bootstrap the application")
|
||||||
the application's main module (`AppModule`) to run in the browser.
|
the application's main module (`AppModule`) to run in the browser.
|
||||||
The JIT compiler is a reasonable choice during the development of most projects and
|
The JIT compiler is a reasonable choice during the development of most projects and
|
||||||
it's the only viable choice for a sample running in a _live-coding_ environment like Plunker.
|
it's the only viable choice for a sample running in a _live-coding_ environment like Plunker.
|
||||||
@ -315,8 +315,8 @@ Get them now</a> if they're not already installed on your machine.
|
|||||||
by running the commands `node -v` and `npm -v` in a terminal/console window.
|
by running the commands `node -v` and `npm -v` in a terminal/console window.
|
||||||
Older versions produce errors.
|
Older versions produce errors.
|
||||||
|
|
||||||
We recommend [nvm](https://github.com/creationix/nvm) for managing multiple versions of node and npm.
|
We recommend [nvm](https://github.com/creationix/nvm) for managing multiple versions of node and npm.
|
||||||
You may need [nvm](https://github.com/creationix/nvm) if you already have projects running on your machine that
|
You may need [nvm](https://github.com/creationix/nvm) if you already have projects running on your machine that
|
||||||
use other versions of node and npm.
|
use other versions of node and npm.
|
||||||
|
|
||||||
|
|
||||||
@ -334,7 +334,7 @@ You can play with the sample code, share your changes with friends, and download
|
|||||||
The [QuickStart](guide/quickstart "Angular QuickStart Playground") shows just the `AppComponent` file.
|
The [QuickStart](guide/quickstart "Angular QuickStart Playground") shows just the `AppComponent` file.
|
||||||
It creates the equivalent of `app.module.ts` and `main.ts` internally _for the playground only_.
|
It creates the equivalent of `app.module.ts` and `main.ts` internally _for the playground only_.
|
||||||
so the reader can discover Angular without distraction.
|
so the reader can discover Angular without distraction.
|
||||||
The other samples are based on the QuickStart seed.
|
The other samples are based on the QuickStart seed.
|
||||||
|
|
||||||
As much fun as this is ...
|
As much fun as this is ...
|
||||||
|
|
||||||
@ -343,7 +343,7 @@ As much fun as this is ...
|
|||||||
* transpiling TypeScript in the browser is slow
|
* transpiling TypeScript in the browser is slow
|
||||||
* the type support, refactoring, and code completion only work in your local IDE
|
* the type support, refactoring, and code completion only work in your local IDE
|
||||||
|
|
||||||
Use the <live-example title="QuickStart Seed in Plunker">live coding</live-example> environment as a _playground_,
|
Use the <live-example title="QuickStart Seed in Plunker">live coding</live-example> environment as a _playground_,
|
||||||
a place to try the documentation samples and experiment on your own.
|
a place to try the documentation samples and experiment on your own.
|
||||||
It's the perfect place to reproduce a bug when you want to
|
It's the perfect place to reproduce a bug when you want to
|
||||||
<a href="https://github.com/angular/angular/issues/new" title="File a documentation issue">file a documentation issue</a> or
|
<a href="https://github.com/angular/angular/issues/new" title="File a documentation issue">file a documentation issue</a> or
|
||||||
|
BIN
aio/content/images/marketing/angular-mix.png
Normal file
BIN
aio/content/images/marketing/angular-mix.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.8 KiB |
@ -5,8 +5,8 @@ Angular is a platform that makes it easy to build applications with the web. Ang
|
|||||||
<div class="card-container">
|
<div class="card-container">
|
||||||
<a href="generated/live-examples/quickstart/eplnkr.html" target="_blank" class="docs-card"
|
<a href="generated/live-examples/quickstart/eplnkr.html" target="_blank" class="docs-card"
|
||||||
title="Experience Angular in a live coding environment">
|
title="Experience Angular in a live coding environment">
|
||||||
<section>Experience Angular</section>
|
<section>Get a Glimpse of Angular</section>
|
||||||
<p>A quick look at an Angular application.</p>
|
<p>A quick look at an Angular "hello world" application.</p>
|
||||||
<p class="card-footer">Angular in Action</p>
|
<p class="card-footer">Angular in Action</p>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -16,8 +16,6 @@ Angular is a platform that makes it easy to build applications with the web. Ang
|
|||||||
<p class="card-footer" >
|
<p class="card-footer" >
|
||||||
<a href="guide/quickstart" title="Angular Quickstart">Quickstart</a>
|
<a href="guide/quickstart" title="Angular Quickstart">Quickstart</a>
|
||||||
</p>
|
</p>
|
||||||
<!--<p class="card-footer"><a href="guide/quickstart">Quickstart</a></p>
|
|
||||||
<p class="card-footer"><a href="guide/tutorial">Tutorial</a></p>-->
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href="guide/architecture" class="docs-card" title="Angular Architecture">
|
<a href="guide/architecture" class="docs-card" title="Angular Architecture">
|
||||||
|
@ -19,6 +19,12 @@
|
|||||||
<td>Tokyo, Japan</td>
|
<td>Tokyo, Japan</td>
|
||||||
<td>June 17, 2017</td>
|
<td>June 17, 2017</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<!-- AngularMix -->
|
||||||
|
<tr>
|
||||||
|
<th><a href="https://angularmix.com/" title="AngularMix">AngularMix</a></th>
|
||||||
|
<td>Universal Studios, Orlando, Florida</td>
|
||||||
|
<td>October 8, 2017</td>
|
||||||
|
</tr>
|
||||||
<!-- ReactiveConf -->
|
<!-- ReactiveConf -->
|
||||||
<tr>
|
<tr>
|
||||||
<th><a href="https://reactiveconf.com/" title="ReactiveConf">ReactiveConf</a></th>
|
<th><a href="https://reactiveconf.com/" title="ReactiveConf">ReactiveConf</a></th>
|
||||||
@ -29,7 +35,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th><a href="http://angularconnect.com" title="AngularConnect">AngularConnect</a></th>
|
<th><a href="http://angularconnect.com" title="AngularConnect">AngularConnect</a></th>
|
||||||
<td>London, United Kingdom</td>
|
<td>London, United Kingdom</td>
|
||||||
<td>Nov. 07, 2017</td>
|
<td>November 07, 2017</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -32,10 +32,10 @@
|
|||||||
<!--Announcement Bar-->
|
<!--Announcement Bar-->
|
||||||
<div class="homepage-container">
|
<div class="homepage-container">
|
||||||
<div class="announcement-bar">
|
<div class="announcement-bar">
|
||||||
<img src="assets/images/logos/angular/angular-banner-logo-grey.png" width="64"/>
|
<img src="generated/images/marketing/angular-mix.png" height="40" width="151">
|
||||||
<p>Angular v4.0 is out! Smaller, faster, no biggie...</p>
|
<p>Join us at our newest event, October 2017</p>
|
||||||
<button class="button">
|
<button class="button">
|
||||||
<a href="http://angularjs.blogspot.com/2017/03/angular-400-now-available.html" target="_blank">Learn More</a>
|
<a href="https://angularmix.com/">Learn More</a>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -44,7 +44,7 @@
|
|||||||
<div layout="row" layout-xs="column" class="home-row homepage-container">
|
<div layout="row" layout-xs="column" class="home-row homepage-container">
|
||||||
<div class="promo-img-container promo-1">
|
<div class="promo-img-container promo-1">
|
||||||
<div>
|
<div>
|
||||||
<img height="222" src="assets/images/home/responsive-framework.svg" alt="responsive framework">
|
<img height="222" width="340" src="assets/images/home/responsive-framework.svg" alt="responsive framework">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -69,7 +69,7 @@
|
|||||||
|
|
||||||
<div class="promo-img-container promo-2">
|
<div class="promo-img-container promo-2">
|
||||||
<div>
|
<div>
|
||||||
<img height="222" src="assets/images/home/speed-performance.svg" alt="speed and performance">
|
<img height="222" width="323" src="assets/images/home/speed-performance.svg" alt="speed and performance">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -112,12 +112,12 @@
|
|||||||
<!-- CTA CARDS -->
|
<!-- CTA CARDS -->
|
||||||
<div layout="row" layout-xs="column" class="home-row">
|
<div layout="row" layout-xs="column" class="home-row">
|
||||||
|
|
||||||
<a href="tutorial">
|
<a href="guide/quickstart">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<img src="../assets/images/icons/code-icon.svg" height="70px">
|
<img src="../assets/images/icons/code-icon.svg" height="70px">
|
||||||
<div class="card-text-container">
|
<div class="card-text-container">
|
||||||
<div class="text-headline">Start Tutorial</div>
|
<div class="text-headline">Get Started</div>
|
||||||
<p>Start building your Angular application in TypeScript.</p>
|
<p>Start building your Angular application.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
{
|
{
|
||||||
"url": "events",
|
"url": "events",
|
||||||
"title": "Events"
|
"title": "Events"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blog.angularjs.org/",
|
||||||
|
"title": "Blog"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
@ -33,6 +37,10 @@
|
|||||||
{
|
{
|
||||||
"url": "events",
|
"url": "events",
|
||||||
"title": "Events"
|
"title": "Events"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blog.angularjs.org/",
|
||||||
|
"title": "Blog"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -47,21 +55,10 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
"url": "guide/quickstart",
|
||||||
"title": "Getting Started",
|
"title": "Getting Started",
|
||||||
"tooltip": "A gentle introduction to Angular.",
|
"tooltip": "A gentle introduction to Angular."
|
||||||
"children": [
|
},
|
||||||
{
|
|
||||||
"url": "guide/quickstart",
|
|
||||||
"title": "Basic Quickstart",
|
|
||||||
"tooltip": "A quick look at an Angular app without tooling."
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"url": "guide/cli-quickstart",
|
|
||||||
"title": "CLI Quickstart",
|
|
||||||
"tooltip": "A quick look at an Angular app built with the Angular CLI."
|
|
||||||
}
|
|
||||||
]},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"title": "Tutorial",
|
"title": "Tutorial",
|
||||||
@ -109,43 +106,14 @@
|
|||||||
"title": "Fundamentals",
|
"title": "Fundamentals",
|
||||||
"tooltip": "The fundamentals of Angular",
|
"tooltip": "The fundamentals of Angular",
|
||||||
"children": [
|
"children": [
|
||||||
|
|
||||||
{
|
|
||||||
"url": "guide/animations",
|
|
||||||
"title": "Animations",
|
|
||||||
"tooltip": "A guide to Angular's animation system."
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"title": "Angular Modules",
|
|
||||||
"tooltip": "Learn how directives modify the layout and behavior of elements.",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"url": "guide/appmodule",
|
|
||||||
"title": "The Root AppModule",
|
|
||||||
"tooltip": "Tell Angular how to construct and bootstrap the app in the root \"AppModule\"."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/ngmodule",
|
|
||||||
"title": "NgModule",
|
|
||||||
"tooltip": "Define application modules with @NgModule."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/ngmodule-faq",
|
|
||||||
"title": "Angular Module FAQs",
|
|
||||||
"tooltip": "Answers to frequently asked questions about @NgModule."
|
|
||||||
}
|
|
||||||
]},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"url": "guide/architecture",
|
"url": "guide/architecture",
|
||||||
"title": "Architecture",
|
"title": "Architecture",
|
||||||
"tooltip": "The basic building blocks of Angular applications."
|
"tooltip": "The basic building blocks of Angular applications."
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"title": "Components",
|
"title": "Template & Data Binding",
|
||||||
"tooltip": "Components present information to users and collect their input.",
|
"tooltip": "Template & Data Binding",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"url": "guide/displaying-data",
|
"url": "guide/displaying-data",
|
||||||
@ -167,23 +135,86 @@
|
|||||||
"title": "Component Interaction",
|
"title": "Component Interaction",
|
||||||
"tooltip": "Share information between different directives and components."
|
"tooltip": "Share information between different directives and components."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"url": "guide/component-styles",
|
|
||||||
"title": "Component Styles",
|
|
||||||
"tooltip": "Learn how to apply CSS styles to components."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"url": "guide/dynamic-component-loader",
|
"url": "guide/dynamic-component-loader",
|
||||||
"title": "Dynamic Components",
|
"title": "Dynamic Components",
|
||||||
"tooltip": "Load components dynamically."
|
"tooltip": "Load components dynamically."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/attribute-directives",
|
||||||
|
"title": "Attribute Directives",
|
||||||
|
"tooltip": "Attribute directives attach behavior to elements."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/structural-directives",
|
||||||
|
"title": "Structural Directives",
|
||||||
|
"tooltip": "Structural directives manipulate the layout of the page."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"url": "guide/pipes",
|
"url": "guide/pipes",
|
||||||
"title": "Pipes",
|
"title": "Pipes",
|
||||||
"tooltip": "Pipes transform displayed values within a template."
|
"tooltip": "Pipes transform displayed values within a template."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/animations",
|
||||||
|
"title": "Animations",
|
||||||
|
"tooltip": "A guide to Angular's animation system."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"title": "Forms",
|
||||||
|
"tooltip": "Angular Forms",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"url": "guide/user-input",
|
||||||
|
"title": "User Input",
|
||||||
|
"tooltip": "User input triggers DOM events. We listen to those events with event bindings that funnel updated values back into our components and models."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/forms",
|
||||||
|
"title": "Template-driven Forms",
|
||||||
|
"tooltip": "A form creates a cohesive, effective, and compelling data entry experience. An Angular form coordinates a set of data-bound user controls, tracks changes, validates input, and presents errors."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/form-validation",
|
||||||
|
"title": "Form Validation",
|
||||||
|
"tooltip": "Validate user's form entries."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/reactive-forms",
|
||||||
|
"title": "Reactive Forms",
|
||||||
|
"tooltip": "Create a reactive form using FormBuilder, groups, and arrays."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/dynamic-form",
|
||||||
|
"title": "Dynamic forms",
|
||||||
|
"tooltip": "Render dynamic forms with FormGroup."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"url": "guide/bootstrapping",
|
||||||
|
"title": "Bootstrapping",
|
||||||
|
"tooltip": "Tell Angular how to construct and bootstrap the app in the root \"AppModule\"."
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"title": "NgModules",
|
||||||
|
"tooltip": "Learn how to use NgModules to make your apps efficient.",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"url": "guide/ngmodule",
|
||||||
|
"title": "NgModules",
|
||||||
|
"tooltip": "Define application modules with @NgModule."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/ngmodule-faq",
|
||||||
|
"title": "NgModule FAQs",
|
||||||
|
"tooltip": "Answers to frequently asked questions about @NgModule."
|
||||||
|
}
|
||||||
|
]},
|
||||||
|
|
||||||
{
|
{
|
||||||
"title": "Dependency Injection",
|
"title": "Dependency Injection",
|
||||||
@ -207,73 +238,26 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
"title": "Directives",
|
|
||||||
"tooltip": "Learn how directives modify the layout and behavior of elements.",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"url": "guide/attribute-directives",
|
|
||||||
"title": "Attribute Directives",
|
|
||||||
"tooltip": "Attribute directives attach behavior to elements."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/structural-directives",
|
|
||||||
"title": "Structural Directives",
|
|
||||||
"tooltip": "Structural directives manipulate the layout of the page."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"url": "guide/http",
|
"url": "guide/http",
|
||||||
"title": "HTTP",
|
"title": "Server Communication",
|
||||||
"tooltip": "Use HTTP to talk to a remote server."
|
"tooltip": "Use HTTP to talk to a remote server."
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
"url": "guide/i18n",
|
|
||||||
"title": "Internationalization (i18n)",
|
|
||||||
"tooltip": "Translate the app's template text into multiple languages."
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"url": "guide/router",
|
"url": "guide/router",
|
||||||
"title": "Routing & Navigation",
|
"title": "Routing & Navigation",
|
||||||
"tooltip": "Discover the basics of screen navigation with the Angular Router."
|
"tooltip": "Discover the basics of screen navigation with the Angular Router."
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"title": "User Input",
|
"url": "guide/testing",
|
||||||
"tooltip": "User Input",
|
"title": "Testing",
|
||||||
"children": [
|
"tooltip": "Techniques and practices for testing an Angular app."
|
||||||
{
|
},
|
||||||
"url": "guide/user-input",
|
{
|
||||||
"title": "User Input",
|
"url": "guide/cheatsheet",
|
||||||
"tooltip": "User input triggers DOM events. We listen to those events with event bindings that funnel updated values back into our components and models."
|
"title": "Cheat Sheet",
|
||||||
},
|
"tooltip": "A quick guide to common Angular coding techniques."
|
||||||
|
}
|
||||||
{
|
|
||||||
"url": "guide/forms",
|
|
||||||
"title": "Template-driven Forms",
|
|
||||||
"tooltip": "A form creates a cohesive, effective, and compelling data entry experience. An Angular form coordinates a set of data-bound user controls, tracks changes, validates input, and presents errors."
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"url": "guide/reactive-forms",
|
|
||||||
"title": "Reactive Forms",
|
|
||||||
"tooltip": "Create a reactive form using FormBuilder, groups, and arrays."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/form-validation",
|
|
||||||
"title": "Form Validation",
|
|
||||||
"tooltip": "Validate user's form entries."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "guide/dynamic-form",
|
|
||||||
"title": "Dynamic forms",
|
|
||||||
"tooltip": "Render dynamic forms with FormGroup."
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
]},
|
]},
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -281,18 +265,21 @@
|
|||||||
"tooltip": "Techniques for putting Angular to work in your environment",
|
"tooltip": "Techniques for putting Angular to work in your environment",
|
||||||
"children": [
|
"children": [
|
||||||
|
|
||||||
|
{
|
||||||
|
"url": "guide/i18n",
|
||||||
|
"title": "Internationalization (i18n)",
|
||||||
|
"tooltip": "Translate the app's template text into multiple languages."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"url": "guide/security",
|
"url": "guide/security",
|
||||||
"title": "Security",
|
"title": "Security",
|
||||||
"tooltip": "Developing for content security in Angular applications."
|
"tooltip": "Developing for content security in Angular applications."
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"url": "guide/set-document-title",
|
"url": "guide/ts-to-js",
|
||||||
"title": "Set the document tab title",
|
"title": "TypeScript to JavaScript",
|
||||||
"tooltip": "Set the browser tab title dynamically with the Angular Title service"
|
"tooltip": "Convert Angular TypeScript examples into ES6 and ES5 JavaScript."
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"title": "Setup & Deployment",
|
"title": "Setup & Deployment",
|
||||||
"tooltip": "Setup and Deployment",
|
"tooltip": "Setup and Deployment",
|
||||||
@ -336,31 +323,19 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
"url": "guide/testing",
|
|
||||||
"title": "Testing",
|
|
||||||
"tooltip": "Techniques and practices for testing an Angular app."
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"url": "guide/ts-to-js",
|
|
||||||
"title": "TypeScript to JavaScript",
|
|
||||||
"tooltip": "Convert Angular TypeScript examples into ES6 and ES5 JavaScript."
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"title": "Upgrading",
|
"title": "Upgrading",
|
||||||
"tooltip": "Incrementally upgrade an AngularJS application to Angular.",
|
"tooltip": "Incrementally upgrade an AngularJS application to Angular.",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
|
||||||
"url": "guide/ajs-quick-reference",
|
|
||||||
"title": "AngularJS to Angular",
|
|
||||||
"tooltip": "Learn how AngularJS concepts and techniques map to Angular."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"url": "guide/upgrade",
|
"url": "guide/upgrade",
|
||||||
"title": "Upgrading from AngularJS",
|
"title": "Upgrading from AngularJS",
|
||||||
"tooltip": "Incrementally upgrade an AngularJS application to Angular."
|
"tooltip": "Incrementally upgrade an AngularJS application to Angular."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/ajs-quick-reference",
|
||||||
|
"title": "AngularJS to Angular",
|
||||||
|
"tooltip": "Learn how AngularJS concepts and techniques map to Angular."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -370,11 +345,15 @@
|
|||||||
"title": "Visual Studio 2015 QuickStart",
|
"title": "Visual Studio 2015 QuickStart",
|
||||||
"tooltip": "Use Visual Studio 2015 with the QuickStart files."
|
"tooltip": "Use Visual Studio 2015 with the QuickStart files."
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"url": "guide/webpack",
|
"url": "guide/styleguide",
|
||||||
"title": "Webpack: An Introduction",
|
"title": "Style Guide",
|
||||||
"tooltip": "Create Angular applications with Webpack based tooling."
|
"tooltip": "Write Angular with style."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "guide/glossary",
|
||||||
|
"title": "Glossary",
|
||||||
|
"tooltip": "Brief definitions of the most important words in the Angular vocabulary."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -383,36 +362,6 @@
|
|||||||
"title": "API",
|
"title": "API",
|
||||||
"tooltip": "Details of the Angular classes and values.",
|
"tooltip": "Details of the Angular classes and values.",
|
||||||
"url": "api"
|
"url": "api"
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"title": "References",
|
|
||||||
"tooltip": "References on Angular usage and style.",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"url": "guide/change-log",
|
|
||||||
"title": "Change Log",
|
|
||||||
"tooltip": "An annotated history of recent documentation improvements."
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"url": "guide/cheatsheet",
|
|
||||||
"title": "Cheat Sheet",
|
|
||||||
"tooltip": "A quick guide to common Angular coding techniques."
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"url": "guide/glossary",
|
|
||||||
"title": "Glossary",
|
|
||||||
"tooltip": "Brief definitions of the most important words in the Angular vocabulary."
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"url": "guide/styleguide",
|
|
||||||
"title": "Style Guide",
|
|
||||||
"tooltip": "Write Angular with style."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
@ -434,6 +383,11 @@
|
|||||||
"url": "presskit",
|
"url": "presskit",
|
||||||
"title": "Press Kit",
|
"title": "Press Kit",
|
||||||
"tooltip": "Press contacts, logos, and branding."
|
"tooltip": "Press contacts, logos, and branding."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blog.angularjs.org/",
|
||||||
|
"title": "Blog",
|
||||||
|
"tooltip": "Angular Blog"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -1,12 +1,5 @@
|
|||||||
@title
|
|
||||||
Tutorial: Tour of Heroes
|
|
||||||
|
|
||||||
@intro
|
|
||||||
The Tour of Heroes tutorial takes you through the steps of creating an Angular application in TypeScript.
|
|
||||||
|
|
||||||
@description
|
|
||||||
|
|
||||||
|
|
||||||
|
# Tutorial: Tour of Heroes
|
||||||
|
|
||||||
The grand plan for this tutorial is to build an app that helps a staffing agency manage its stable of heroes.
|
The grand plan for this tutorial is to build an app that helps a staffing agency manage its stable of heroes.
|
||||||
|
|
||||||
@ -34,7 +27,7 @@ When you're done with this tutorial, the app will look like this <live-example n
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## The end game
|
## What you'll build
|
||||||
|
|
||||||
Here's a visual idea of where this tutorial leads, beginning with the "Dashboard"
|
Here's a visual idea of where this tutorial leads, beginning with the "Dashboard"
|
||||||
view and the most heroic heroes:
|
view and the most heroic heroes:
|
||||||
|
@ -1200,7 +1200,7 @@ These correspond to the full set of master styles that you installed earlier dur
|
|||||||
Here's an excerpt:
|
Here's an excerpt:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/styles.css" region="toh" title="src/styles.css (excerpt)">
|
<code-example path="toh-pt5/src/styles.1.css" title="src/styles.css (excerpt)">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
@ -27,9 +27,7 @@ describe('site App', function() {
|
|||||||
// Show the menu
|
// Show the menu
|
||||||
page.docsMenuLink.click();
|
page.docsMenuLink.click();
|
||||||
|
|
||||||
// Open the tutorial header
|
// Tutorial folder should still be expanded because this test runs in wide mode
|
||||||
page.getNavItem(/tutorial/i).click();
|
|
||||||
|
|
||||||
// Navigate to the tutorial introduction via a link in the sidenav
|
// Navigate to the tutorial introduction via a link in the sidenav
|
||||||
page.getNavItem(/introduction/i).click();
|
page.getNavItem(/introduction/i).click();
|
||||||
expect(page.getDocViewerText()).toMatch(/Tutorial: Tour of Heroes/i);
|
expect(page.getDocViewerText()).toMatch(/Tutorial: Tour of Heroes/i);
|
||||||
@ -61,14 +59,6 @@ describe('site App', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('api-docs', () => {
|
|
||||||
it('should show a link to github', () => {
|
|
||||||
page.navigateTo('api/common/NgClass');
|
|
||||||
expect(page.ghLink.getAttribute('href'))
|
|
||||||
.toMatch(/https:\/\/github.com\/angular\/angular\/tree\/.+\/packages\/common\/src\/directives\/ng_class\.ts/);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('tutorial docs', () => {
|
describe('tutorial docs', () => {
|
||||||
it('should not render a paragraph element inside the h1 element', () => {
|
it('should not render a paragraph element inside the h1 element', () => {
|
||||||
page.navigateTo('tutorial/toh-pt1');
|
page.navigateTo('tutorial/toh-pt1');
|
||||||
|
@ -39,17 +39,17 @@
|
|||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "next",
|
"@angular/animations": "4.2.0",
|
||||||
"@angular/common": "next",
|
"@angular/common": "4.2.0",
|
||||||
"@angular/compiler": "next",
|
"@angular/compiler": "4.2.0",
|
||||||
"@angular/core": "next",
|
"@angular/core": "4.2.0",
|
||||||
"@angular/forms": "next",
|
"@angular/forms": "4.2.0",
|
||||||
"@angular/http": "next",
|
"@angular/http": "4.2.0",
|
||||||
"@angular/material": "^2.0.0-beta.3",
|
"@angular/material": "^2.0.0-beta.3",
|
||||||
"@angular/platform-browser": "next",
|
"@angular/platform-browser": "4.2.0",
|
||||||
"@angular/platform-browser-dynamic": "next",
|
"@angular/platform-browser-dynamic": "4.2.0",
|
||||||
"@angular/platform-server": "next",
|
"@angular/platform-server": "4.2.0",
|
||||||
"@angular/router": "next",
|
"@angular/router": "4.2.0",
|
||||||
"@angular/service-worker": "^1.0.0-beta.12",
|
"@angular/service-worker": "^1.0.0-beta.12",
|
||||||
"classlist.js": "^1.1.20150312",
|
"classlist.js": "^1.1.20150312",
|
||||||
"core-js": "^2.4.1",
|
"core-js": "^2.4.1",
|
||||||
@ -63,7 +63,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular/cli": "^1.1.0-rc.0",
|
"@angular/cli": "^1.1.0-rc.0",
|
||||||
"@angular/compiler-cli": "next",
|
"@angular/compiler-cli": "4.2.0",
|
||||||
"@types/jasmine": "^2.5.47",
|
"@types/jasmine": "^2.5.47",
|
||||||
"@types/node": "~6.0.60",
|
"@types/node": "~6.0.60",
|
||||||
"archiver": "^1.3.0",
|
"archiver": "^1.3.0",
|
||||||
@ -83,6 +83,7 @@
|
|||||||
"hast-util-to-string": "^1.0.0",
|
"hast-util-to-string": "^1.0.0",
|
||||||
"html": "^1.0.0",
|
"html": "^1.0.0",
|
||||||
"http-server": "^0.9.0",
|
"http-server": "^0.9.0",
|
||||||
|
"ignore": "^3.3.3",
|
||||||
"image-size": "^0.5.1",
|
"image-size": "^0.5.1",
|
||||||
"jasmine-core": "~2.5.2",
|
"jasmine-core": "~2.5.2",
|
||||||
"jasmine-spec-reporter": "~3.2.0",
|
"jasmine-spec-reporter": "~3.2.0",
|
||||||
@ -106,7 +107,7 @@
|
|||||||
"tree-kill": "^1.1.0",
|
"tree-kill": "^1.1.0",
|
||||||
"ts-node": "~2.0.0",
|
"ts-node": "~2.0.0",
|
||||||
"tslint": "~4.5.0",
|
"tslint": "~4.5.0",
|
||||||
"typescript": "2.2.0",
|
"typescript": "2.3.2",
|
||||||
"unist-util-filter": "^0.2.1",
|
"unist-util-filter": "^0.2.1",
|
||||||
"unist-util-source": "^1.0.1",
|
"unist-util-source": "^1.0.1",
|
||||||
"unist-util-visit": "^1.1.1",
|
"unist-util-visit": "^1.1.1",
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<md-toolbar color="primary" class="app-toolbar">
|
<md-toolbar color="primary" class="app-toolbar">
|
||||||
<button class="hamburger" md-button
|
<button class="hamburger" [class.starting]="isStarting" md-button
|
||||||
(click)="sidenav.toggle()" title="Docs menu">
|
(click)="sidenav.toggle()" title="Docs menu">
|
||||||
<md-icon [ngClass]="{'sidenav-open': !isSideBySide }" svgIcon="menu"></md-icon>
|
<md-icon [ngClass]="{'sidenav-open': !isSideBySide }" svgIcon="menu"></md-icon>
|
||||||
</button>
|
</button>
|
||||||
@ -15,11 +15,11 @@
|
|||||||
</md-toolbar>
|
</md-toolbar>
|
||||||
<aio-search-results #searchResults *ngIf="showSearchResults" (resultSelected)="hideSearchResults()"></aio-search-results>
|
<aio-search-results #searchResults *ngIf="showSearchResults" (resultSelected)="hideSearchResults()"></aio-search-results>
|
||||||
|
|
||||||
<md-sidenav-container class="sidenav-container" [class.starting]="isStarting" role="main">
|
<md-sidenav-container class="sidenav-container" [class.starting]="isStarting" [class.has-floating-toc]="hasFloatingToc" role="main">
|
||||||
|
|
||||||
<md-sidenav [ngClass]="{'collapsed': !isSideBySide }" #sidenav class="sidenav" [opened]="isOpened" [mode]="mode" (open)="updateHostClasses()" (close)="updateHostClasses()">
|
<md-sidenav [ngClass]="{'collapsed': !isSideBySide }" #sidenav class="sidenav" [opened]="isOpened" [mode]="mode" (open)="updateHostClasses()" (close)="updateHostClasses()">
|
||||||
<aio-nav-menu *ngIf="!isSideBySide" [nodes]="topMenuNarrowNodes" [currentNode]="currentNodes?.TopBarNarrow"></aio-nav-menu>
|
<aio-nav-menu *ngIf="!isSideBySide" [nodes]="topMenuNarrowNodes" [currentNode]="currentNodes?.TopBarNarrow" [isWide]="false"></aio-nav-menu>
|
||||||
<aio-nav-menu [nodes]="sideNavNodes" [currentNode]="currentNodes?.SideNav" ></aio-nav-menu>
|
<aio-nav-menu [nodes]="sideNavNodes" [currentNode]="currentNodes?.SideNav" [isWide]="isSideBySide"></aio-nav-menu>
|
||||||
|
|
||||||
<div class="doc-version" title="Angular docs version {{currentDocVersion?.title}}">
|
<div class="doc-version" title="Angular docs version {{currentDocVersion?.title}}">
|
||||||
<aio-select (change)="onDocVersionChange($event.index)" [options]="docVersions" [selected]="docVersions && docVersions[0]"></aio-select>
|
<aio-select (change)="onDocVersionChange($event.index)" [options]="docVersions" [selected]="docVersions && docVersions[0]"></aio-select>
|
||||||
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
</md-sidenav-container>
|
</md-sidenav-container>
|
||||||
|
|
||||||
<div *ngIf="showFloatingToc" class="toc-container" [style.max-height.px]="tocMaxHeight">
|
<div *ngIf="hasFloatingToc" class="toc-container" [style.max-height.px]="tocMaxHeight" (mousewheel)="restrainScrolling($event)">
|
||||||
<aio-toc></aio-toc>
|
<aio-toc></aio-toc>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import { async, inject, ComponentFixture, TestBed, fakeAsync, tick } from '@angu
|
|||||||
import { Title } from '@angular/platform-browser';
|
import { Title } from '@angular/platform-browser';
|
||||||
import { APP_BASE_HREF } from '@angular/common';
|
import { APP_BASE_HREF } from '@angular/common';
|
||||||
import { Http } from '@angular/http';
|
import { Http } from '@angular/http';
|
||||||
import { MdProgressBar } from '@angular/material';
|
import { MdProgressBar, MdSidenav } from '@angular/material';
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
|
|
||||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||||
@ -27,7 +27,7 @@ import { SearchService } from 'app/search/search.service';
|
|||||||
import { SelectComponent, Option } from 'app/shared/select/select.component';
|
import { SelectComponent, Option } from 'app/shared/select/select.component';
|
||||||
import { SwUpdateNotificationsService } from 'app/sw-updates/sw-update-notifications.service';
|
import { SwUpdateNotificationsService } from 'app/sw-updates/sw-update-notifications.service';
|
||||||
import { TocComponent } from 'app/embedded/toc/toc.component';
|
import { TocComponent } from 'app/embedded/toc/toc.component';
|
||||||
import { MdSidenav } from '@angular/material';
|
import { TocItem, TocService } from 'app/shared/toc.service';
|
||||||
|
|
||||||
const sideBySideBreakPoint = 992;
|
const sideBySideBreakPoint = 992;
|
||||||
const hideToCBreakPoint = 800;
|
const hideToCBreakPoint = 800;
|
||||||
@ -40,6 +40,7 @@ describe('AppComponent', () => {
|
|||||||
let hamburger: HTMLButtonElement;
|
let hamburger: HTMLButtonElement;
|
||||||
let locationService: MockLocationService;
|
let locationService: MockLocationService;
|
||||||
let sidenav: HTMLElement;
|
let sidenav: HTMLElement;
|
||||||
|
let tocService: TocService;
|
||||||
|
|
||||||
const initializeTest = () => {
|
const initializeTest = () => {
|
||||||
fixture = TestBed.createComponent(AppComponent);
|
fixture = TestBed.createComponent(AppComponent);
|
||||||
@ -48,10 +49,12 @@ describe('AppComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
component.onResize(sideBySideBreakPoint + 1); // wide by default
|
component.onResize(sideBySideBreakPoint + 1); // wide by default
|
||||||
|
|
||||||
docViewer = fixture.debugElement.query(By.css('aio-doc-viewer')).nativeElement;
|
const de = fixture.debugElement;
|
||||||
hamburger = fixture.debugElement.query(By.css('.hamburger')).nativeElement;
|
docViewer = de.query(By.css('aio-doc-viewer')).nativeElement;
|
||||||
locationService = fixture.debugElement.injector.get(LocationService) as any;
|
hamburger = de.query(By.css('.hamburger')).nativeElement;
|
||||||
sidenav = fixture.debugElement.query(By.css('md-sidenav')).nativeElement;
|
locationService = de.injector.get(LocationService) as any as MockLocationService;
|
||||||
|
sidenav = de.query(By.css('md-sidenav')).nativeElement;
|
||||||
|
tocService = de.injector.get(TocService);
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('with proper DocViewer', () => {
|
describe('with proper DocViewer', () => {
|
||||||
@ -72,19 +75,74 @@ describe('AppComponent', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('onResize', () => {
|
describe('hasFloatingToc', () => {
|
||||||
it('should update `isSideBySide` accordingly', () => {
|
it('should initially be true', () => {
|
||||||
component.onResize(sideBySideBreakPoint + 1);
|
const fixture2 = TestBed.createComponent(AppComponent);
|
||||||
expect(component.isSideBySide).toBe(true);
|
const component2 = fixture2.componentInstance;
|
||||||
component.onResize(sideBySideBreakPoint - 1);
|
|
||||||
expect(component.isSideBySide).toBe(false);
|
expect(component2.hasFloatingToc).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update `showFloatingToc` accordingly', () => {
|
it('should be false on narrow screens', () => {
|
||||||
component.onResize(hideToCBreakPoint + 1);
|
|
||||||
expect(component.showFloatingToc).toBe(true);
|
|
||||||
component.onResize(hideToCBreakPoint - 1);
|
component.onResize(hideToCBreakPoint - 1);
|
||||||
expect(component.showFloatingToc).toBe(false);
|
|
||||||
|
tocService.tocList.next([{}, {}, {}] as TocItem[]);
|
||||||
|
expect(component.hasFloatingToc).toBe(false);
|
||||||
|
|
||||||
|
tocService.tocList.next([]);
|
||||||
|
expect(component.hasFloatingToc).toBe(false);
|
||||||
|
|
||||||
|
tocService.tocList.next([{}, {}, {}] as TocItem[]);
|
||||||
|
expect(component.hasFloatingToc).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be true on wide screens unless the toc is empty', () => {
|
||||||
|
component.onResize(hideToCBreakPoint + 1);
|
||||||
|
|
||||||
|
tocService.tocList.next([{}, {}, {}] as TocItem[]);
|
||||||
|
expect(component.hasFloatingToc).toBe(true);
|
||||||
|
|
||||||
|
tocService.tocList.next([]);
|
||||||
|
expect(component.hasFloatingToc).toBe(false);
|
||||||
|
|
||||||
|
tocService.tocList.next([{}, {}, {}] as TocItem[]);
|
||||||
|
expect(component.hasFloatingToc).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be false when toc is empty', () => {
|
||||||
|
tocService.tocList.next([]);
|
||||||
|
|
||||||
|
component.onResize(hideToCBreakPoint + 1);
|
||||||
|
expect(component.hasFloatingToc).toBe(false);
|
||||||
|
|
||||||
|
component.onResize(hideToCBreakPoint - 1);
|
||||||
|
expect(component.hasFloatingToc).toBe(false);
|
||||||
|
|
||||||
|
component.onResize(hideToCBreakPoint + 1);
|
||||||
|
expect(component.hasFloatingToc).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be true when toc is not empty unless the screen is narrow', () => {
|
||||||
|
tocService.tocList.next([{}, {}, {}] as TocItem[]);
|
||||||
|
|
||||||
|
component.onResize(hideToCBreakPoint + 1);
|
||||||
|
expect(component.hasFloatingToc).toBe(true);
|
||||||
|
|
||||||
|
component.onResize(hideToCBreakPoint - 1);
|
||||||
|
expect(component.hasFloatingToc).toBe(false);
|
||||||
|
|
||||||
|
component.onResize(hideToCBreakPoint + 1);
|
||||||
|
expect(component.hasFloatingToc).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isSideBySide', () => {
|
||||||
|
it('should be updated on resize', () => {
|
||||||
|
component.onResize(sideBySideBreakPoint - 1);
|
||||||
|
expect(component.isSideBySide).toBe(false);
|
||||||
|
|
||||||
|
component.onResize(sideBySideBreakPoint + 1);
|
||||||
|
expect(component.isSideBySide).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -472,18 +530,82 @@ describe('AppComponent', () => {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('restrainScrolling()', () => {
|
||||||
|
const preventedScrolling = (currentTarget: object, deltaY: number) => {
|
||||||
|
const evt = {
|
||||||
|
deltaY,
|
||||||
|
currentTarget,
|
||||||
|
defaultPrevented: false,
|
||||||
|
preventDefault() { this.defaultPrevented = true; }
|
||||||
|
} as any as WheelEvent;
|
||||||
|
|
||||||
|
component.restrainScrolling(evt);
|
||||||
|
|
||||||
|
return evt.defaultPrevented;
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should prevent scrolling up if already at the top', () => {
|
||||||
|
const elem = {scrollTop: 0};
|
||||||
|
|
||||||
|
expect(preventedScrolling(elem, -100)).toBe(true);
|
||||||
|
expect(preventedScrolling(elem, +100)).toBe(false);
|
||||||
|
expect(preventedScrolling(elem, -10)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should prevent scrolling down if already at the bottom', () => {
|
||||||
|
const elem = {scrollTop: 100, scrollHeight: 150, clientHeight: 50};
|
||||||
|
|
||||||
|
expect(preventedScrolling(elem, +10)).toBe(true);
|
||||||
|
expect(preventedScrolling(elem, -10)).toBe(false);
|
||||||
|
expect(preventedScrolling(elem, +5)).toBe(true);
|
||||||
|
|
||||||
|
elem.clientHeight -= 10;
|
||||||
|
expect(preventedScrolling(elem, +5)).toBe(false);
|
||||||
|
|
||||||
|
elem.scrollHeight -= 20;
|
||||||
|
expect(preventedScrolling(elem, +5)).toBe(true);
|
||||||
|
|
||||||
|
elem.scrollTop -= 30;
|
||||||
|
expect(preventedScrolling(elem, +5)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not prevent scrolling if neither at the top nor at the bottom', () => {
|
||||||
|
const elem = {scrollTop: 50, scrollHeight: 150, clientHeight: 50};
|
||||||
|
|
||||||
|
expect(preventedScrolling(elem, +100)).toBe(false);
|
||||||
|
expect(preventedScrolling(elem, -100)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('aio-toc', () => {
|
describe('aio-toc', () => {
|
||||||
let tocDebugElement: DebugElement;
|
let tocDebugElement: DebugElement;
|
||||||
let tocContainer: DebugElement;
|
let tocContainer: DebugElement;
|
||||||
|
|
||||||
beforeEach(() => {
|
const setHasFloatingToc = hasFloatingToc => {
|
||||||
|
component.hasFloatingToc = hasFloatingToc;
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
tocDebugElement = fixture.debugElement.query(By.directive(TocComponent));
|
tocDebugElement = fixture.debugElement.query(By.directive(TocComponent));
|
||||||
tocContainer = tocDebugElement.parent;
|
tocContainer = tocDebugElement && tocDebugElement.parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => setHasFloatingToc(true));
|
||||||
|
|
||||||
|
|
||||||
|
it('should show/hide `<aio-toc>` based on `hasFloatingToc`', () => {
|
||||||
|
expect(tocDebugElement).toBeTruthy();
|
||||||
|
expect(tocContainer).toBeTruthy();
|
||||||
|
|
||||||
|
setHasFloatingToc(false);
|
||||||
|
expect(tocDebugElement).toBeFalsy();
|
||||||
|
expect(tocContainer).toBeFalsy();
|
||||||
|
|
||||||
|
setHasFloatingToc(true);
|
||||||
|
expect(tocDebugElement).toBeTruthy();
|
||||||
|
expect(tocContainer).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should have a non-embedded `<aio-toc>` element', () => {
|
it('should have a non-embedded `<aio-toc>` element', () => {
|
||||||
expect(tocDebugElement).toBeDefined();
|
|
||||||
expect(tocDebugElement.classes['embedded']).toBeFalsy();
|
expect(tocDebugElement.classes['embedded']).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -495,6 +617,16 @@ describe('AppComponent', () => {
|
|||||||
|
|
||||||
expect(tocContainer.styles['max-height']).toBe('100px');
|
expect(tocContainer.styles['max-height']).toBe('100px');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should restrain scrolling inside the ToC container', () => {
|
||||||
|
const restrainScrolling = spyOn(component, 'restrainScrolling');
|
||||||
|
const evt = {};
|
||||||
|
|
||||||
|
expect(restrainScrolling).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
tocContainer.triggerEventHandler('mousewheel', evt);
|
||||||
|
expect(restrainScrolling).toHaveBeenCalledWith(evt);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('footer', () => {
|
describe('footer', () => {
|
||||||
|
@ -12,7 +12,9 @@ import { SearchResultsComponent } from 'app/search/search-results/search-results
|
|||||||
import { SearchBoxComponent } from 'app/search/search-box/search-box.component';
|
import { SearchBoxComponent } from 'app/search/search-box/search-box.component';
|
||||||
import { SearchService } from 'app/search/search.service';
|
import { SearchService } from 'app/search/search.service';
|
||||||
import { SwUpdateNotificationsService } from 'app/sw-updates/sw-update-notifications.service';
|
import { SwUpdateNotificationsService } from 'app/sw-updates/sw-update-notifications.service';
|
||||||
|
import { TocService } from 'app/shared/toc.service';
|
||||||
|
|
||||||
|
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||||
import { combineLatest } from 'rxjs/observable/combineLatest';
|
import { combineLatest } from 'rxjs/observable/combineLatest';
|
||||||
|
|
||||||
const sideNavView = 'SideNav';
|
const sideNavView = 'SideNav';
|
||||||
@ -65,8 +67,9 @@ export class AppComponent implements OnInit {
|
|||||||
topMenuNodes: NavigationNode[];
|
topMenuNodes: NavigationNode[];
|
||||||
topMenuNarrowNodes: NavigationNode[];
|
topMenuNarrowNodes: NavigationNode[];
|
||||||
|
|
||||||
showFloatingToc = false;
|
hasFloatingToc = true;
|
||||||
showFloatingTocWidth = 800;
|
private showFloatingToc = new BehaviorSubject(false);
|
||||||
|
private showFloatingTocWidth = 800;
|
||||||
tocMaxHeight: string;
|
tocMaxHeight: string;
|
||||||
private tocMaxHeightOffset = 0;
|
private tocMaxHeightOffset = 0;
|
||||||
|
|
||||||
@ -103,8 +106,9 @@ export class AppComponent implements OnInit {
|
|||||||
private navigationService: NavigationService,
|
private navigationService: NavigationService,
|
||||||
private scrollService: ScrollService,
|
private scrollService: ScrollService,
|
||||||
private searchService: SearchService,
|
private searchService: SearchService,
|
||||||
private swUpdateNotifications: SwUpdateNotificationsService
|
private swUpdateNotifications: SwUpdateNotificationsService,
|
||||||
) { }
|
private tocService: TocService
|
||||||
|
) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// Do not initialize the search on browsers that lack web worker support
|
// Do not initialize the search on browsers that lack web worker support
|
||||||
@ -174,6 +178,10 @@ export class AppComponent implements OnInit {
|
|||||||
this.navigationService.versionInfo.subscribe( vi => this.versionInfo = vi );
|
this.navigationService.versionInfo.subscribe( vi => this.versionInfo = vi );
|
||||||
|
|
||||||
this.swUpdateNotifications.enable();
|
this.swUpdateNotifications.enable();
|
||||||
|
|
||||||
|
const hasNonEmptyToc = this.tocService.tocList.map(tocList => tocList.length > 0);
|
||||||
|
combineLatest(hasNonEmptyToc, this.showFloatingToc)
|
||||||
|
.subscribe(([hasToc, showFloatingToc]) => this.hasFloatingToc = hasToc && showFloatingToc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scroll to the anchor in the hash fragment or top of doc.
|
// Scroll to the anchor in the hash fragment or top of doc.
|
||||||
@ -207,7 +215,7 @@ export class AppComponent implements OnInit {
|
|||||||
@HostListener('window:resize', ['$event.target.innerWidth'])
|
@HostListener('window:resize', ['$event.target.innerWidth'])
|
||||||
onResize(width) {
|
onResize(width) {
|
||||||
this.isSideBySide = width > this.sideBySideWidth;
|
this.isSideBySide = width > this.sideBySideWidth;
|
||||||
this.showFloatingToc = width > this.showFloatingTocWidth;
|
this.showFloatingToc.next(width > this.showFloatingTocWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('click', ['$event.target', '$event.button', '$event.ctrlKey', '$event.metaKey', '$event.altKey'])
|
@HostListener('click', ['$event.target', '$event.button', '$event.ctrlKey', '$event.metaKey', '$event.altKey'])
|
||||||
@ -275,6 +283,25 @@ export class AppComponent implements OnInit {
|
|||||||
this.tocMaxHeight = (document.body.scrollHeight - window.pageYOffset - this.tocMaxHeightOffset).toFixed(2);
|
this.tocMaxHeight = (document.body.scrollHeight - window.pageYOffset - this.tocMaxHeightOffset).toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restrain scrolling inside an element, when the cursor is over it
|
||||||
|
restrainScrolling(evt: WheelEvent) {
|
||||||
|
const elem = evt.currentTarget as Element;
|
||||||
|
const scrollTop = elem.scrollTop;
|
||||||
|
|
||||||
|
if (evt.deltaY < 0) {
|
||||||
|
// Trying to scroll up: Prevent scrolling if already at the top.
|
||||||
|
if (scrollTop < 1) {
|
||||||
|
evt.preventDefault();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Trying to scroll down: Prevent scrolling if already at the bottom.
|
||||||
|
const maxScrollTop = elem.scrollHeight - elem.clientHeight;
|
||||||
|
if (maxScrollTop - scrollTop < 1) {
|
||||||
|
evt.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Search related methods and handlers
|
// Search related methods and handlers
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="heading-children" [ngClass]="classes">
|
<div class="heading-children" [ngClass]="classes">
|
||||||
<aio-nav-item *ngFor="let node of node.children" [level]="level + 1"
|
<aio-nav-item *ngFor="let node of node.children" [level]="level + 1" [isWide]="isWide"
|
||||||
[node]="node" [selectedNodes]="selectedNodes"></aio-nav-item>
|
[node]="node" [selectedNodes]="selectedNodes"></aio-nav-item>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,159 +1,196 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
import { SimpleChange, SimpleChanges } from '@angular/core';
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { SimpleChange, SimpleChanges, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
|
||||||
import { NavItemComponent } from './nav-item.component';
|
import { NavItemComponent } from './nav-item.component';
|
||||||
import { NavigationNode } from 'app/navigation/navigation.model';
|
import { NavigationNode } from 'app/navigation/navigation.model';
|
||||||
|
|
||||||
// Testing the component class behaviors, independent of its template
|
describe('NavItemComponent', () => {
|
||||||
// No dependencies. Just new it and test :)
|
|
||||||
// Let e2e tests verify how it displays.
|
|
||||||
describe('NavItemComponent (class-only)', () => {
|
|
||||||
|
|
||||||
let component: NavItemComponent;
|
// Testing the component class behaviors, independent of its template
|
||||||
|
// No dependencies. Just new it and test :)
|
||||||
|
// Let e2e tests verify how it displays.
|
||||||
|
describe('(class-only)', () => {
|
||||||
|
|
||||||
let selectedNodes: NavigationNode[];
|
let component: NavItemComponent;
|
||||||
let setClassesSpy: jasmine.Spy;
|
|
||||||
|
|
||||||
function initialize(nd: NavigationNode) {
|
let selectedNodes: NavigationNode[];
|
||||||
component.node = nd;
|
let setClassesSpy: jasmine.Spy;
|
||||||
onChanges(); // Angular calls when initializing the component
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enough to triggers component's ngOnChange method
|
function initialize(nd: NavigationNode) {
|
||||||
function onChanges() {
|
component.node = nd;
|
||||||
component.ngOnChanges({node: <SimpleChange><any> 'anything' });
|
onChanges(); // Angular calls when initializing the component
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(() => {
|
// Enough to triggers component's ngOnChange method
|
||||||
|
function onChanges() {
|
||||||
|
component.ngOnChanges({node: <SimpleChange><any> 'anything' });
|
||||||
|
}
|
||||||
|
|
||||||
component = new NavItemComponent();
|
beforeEach(() => {
|
||||||
setClassesSpy = spyOn(component, 'setClasses').and.callThrough();
|
|
||||||
|
|
||||||
// Selected nodes is the selected node and its header ancestors
|
component = new NavItemComponent();
|
||||||
selectedNodes = [
|
setClassesSpy = spyOn(component, 'setClasses').and.callThrough();
|
||||||
{ title: 'a' }, // selected node: an item or a header
|
|
||||||
{ title: 'parent' }, // selected node's header parent
|
|
||||||
{ title: 'grandparent' }, // selected node's header grandparent
|
|
||||||
];
|
|
||||||
component.selectedNodes = selectedNodes;
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('should have expected classes when initialized', () => {
|
// Selected nodes is the selected node and its header ancestors
|
||||||
it('with selected node', () => {
|
selectedNodes = [
|
||||||
initialize(selectedNodes[0]);
|
{ title: 'a' }, // selected node: an item or a header
|
||||||
expect(component.classes).toEqual(
|
{ title: 'parent' }, // selected node's header parent
|
||||||
// selecting the current node has no effect on expanded state,
|
{ title: 'grandparent' }, // selected node's header grandparent
|
||||||
// even if current node is a header.
|
];
|
||||||
{ 'level-1': true, collapsed: true, expanded: false, selected: true}
|
component.selectedNodes = selectedNodes;
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('with selected node ancestor', () => {
|
describe('should have expected classes when initialized', () => {
|
||||||
initialize(selectedNodes[1]);
|
it('with selected node', () => {
|
||||||
expect(component.classes).toEqual(
|
initialize(selectedNodes[0]);
|
||||||
// ancestor is a header and should be expanded
|
expect(component.classes).toEqual(
|
||||||
{ 'level-1': true, collapsed: false, expanded: true, selected: true}
|
// selected node should be expanded even if is a header.
|
||||||
);
|
{ 'level-1': true, collapsed: false, expanded: true, selected: true }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with selected node ancestor', () => {
|
||||||
|
initialize(selectedNodes[1]);
|
||||||
|
expect(component.classes).toEqual(
|
||||||
|
// ancestor is a header and should be expanded
|
||||||
|
{ 'level-1': true, collapsed: false, expanded: true, selected: true }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with other than a selected node or ancestor', () => {
|
||||||
|
initialize({ title: 'x' });
|
||||||
|
expect(component.classes).toEqual(
|
||||||
|
{ 'level-1': true, collapsed: true, expanded: false, selected: false }
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('with other than a selected node or ancestor', () => {
|
describe('when becomes a non-selected node', () => {
|
||||||
initialize({ title: 'x' });
|
|
||||||
expect(component.classes).toEqual(
|
// this node won't be the selected node when ngOnChanges() called
|
||||||
{ 'level-1': true, collapsed: true, expanded: false, selected: false}
|
beforeEach(() => component.node = { title: 'x' });
|
||||||
);
|
|
||||||
|
it('should de-select if previously selected', () => {
|
||||||
|
component.isSelected = true;
|
||||||
|
onChanges();
|
||||||
|
expect(component.isSelected).toBe(false, 'becomes de-selected');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should collapse if previously expanded in narrow mode', () => {
|
||||||
|
component.isWide = false;
|
||||||
|
component.isExpanded = true;
|
||||||
|
onChanges();
|
||||||
|
expect(component.isExpanded).toBe(false, 'becomes collapsed');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remain expanded in wide mode', () => {
|
||||||
|
component.isWide = true;
|
||||||
|
component.isExpanded = true;
|
||||||
|
onChanges();
|
||||||
|
expect(component.isExpanded).toBe(true, 'remains expanded');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when becomes a selected node', () => {
|
||||||
|
|
||||||
|
// this node will be the selected node when ngOnChanges() called
|
||||||
|
beforeEach(() => component.node = selectedNodes[0]);
|
||||||
|
|
||||||
|
it('should select when previously not selected', () => {
|
||||||
|
component.isSelected = false;
|
||||||
|
onChanges();
|
||||||
|
expect(component.isSelected).toBe(true, 'becomes selected');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should expand the current node or keep it expanded', () => {
|
||||||
|
component.isExpanded = false;
|
||||||
|
onChanges();
|
||||||
|
expect(component.isExpanded).toBe(true, 'becomes true');
|
||||||
|
|
||||||
|
component.isExpanded = true;
|
||||||
|
onChanges();
|
||||||
|
expect(component.isExpanded).toBe(true, 'remains true');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when becomes a selected ancestor node', () => {
|
||||||
|
|
||||||
|
// this node will be a selected node ancestor header when ngOnChanges() called
|
||||||
|
beforeEach(() => component.node = selectedNodes[2]);
|
||||||
|
|
||||||
|
it('should select when previously not selected', () => {
|
||||||
|
component.isSelected = false;
|
||||||
|
onChanges();
|
||||||
|
expect(component.isSelected).toBe(true, 'becomes selected');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should always expand this header', () => {
|
||||||
|
component.isExpanded = false;
|
||||||
|
onChanges();
|
||||||
|
expect(component.isExpanded).toBe(true, 'becomes expanded');
|
||||||
|
|
||||||
|
component.isExpanded = false;
|
||||||
|
onChanges();
|
||||||
|
expect(component.isExpanded).toBe(true, 'stays expanded');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when headerClicked()', () => {
|
||||||
|
// current node doesn't matter in these tests.
|
||||||
|
|
||||||
|
it('should expand when headerClicked() and previously collapsed', () => {
|
||||||
|
component.isExpanded = false;
|
||||||
|
component.headerClicked();
|
||||||
|
expect(component.isExpanded).toBe(true, 'should be expanded');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should collapse when headerClicked() and previously expanded', () => {
|
||||||
|
component.isExpanded = true;
|
||||||
|
component.headerClicked();
|
||||||
|
expect(component.isExpanded).toBe(false, 'should be collapsed');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not change isSelected when headerClicked()', () => {
|
||||||
|
component.isSelected = true;
|
||||||
|
component.headerClicked();
|
||||||
|
expect(component.isSelected).toBe(true, 'remains selected');
|
||||||
|
|
||||||
|
component.isSelected = false;
|
||||||
|
component.headerClicked();
|
||||||
|
expect(component.isSelected).toBe(false, 'remains not selected');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set classes', () => {
|
||||||
|
component.headerClicked();
|
||||||
|
expect(setClassesSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when becomes a non-selected node', () => {
|
describe('(via TestBed)', () => {
|
||||||
|
it('should pass the `isWide` property to all child nav-items', () => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [NavItemComponent],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
});
|
||||||
|
const fixture = TestBed.createComponent(NavItemComponent);
|
||||||
|
fixture.componentInstance.node = {
|
||||||
|
title: 'x',
|
||||||
|
children: [{ title: 'a' }, { title: 'b' }]
|
||||||
|
};
|
||||||
|
|
||||||
// this node won't be the selected node when ngOnChanges() called
|
fixture.componentInstance.isWide = true;
|
||||||
beforeEach(() => component.node = { title: 'x' });
|
fixture.detectChanges();
|
||||||
|
let children = fixture.debugElement.queryAll(By.directive(NavItemComponent));
|
||||||
|
expect(children.length).toEqual(2);
|
||||||
|
children.forEach(child => expect(child.componentInstance.isWide).toBe(true));
|
||||||
|
|
||||||
it('should collapse if previously expanded', () => {
|
fixture.componentInstance.isWide = false;
|
||||||
component.isExpanded = true;
|
fixture.detectChanges();
|
||||||
onChanges();
|
children = fixture.debugElement.queryAll(By.directive(NavItemComponent));
|
||||||
expect(component.isExpanded).toBe(false, 'becomes collapsed');
|
expect(children.length).toEqual(2);
|
||||||
});
|
children.forEach(child => expect(child.componentInstance.isWide).toBe(false));
|
||||||
|
|
||||||
it('should de-select if previously selected', () => {
|
|
||||||
component.isSelected = true;
|
|
||||||
onChanges();
|
|
||||||
expect(component.isSelected).toBe(false, 'becomes de-selected');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when becomes a selected node', () => {
|
|
||||||
|
|
||||||
// this node will be the selected node when ngOnChanges() called
|
|
||||||
beforeEach(() => component.node = selectedNodes[0]);
|
|
||||||
|
|
||||||
it('should select when previously not selected', () => {
|
|
||||||
component.isSelected = false;
|
|
||||||
onChanges();
|
|
||||||
expect(component.isSelected).toBe(true, 'becomes selected');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should leave the expanded/collapsed state untouched', () => {
|
|
||||||
component.isExpanded = false;
|
|
||||||
onChanges();
|
|
||||||
expect(component.isExpanded).toBe(false, 'remains false');
|
|
||||||
|
|
||||||
component.isExpanded = true;
|
|
||||||
onChanges();
|
|
||||||
expect(component.isExpanded).toBe(true, 'remains true');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when becomes a selected ancestor node', () => {
|
|
||||||
|
|
||||||
// this node will be a selected node ancestor header when ngOnChanges() called
|
|
||||||
beforeEach(() => component.node = selectedNodes[2]);
|
|
||||||
|
|
||||||
it('should select when previously not selected', () => {
|
|
||||||
component.isSelected = false;
|
|
||||||
onChanges();
|
|
||||||
expect(component.isSelected).toBe(true, 'becomes selected');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should always expand this header', () => {
|
|
||||||
component.isExpanded = false;
|
|
||||||
onChanges();
|
|
||||||
expect(component.isExpanded).toBe(true, 'becomes expanded');
|
|
||||||
|
|
||||||
component.isExpanded = false;
|
|
||||||
onChanges();
|
|
||||||
expect(component.isExpanded).toBe(true, 'stays expanded');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when headerClicked()', () => {
|
|
||||||
// current node doesn't matter in these tests.
|
|
||||||
|
|
||||||
it('should expand when headerClicked() and previously collapsed', () => {
|
|
||||||
component.isExpanded = false;
|
|
||||||
component.headerClicked();
|
|
||||||
expect(component.isExpanded).toBe(true, 'should be expanded');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should collapse when headerClicked() and previously expanded', () => {
|
|
||||||
component.isExpanded = true;
|
|
||||||
component.headerClicked();
|
|
||||||
expect(component.isExpanded).toBe(false, 'should be collapsed');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not change isSelected when headerClicked()', () => {
|
|
||||||
component.isSelected = true;
|
|
||||||
component.headerClicked();
|
|
||||||
expect(component.isSelected).toBe(true, 'remains selected');
|
|
||||||
|
|
||||||
component.isSelected = false;
|
|
||||||
component.headerClicked();
|
|
||||||
expect(component.isSelected).toBe(false, 'remains not selected');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set classes', () => {
|
|
||||||
component.headerClicked();
|
|
||||||
expect(setClassesSpy).toHaveBeenCalled();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -6,20 +6,23 @@ import { NavigationNode } from 'app/navigation/navigation.model';
|
|||||||
templateUrl: 'nav-item.component.html',
|
templateUrl: 'nav-item.component.html',
|
||||||
})
|
})
|
||||||
export class NavItemComponent implements OnChanges {
|
export class NavItemComponent implements OnChanges {
|
||||||
@Input() selectedNodes: NavigationNode[];
|
@Input() isWide = false;
|
||||||
@Input() node: NavigationNode;
|
|
||||||
@Input() level = 1;
|
@Input() level = 1;
|
||||||
|
@Input() node: NavigationNode;
|
||||||
|
@Input() selectedNodes: NavigationNode[];
|
||||||
|
|
||||||
isExpanded = false;
|
isExpanded = false;
|
||||||
isSelected = false;
|
isSelected = false;
|
||||||
classes: {[index: string]: boolean };
|
classes: {[index: string]: boolean };
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
if (changes['selectedNodes'] || changes['node']) {
|
if (changes['selectedNodes'] || changes['node'] || changes['isWide']) {
|
||||||
if (this.selectedNodes) {
|
if (this.selectedNodes) {
|
||||||
const ix = this.selectedNodes.indexOf(this.node);
|
const ix = this.selectedNodes.indexOf(this.node);
|
||||||
this.isSelected = ix !== -1;
|
this.isSelected = ix !== -1; // this node is the selected node or its ancestor
|
||||||
if (ix !== 0) { this.isExpanded = this.isSelected; }
|
this.isExpanded = this.isSelected || // expand if selected or ...
|
||||||
|
// preserve expanded state when display is wide; collapse in mobile.
|
||||||
|
(this.isWide && this.isExpanded);
|
||||||
} else {
|
} else {
|
||||||
this.isSelected = false;
|
this.isSelected = false;
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,12 @@ import { CurrentNode, NavigationNode } from 'app/navigation/navigation.service';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'aio-nav-menu',
|
selector: 'aio-nav-menu',
|
||||||
template: `
|
template: `
|
||||||
<aio-nav-item *ngFor="let node of filteredNodes" [node]="node" [selectedNodes]="currentNode?.nodes">
|
<aio-nav-item *ngFor="let node of filteredNodes" [node]="node" [selectedNodes]="currentNode?.nodes" [isWide]="isWide">
|
||||||
</aio-nav-item>`
|
</aio-nav-item>`
|
||||||
})
|
})
|
||||||
export class NavMenuComponent {
|
export class NavMenuComponent {
|
||||||
@Input() currentNode: CurrentNode;
|
@Input() currentNode: CurrentNode;
|
||||||
@Input() nodes: NavigationNode[] ;
|
@Input() isWide = false;
|
||||||
|
@Input() nodes: NavigationNode[];
|
||||||
get filteredNodes() { return this.nodes ? this.nodes.filter(n => !n.hidden) : []; }
|
get filteredNodes() { return this.nodes ? this.nodes.filter(n => !n.hidden) : []; }
|
||||||
}
|
}
|
||||||
|
@ -42,12 +42,12 @@ md-sidenav.mat-sidenav.sidenav {
|
|||||||
md-sidenav-container.sidenav-container {
|
md-sidenav-container.sidenav-container {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
height: auto !important;
|
height: auto !important;
|
||||||
max-width: 82%;
|
max-width: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
transform: none;
|
transform: none;
|
||||||
|
|
||||||
@media (max-width: 800px) {
|
&.has-floating-toc {
|
||||||
max-width: 100%;
|
max-width: 82%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,6 +135,7 @@ button.vertical-menu-item {
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
transition: background-color 0.2s;
|
transition: background-color 0.2s;
|
||||||
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-2 {
|
.level-2 {
|
||||||
|
@ -43,9 +43,11 @@ aio-top-menu {
|
|||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
background: rgba($white, 0.15);
|
// Temporarily remove the focus styling until we update to an @angular/material version that
|
||||||
border-radius: 4px;
|
// includes https://github.com/angular/material2/commit/3bc82f6dc.
|
||||||
padding: 8px 16px;
|
// background: rgba($white, 0.15);
|
||||||
|
// border-radius: 4px;
|
||||||
|
// padding: 8px 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,10 +88,8 @@ aio-shell.page-resources md-toolbar.mat-toolbar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 992px) {
|
@media (min-width: 992px) {
|
||||||
padding-left: 24px;
|
|
||||||
|
|
||||||
button.hamburger {
|
button.hamburger {
|
||||||
display: none;
|
margin: 0 24px 0 -88px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
.api-info-bar {
|
.api-info-bar {
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
text-align: center;
|
text-align: left;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
margin: 0 16px;
|
margin: 0 16px 0 0;
|
||||||
|
|
||||||
@media screen and (max-width: 600px) {
|
@media screen and (max-width: 600px) {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.hamburger.mat-button {
|
.hamburger.mat-button {
|
||||||
transition: color 0.2s;
|
height: 100%;
|
||||||
height: 100%;
|
margin: 0;
|
||||||
margin: 0;
|
padding: 0;
|
||||||
padding: 0;
|
|
||||||
|
&:not(.starting) {
|
||||||
|
transition-duration: .4s;
|
||||||
|
transition-property: color, margin;
|
||||||
|
transition-timing-function: cubic-bezier(.25, .8, .25, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.hamburger.mat-button:hover {
|
.hamburger.mat-button:hover {
|
||||||
color: $offwhite;
|
color: $offwhite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hamburger .mat-icon {
|
.hamburger .mat-icon {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
/* #docregion , quickstart, toh */
|
|
||||||
/* Master Styles */
|
/* Master Styles */
|
||||||
h1 {
|
h1 {
|
||||||
color: #369;
|
color: #369;
|
||||||
@ -13,12 +12,10 @@ h2, h3 {
|
|||||||
body {
|
body {
|
||||||
margin: 2em;
|
margin: 2em;
|
||||||
}
|
}
|
||||||
/* #enddocregion quickstart */
|
|
||||||
body, input[text], button {
|
body, input[text], button {
|
||||||
color: #888;
|
color: #888;
|
||||||
font-family: Cambria, Georgia;
|
font-family: Cambria, Georgia;
|
||||||
}
|
}
|
||||||
/* #enddocregion toh */
|
|
||||||
a {
|
a {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
cursor: hand;
|
cursor: hand;
|
||||||
@ -62,54 +59,6 @@ nav a.active {
|
|||||||
color: #039be5;
|
color: #039be5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* items class */
|
|
||||||
.items {
|
|
||||||
margin: 0 0 2em 0;
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0;
|
|
||||||
width: 24em;
|
|
||||||
}
|
|
||||||
.items li {
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
left: 0;
|
|
||||||
background-color: #EEE;
|
|
||||||
margin: .5em;
|
|
||||||
padding: .3em 0;
|
|
||||||
height: 1.6em;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
.items li:hover {
|
|
||||||
color: #607D8B;
|
|
||||||
background-color: #DDD;
|
|
||||||
left: .1em;
|
|
||||||
}
|
|
||||||
.items li.selected {
|
|
||||||
background-color: #CFD8DC;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
.items li.selected:hover {
|
|
||||||
background-color: #BBD8DC;
|
|
||||||
}
|
|
||||||
.items .text {
|
|
||||||
position: relative;
|
|
||||||
top: -3px;
|
|
||||||
}
|
|
||||||
.items .badge {
|
|
||||||
display: inline-block;
|
|
||||||
font-size: small;
|
|
||||||
color: white;
|
|
||||||
padding: 0.8em 0.7em 0 0.7em;
|
|
||||||
background-color: #607D8B;
|
|
||||||
line-height: 1em;
|
|
||||||
position: relative;
|
|
||||||
left: -1px;
|
|
||||||
top: -4px;
|
|
||||||
height: 1.8em;
|
|
||||||
margin-right: .8em;
|
|
||||||
border-radius: 4px 0 0 4px;
|
|
||||||
}
|
|
||||||
/* #docregion toh */
|
|
||||||
/* everywhere else */
|
/* everywhere else */
|
||||||
* {
|
* {
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
'rxjs': 'npm:rxjs@5.0.1',
|
'rxjs': 'npm:rxjs@5.0.1',
|
||||||
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
|
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
|
||||||
'ts': 'npm:plugin-typescript@5.2.7/lib/plugin.js',
|
'ts': 'npm:plugin-typescript@5.2.7/lib/plugin.js',
|
||||||
'typescript': 'npm:typescript@2.2.1/lib/typescript.js',
|
'typescript': 'npm:typescript@2.3.2/lib/typescript.js',
|
||||||
|
|
||||||
},
|
},
|
||||||
// packages tells the System loader how to load when no filename and/or no extension
|
// packages tells the System loader how to load when no filename and/or no extension
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
'rxjs': 'npm:rxjs@5.0.1',
|
'rxjs': 'npm:rxjs@5.0.1',
|
||||||
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
|
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
|
||||||
'ts': 'npm:plugin-typescript@5.2.7/lib/plugin.js',
|
'ts': 'npm:plugin-typescript@5.2.7/lib/plugin.js',
|
||||||
'typescript': 'npm:typescript@2.2.1/lib/typescript.js',
|
'typescript': 'npm:typescript@2.3.2/lib/typescript.js',
|
||||||
|
|
||||||
},
|
},
|
||||||
// packages tells the System loader how to load when no filename and/or no extension
|
// packages tells the System loader how to load when no filename and/or no extension
|
||||||
|
@ -12,19 +12,19 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "~4.0.0",
|
"@angular/animations": "~4.2.0",
|
||||||
"@angular/common": "~4.0.0",
|
"@angular/common": "~4.2.0",
|
||||||
"@angular/compiler": "~4.0.0",
|
"@angular/compiler": "~4.2.0",
|
||||||
"@angular/compiler-cli": "~4.0.0",
|
"@angular/compiler-cli": "~4.2.0",
|
||||||
"@angular/core": "~4.0.0",
|
"@angular/core": "~4.2.0",
|
||||||
"@angular/forms": "~4.0.0",
|
"@angular/forms": "~4.2.0",
|
||||||
"@angular/http": "~4.0.0",
|
"@angular/http": "~4.2.0",
|
||||||
"@angular/platform-browser": "~4.0.0",
|
"@angular/platform-browser": "~4.2.0",
|
||||||
"@angular/platform-browser-dynamic": "~4.0.0",
|
"@angular/platform-browser-dynamic": "~4.2.0",
|
||||||
"@angular/platform-server": "~4.0.0",
|
"@angular/platform-server": "~4.2.0",
|
||||||
"@angular/router": "~4.0.0",
|
"@angular/router": "~4.2.0",
|
||||||
"@angular/tsc-wrapped": "~4.0.0",
|
"@angular/tsc-wrapped": "~4.2.0",
|
||||||
"@angular/upgrade": "~4.0.0",
|
"@angular/upgrade": "~4.2.0",
|
||||||
"angular-in-memory-web-api": "~0.3.2",
|
"angular-in-memory-web-api": "~0.3.2",
|
||||||
"core-js": "^2.4.1",
|
"core-js": "^2.4.1",
|
||||||
"rxjs": "5.0.1",
|
"rxjs": "5.0.1",
|
||||||
@ -80,7 +80,7 @@
|
|||||||
"style-loader": "^0.13.1",
|
"style-loader": "^0.13.1",
|
||||||
"ts-node": "^1.3.0",
|
"ts-node": "^1.3.0",
|
||||||
"tslint": "^3.15.1",
|
"tslint": "^3.15.1",
|
||||||
"typescript": "~2.2.0",
|
"typescript": "~2.3.2",
|
||||||
"webpack": "2.2.1",
|
"webpack": "2.2.1",
|
||||||
"webpack-dev-server": "2.4.1",
|
"webpack-dev-server": "2.4.1",
|
||||||
"webpack-merge": "^3.0.0"
|
"webpack-merge": "^3.0.0"
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -6,17 +6,29 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
const Package = require('dgeni').Package;
|
const Package = require('dgeni').Package;
|
||||||
|
const globby = require('globby');
|
||||||
|
const ignore = require('ignore');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('canonical-path');
|
||||||
const basePackage = require('../angular-base-package');
|
const basePackage = require('../angular-base-package');
|
||||||
const contentPackage = require('../content-package');
|
const contentPackage = require('../content-package');
|
||||||
|
|
||||||
const { CONTENTS_PATH } = require('../config');
|
const { CONTENTS_PATH, GUIDE_EXAMPLES_PATH } = require('../config');
|
||||||
|
|
||||||
module.exports = new Package('angular-content', [basePackage, contentPackage])
|
module.exports = new Package('angular-content', [basePackage, contentPackage])
|
||||||
|
|
||||||
// Where do we get the source files?
|
// Where do we get the source files?
|
||||||
.config(function(readFilesProcessor, collectExamples) {
|
.config(function(readFilesProcessor, collectExamples) {
|
||||||
|
|
||||||
|
const gitignoreFile = fs.readFileSync(path.resolve(GUIDE_EXAMPLES_PATH, '.gitignore'), 'utf8');
|
||||||
|
const gitignore = ignore().add(gitignoreFile);
|
||||||
|
|
||||||
|
const examplePaths = globby.sync('**/*', { cwd: GUIDE_EXAMPLES_PATH, mark: true, dot: true })
|
||||||
|
.filter(filePath => filePath !== '.gitignore') // we are not interested in the .gitignore file itself
|
||||||
|
.filter(filePath => !/\/$/.test(filePath)); // this filter removes the folders, leaving only files
|
||||||
|
const filteredExamplePaths = gitignore.filter(examplePaths) // filter out files that match the .gitignore rules
|
||||||
|
.map(filePath => path.resolve(GUIDE_EXAMPLES_PATH, filePath)); // we need the full paths for the filereader
|
||||||
|
|
||||||
readFilesProcessor.sourceFiles = readFilesProcessor.sourceFiles.concat([
|
readFilesProcessor.sourceFiles = readFilesProcessor.sourceFiles.concat([
|
||||||
{
|
{
|
||||||
basePath: CONTENTS_PATH,
|
basePath: CONTENTS_PATH,
|
||||||
@ -36,26 +48,7 @@ module.exports = new Package('angular-content', [basePackage, contentPackage])
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
basePath: CONTENTS_PATH,
|
basePath: CONTENTS_PATH,
|
||||||
include: CONTENTS_PATH + '/examples/**/*',
|
include: filteredExamplePaths,
|
||||||
exclude: [
|
|
||||||
'**/*plnkr.no-link.html',
|
|
||||||
'**/node_modules/**',
|
|
||||||
// boilerplate files
|
|
||||||
'**/*/src/systemjs-angular-loader.js',
|
|
||||||
'**/*/src/systemjs.config.js',
|
|
||||||
'**/*/src/tsconfig.json',
|
|
||||||
'**/*/bs-config.e2e.json',
|
|
||||||
'**/*/bs-config.json',
|
|
||||||
'**/*/package.json',
|
|
||||||
'**/*/tslint.json',
|
|
||||||
// example files
|
|
||||||
'**/_test-output',
|
|
||||||
'**/protractor-helpers.js',
|
|
||||||
'**/e2e-spec.js',
|
|
||||||
'**/ts/**/*.js',
|
|
||||||
'**/js-es6*/**/*.js',
|
|
||||||
'**/ts-snippets/**/*.js',
|
|
||||||
],
|
|
||||||
fileReader: 'exampleFileReader'
|
fileReader: 'exampleFileReader'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -6,6 +6,7 @@ const AIO_PATH = resolve(PROJECT_ROOT, 'aio');
|
|||||||
const TEMPLATES_PATH = resolve(AIO_PATH, 'tools/transforms/templates');
|
const TEMPLATES_PATH = resolve(AIO_PATH, 'tools/transforms/templates');
|
||||||
const API_TEMPLATES_PATH = resolve(TEMPLATES_PATH, 'api');
|
const API_TEMPLATES_PATH = resolve(TEMPLATES_PATH, 'api');
|
||||||
const CONTENTS_PATH = resolve(AIO_PATH, 'content');
|
const CONTENTS_PATH = resolve(AIO_PATH, 'content');
|
||||||
|
const GUIDE_EXAMPLES_PATH = resolve(CONTENTS_PATH, 'examples');
|
||||||
const SRC_PATH = resolve(AIO_PATH, 'src');
|
const SRC_PATH = resolve(AIO_PATH, 'src');
|
||||||
const OUTPUT_PATH = resolve(SRC_PATH, 'generated');
|
const OUTPUT_PATH = resolve(SRC_PATH, 'generated');
|
||||||
const DOCS_OUTPUT_PATH = resolve(OUTPUT_PATH, 'docs');
|
const DOCS_OUTPUT_PATH = resolve(OUTPUT_PATH, 'docs');
|
||||||
@ -18,5 +19,5 @@ function requireFolder(dirname, folderPath) {
|
|||||||
.map(p => require(resolve(absolutePath, p)));
|
.map(p => require(resolve(absolutePath, p)));
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { PROJECT_ROOT, AIO_PATH, TEMPLATES_PATH, API_TEMPLATES_PATH, CONTENTS_PATH, SRC_PATH, OUTPUT_PATH, DOCS_OUTPUT_PATH, API_SOURCE_PATH, requireFolder };
|
module.exports = { PROJECT_ROOT, AIO_PATH, TEMPLATES_PATH, API_TEMPLATES_PATH, CONTENTS_PATH, GUIDE_EXAMPLES_PATH, SRC_PATH, OUTPUT_PATH, DOCS_OUTPUT_PATH, API_SOURCE_PATH, requireFolder };
|
||||||
|
|
||||||
|
@ -11,8 +11,4 @@
|
|||||||
NgModule: {@link {$ doc.ngModule $}}
|
NgModule: {@link {$ doc.ngModule $}}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</div>
|
||||||
<span class="info-bar-item">
|
|
||||||
{$ github.githubViewLink(doc, versionInfo) $}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
111
aio/yarn.lock
111
aio/yarn.lock
@ -2,9 +2,11 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
"@angular/animations@next":
|
"@angular/animations@4.2.0":
|
||||||
version "4.2.0-beta.1"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-4.2.0-beta.1.tgz#0e84c3f306d407da1546db3e8b5490effbe5ad7c"
|
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-4.2.0.tgz#e964fc56c9621f28679f24d5e69026e2d1571425"
|
||||||
|
dependencies:
|
||||||
|
tslib "^1.7.1"
|
||||||
|
|
||||||
"@angular/cli@^1.1.0-rc.0":
|
"@angular/cli@^1.1.0-rc.0":
|
||||||
version "1.1.0-rc.0"
|
version "1.1.0-rc.0"
|
||||||
@ -69,56 +71,73 @@
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
node-sass "^4.3.0"
|
node-sass "^4.3.0"
|
||||||
|
|
||||||
"@angular/common@next":
|
"@angular/common@4.2.0":
|
||||||
version "4.2.0-beta.1"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@angular/common/-/common-4.2.0-beta.1.tgz#d9d9cfc0188b9e391de9084e1e3f6fac448b5580"
|
resolved "https://registry.yarnpkg.com/@angular/common/-/common-4.2.0.tgz#5df34718bcefc49918bfcb2683f6c19720b66a61"
|
||||||
|
|
||||||
"@angular/compiler-cli@next":
|
|
||||||
version "4.2.0-beta.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-4.2.0-beta.1.tgz#24d8dad585ba9ecdb7b6ba8f342d7c1d05cc890b"
|
|
||||||
dependencies:
|
dependencies:
|
||||||
"@angular/tsc-wrapped" "4.2.0-beta.1"
|
tslib "^1.7.1"
|
||||||
|
|
||||||
|
"@angular/compiler-cli@4.2.0":
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-4.2.0.tgz#bd6f6b71f003df48a8f86184a8c16533afdf23ec"
|
||||||
|
dependencies:
|
||||||
|
"@angular/tsc-wrapped" "4.2.0"
|
||||||
minimist "^1.2.0"
|
minimist "^1.2.0"
|
||||||
reflect-metadata "^0.1.2"
|
reflect-metadata "^0.1.2"
|
||||||
|
|
||||||
"@angular/compiler@next":
|
"@angular/compiler@4.2.0":
|
||||||
version "4.2.0-beta.1"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-4.2.0-beta.1.tgz#0817630876e7d721b1bf6f34c4d1a4434e21164d"
|
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-4.2.0.tgz#a21df81995b210f822ffd70b57247d474876fbed"
|
||||||
|
dependencies:
|
||||||
|
tslib "^1.7.1"
|
||||||
|
|
||||||
"@angular/core@next":
|
"@angular/core@4.2.0":
|
||||||
version "4.2.0-beta.1"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@angular/core/-/core-4.2.0-beta.1.tgz#533c0da98310333ac44bb9249d200db38f514b65"
|
resolved "https://registry.yarnpkg.com/@angular/core/-/core-4.2.0.tgz#8bf57d01379c2a9e29476ad569dec9e20d5b17dc"
|
||||||
|
dependencies:
|
||||||
|
tslib "^1.7.1"
|
||||||
|
|
||||||
"@angular/forms@next":
|
"@angular/forms@4.2.0":
|
||||||
version "4.2.0-beta.1"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-4.2.0-beta.1.tgz#fa3be8ab19dd8689bbdeae8c5b8119f2983d24d1"
|
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-4.2.0.tgz#cb3ae69172e254452fa77578605ebc1bb72138c9"
|
||||||
|
dependencies:
|
||||||
|
tslib "^1.7.1"
|
||||||
|
|
||||||
"@angular/http@next":
|
"@angular/http@4.2.0":
|
||||||
version "4.2.0-beta.1"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@angular/http/-/http-4.2.0-beta.1.tgz#0549ea48c82f9b5a568ba2feea5210781b6d3cd3"
|
resolved "https://registry.yarnpkg.com/@angular/http/-/http-4.2.0.tgz#484af53639e04a68834c5167a1955d2d0cde8e1c"
|
||||||
|
dependencies:
|
||||||
|
tslib "^1.7.1"
|
||||||
|
|
||||||
"@angular/material@^2.0.0-beta.3":
|
"@angular/material@^2.0.0-beta.3":
|
||||||
version "2.0.0-beta.4"
|
version "2.0.0-beta.4"
|
||||||
resolved "https://registry.yarnpkg.com/@angular/material/-/material-2.0.0-beta.4.tgz#137ef759867213308613172c54dfe69061a10829"
|
resolved "https://registry.yarnpkg.com/@angular/material/-/material-2.0.0-beta.4.tgz#137ef759867213308613172c54dfe69061a10829"
|
||||||
|
|
||||||
"@angular/platform-browser-dynamic@next":
|
"@angular/platform-browser-dynamic@4.2.0":
|
||||||
version "4.2.0-beta.1"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-4.2.0-beta.1.tgz#a5a19129fcdca0951d62491f8ec6439c26ea93be"
|
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-4.2.0.tgz#b84c05616bd824e15b52b2b85c47b58b25d0158a"
|
||||||
|
dependencies:
|
||||||
|
tslib "^1.7.1"
|
||||||
|
|
||||||
"@angular/platform-browser@next":
|
"@angular/platform-browser@4.2.0":
|
||||||
version "4.2.0-beta.1"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-4.2.0-beta.1.tgz#f26536b11067c3956b2eaa892fd8fe943e8decd4"
|
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-4.2.0.tgz#dfd782e7ebacba1bbe2ae0556d5d7fb012f2a6cd"
|
||||||
|
dependencies:
|
||||||
|
tslib "^1.7.1"
|
||||||
|
|
||||||
"@angular/platform-server@next":
|
"@angular/platform-server@4.2.0":
|
||||||
version "4.2.0-beta.1"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-4.2.0-beta.1.tgz#a530356a2f32bd08a05731b144a0162a5221dcb7"
|
resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-4.2.0.tgz#90add7fcd9c4f568a31058c9d93a9aca09eb4c58"
|
||||||
dependencies:
|
dependencies:
|
||||||
parse5 "^3.0.1"
|
parse5 "^3.0.1"
|
||||||
|
tslib "^1.7.1"
|
||||||
xhr2 "^0.1.4"
|
xhr2 "^0.1.4"
|
||||||
|
|
||||||
"@angular/router@next":
|
"@angular/router@4.2.0":
|
||||||
version "4.2.0-beta.1"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@angular/router/-/router-4.2.0-beta.1.tgz#b7a4649120373f667451f62a9d60aafdde793a1b"
|
resolved "https://registry.yarnpkg.com/@angular/router/-/router-4.2.0.tgz#7cda9a23621ee41b466eced8bb4cbb62237ba6b9"
|
||||||
|
dependencies:
|
||||||
|
tslib "^1.7.1"
|
||||||
|
|
||||||
"@angular/service-worker@^1.0.0-beta.12":
|
"@angular/service-worker@^1.0.0-beta.12":
|
||||||
version "1.0.0-beta.13"
|
version "1.0.0-beta.13"
|
||||||
@ -127,9 +146,9 @@
|
|||||||
base64-js "^1.1.2"
|
base64-js "^1.1.2"
|
||||||
jshashes "^1.0.5"
|
jshashes "^1.0.5"
|
||||||
|
|
||||||
"@angular/tsc-wrapped@4.2.0-beta.1":
|
"@angular/tsc-wrapped@4.2.0":
|
||||||
version "4.2.0-beta.1"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@angular/tsc-wrapped/-/tsc-wrapped-4.2.0-beta.1.tgz#78b28b853e4cccf3bda4caee89039de63a7a7fd8"
|
resolved "https://registry.yarnpkg.com/@angular/tsc-wrapped/-/tsc-wrapped-4.2.0.tgz#e62ce9953c27ba96e4c6daf117f10e31169ccea2"
|
||||||
dependencies:
|
dependencies:
|
||||||
tsickle "^0.21.0"
|
tsickle "^0.21.0"
|
||||||
|
|
||||||
@ -3362,9 +3381,9 @@ ieee754@^1.1.4:
|
|||||||
version "1.1.8"
|
version "1.1.8"
|
||||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
|
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
|
||||||
|
|
||||||
ignore@^3.2.0:
|
ignore@^3.2.0, ignore@^3.3.3:
|
||||||
version "3.3.0"
|
version "3.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.0.tgz#3812d22cbe9125f2c2b4915755a1b8abd745a001"
|
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d"
|
||||||
|
|
||||||
ignorefs@^1.0.0, ignorefs@^1.1.1:
|
ignorefs@^1.0.0, ignorefs@^1.1.1:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
@ -7150,14 +7169,14 @@ typescript@2.1:
|
|||||||
version "2.1.6"
|
version "2.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.1.6.tgz#40c7e6e9e5da7961b7718b55505f9cac9487a607"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.1.6.tgz#40c7e6e9e5da7961b7718b55505f9cac9487a607"
|
||||||
|
|
||||||
typescript@2.2.0, "typescript@>=2.0.0 <2.4.0":
|
typescript@2.3.2, typescript@^2.2.1:
|
||||||
version "2.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.2.0.tgz#626f2fc70087d2480f21ebb12c1888288c8614e3"
|
|
||||||
|
|
||||||
typescript@^2.2.1:
|
|
||||||
version "2.3.2"
|
version "2.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.3.2.tgz#f0f045e196f69a72f06b25fd3bd39d01c3ce9984"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.3.2.tgz#f0f045e196f69a72f06b25fd3bd39d01c3ce9984"
|
||||||
|
|
||||||
|
"typescript@>=2.0.0 <2.4.0":
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.2.0.tgz#626f2fc70087d2480f21ebb12c1888288c8614e3"
|
||||||
|
|
||||||
uglify-js@^2.6, uglify-js@^2.8.5, uglify-js@~2.8.22:
|
uglify-js@^2.6, uglify-js@^2.8.5, uglify-js@~2.8.22:
|
||||||
version "2.8.23"
|
version "2.8.23"
|
||||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.23.tgz#8230dd9783371232d62a7821e2cf9a817270a8a0"
|
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.23.tgz#8230dd9783371232d62a7821e2cf9a817270a8a0"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "angular-srcs",
|
"name": "angular-srcs",
|
||||||
"version": "4.2.0",
|
"version": "4.2.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"branchPattern": "2.0.*",
|
"branchPattern": "2.0.*",
|
||||||
"description": "Angular - a web framework for modern web apps",
|
"description": "Angular - a web framework for modern web apps",
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
// For TypeScript 1.8, we have to lay out generated files
|
// For TypeScript 1.8, we have to lay out generated files
|
||||||
// in the same source directory with your code.
|
// in the same source directory with your code.
|
||||||
"genDir": ".",
|
"genDir": ".",
|
||||||
"debug": true
|
"debug": true,
|
||||||
|
"enableSummariesForJit": true
|
||||||
},
|
},
|
||||||
|
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
"ng-xi18n": "./src/extract_i18n.js"
|
"ng-xi18n": "./src/extract_i18n.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/tsc-wrapped": "4.2.0",
|
"@angular/tsc-wrapped": "4.2.1",
|
||||||
"reflect-metadata": "^0.1.2",
|
"reflect-metadata": "^0.1.2",
|
||||||
"minimist": "^1.2.0"
|
"minimist": "^1.2.0"
|
||||||
},
|
},
|
||||||
|
@ -100,6 +100,7 @@ export class CodeGenerator {
|
|||||||
i18nFormat: cliOptions.i18nFormat,
|
i18nFormat: cliOptions.i18nFormat,
|
||||||
locale: cliOptions.locale, missingTranslation,
|
locale: cliOptions.locale, missingTranslation,
|
||||||
enableLegacyTemplate: options.enableLegacyTemplate !== false,
|
enableLegacyTemplate: options.enableLegacyTemplate !== false,
|
||||||
|
enableSummariesForJit: options.enableSummariesForJit !== false,
|
||||||
});
|
});
|
||||||
return new CodeGenerator(options, program, tsCompilerHost, aotCompiler, ngCompilerHost);
|
return new CodeGenerator(options, program, tsCompilerHost, aotCompiler, ngCompilerHost);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,10 @@ import {CodeGenerator} from './codegen';
|
|||||||
function codegen(
|
function codegen(
|
||||||
ngOptions: tsc.AngularCompilerOptions, cliOptions: tsc.NgcCliOptions, program: ts.Program,
|
ngOptions: tsc.AngularCompilerOptions, cliOptions: tsc.NgcCliOptions, program: ts.Program,
|
||||||
host: ts.CompilerHost) {
|
host: ts.CompilerHost) {
|
||||||
|
if (ngOptions.enableSummariesForJit === undefined) {
|
||||||
|
// default to false
|
||||||
|
ngOptions.enableSummariesForJit = false;
|
||||||
|
}
|
||||||
return CodeGenerator.create(ngOptions, cliOptions, program, host).codegen();
|
return CodeGenerator.create(ngOptions, cliOptions, program, host).codegen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,10 +99,15 @@ export class NgTools_InternalApi_NG_2 {
|
|||||||
missingTranslation: options.missingTranslation !,
|
missingTranslation: options.missingTranslation !,
|
||||||
basePath: options.basePath
|
basePath: options.basePath
|
||||||
};
|
};
|
||||||
|
const ngOptions = options.angularCompilerOptions;
|
||||||
|
if (ngOptions.enableSummariesForJit === undefined) {
|
||||||
|
// default to false
|
||||||
|
ngOptions.enableSummariesForJit = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Create the Code Generator.
|
// Create the Code Generator.
|
||||||
const codeGenerator = CodeGenerator.create(
|
const codeGenerator =
|
||||||
options.angularCompilerOptions, cliOptions, options.program, options.host, hostContext);
|
CodeGenerator.create(ngOptions, cliOptions, options.program, options.host, hostContext);
|
||||||
|
|
||||||
return codeGenerator.codegen();
|
return codeGenerator.codegen();
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ function compile(
|
|||||||
return ngChecker.getDiagnostics();
|
return ngChecker.getDiagnostics();
|
||||||
}
|
}
|
||||||
|
|
||||||
fdescribe('ng type checker', () => {
|
describe('ng type checker', () => {
|
||||||
let angularFiles = setup();
|
let angularFiles = setup();
|
||||||
|
|
||||||
function accept(...files: MockDirectory[]) {
|
function accept(...files: MockDirectory[]) {
|
||||||
|
@ -261,5 +261,52 @@ describe('compiler-cli', () => {
|
|||||||
})
|
})
|
||||||
.catch(e => done.fail(e));
|
.catch(e => done.fail(e));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not produce ngsummary files by default', (done) => {
|
||||||
|
writeConfig(`{
|
||||||
|
"extends": "./tsconfig-base.json",
|
||||||
|
"files": ["mymodule.ts"]
|
||||||
|
}`);
|
||||||
|
write('mymodule.ts', `
|
||||||
|
import {NgModule} from '@angular/core';
|
||||||
|
|
||||||
|
@NgModule()
|
||||||
|
export class MyModule {}
|
||||||
|
`);
|
||||||
|
|
||||||
|
main({p: basePath})
|
||||||
|
.then((exitCode) => {
|
||||||
|
expect(exitCode).toEqual(0);
|
||||||
|
expect(fs.existsSync(path.resolve(outDir, 'mymodule.ngsummary.js'))).toBe(false);
|
||||||
|
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(e => done.fail(e));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should produce ngsummary files if configured', (done) => {
|
||||||
|
writeConfig(`{
|
||||||
|
"extends": "./tsconfig-base.json",
|
||||||
|
"files": ["mymodule.ts"],
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"enableSummariesForJit": true
|
||||||
|
}
|
||||||
|
}`);
|
||||||
|
write('mymodule.ts', `
|
||||||
|
import {NgModule} from '@angular/core';
|
||||||
|
|
||||||
|
@NgModule()
|
||||||
|
export class MyModule {}
|
||||||
|
`);
|
||||||
|
|
||||||
|
main({p: basePath})
|
||||||
|
.then((exitCode) => {
|
||||||
|
expect(exitCode).toEqual(0);
|
||||||
|
expect(fs.existsSync(path.resolve(outDir, 'mymodule.ngsummary.js'))).toBe(true);
|
||||||
|
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(e => done.fail(e));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -35,7 +35,8 @@ export class AotCompiler {
|
|||||||
private _viewCompiler: ViewCompiler, private _ngModuleCompiler: NgModuleCompiler,
|
private _viewCompiler: ViewCompiler, private _ngModuleCompiler: NgModuleCompiler,
|
||||||
private _outputEmitter: OutputEmitter,
|
private _outputEmitter: OutputEmitter,
|
||||||
private _summaryResolver: SummaryResolver<StaticSymbol>, private _localeId: string|null,
|
private _summaryResolver: SummaryResolver<StaticSymbol>, private _localeId: string|null,
|
||||||
private _translationFormat: string|null, private _symbolResolver: StaticSymbolResolver) {}
|
private _translationFormat: string|null, private _enableSummariesForJit: boolean|null,
|
||||||
|
private _symbolResolver: StaticSymbolResolver) {}
|
||||||
|
|
||||||
clearCache() { this._metadataResolver.clearCache(); }
|
clearCache() { this._metadataResolver.clearCache(); }
|
||||||
|
|
||||||
@ -204,10 +205,12 @@ export class AotCompiler {
|
|||||||
o.StmtModifier.Exported
|
o.StmtModifier.Exported
|
||||||
]));
|
]));
|
||||||
});
|
});
|
||||||
return [
|
const summaryJson = new GeneratedFile(srcFileUrl, summaryFileName(srcFileUrl), json);
|
||||||
new GeneratedFile(srcFileUrl, summaryFileName(srcFileUrl), json),
|
if (this._enableSummariesForJit) {
|
||||||
this._codegenSourceModule(srcFileUrl, forJitOutputCtx)
|
return [summaryJson, this._codegenSourceModule(srcFileUrl, forJitOutputCtx)];
|
||||||
];
|
};
|
||||||
|
|
||||||
|
return [summaryJson];
|
||||||
}
|
}
|
||||||
|
|
||||||
private _compileModule(outputCtx: OutputContext, ngModuleType: StaticSymbol): void {
|
private _compileModule(outputCtx: OutputContext, ngModuleType: StaticSymbol): void {
|
||||||
|
@ -70,6 +70,7 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom
|
|||||||
const compiler = new AotCompiler(
|
const compiler = new AotCompiler(
|
||||||
config, compilerHost, staticReflector, resolver, tmplParser, new StyleCompiler(urlResolver),
|
config, compilerHost, staticReflector, resolver, tmplParser, new StyleCompiler(urlResolver),
|
||||||
viewCompiler, new NgModuleCompiler(staticReflector), new TypeScriptEmitter(), summaryResolver,
|
viewCompiler, new NgModuleCompiler(staticReflector), new TypeScriptEmitter(), summaryResolver,
|
||||||
options.locale || null, options.i18nFormat || null, symbolResolver);
|
options.locale || null, options.i18nFormat || null, options.enableSummariesForJit || null,
|
||||||
|
symbolResolver);
|
||||||
return {compiler, reflector: staticReflector};
|
return {compiler, reflector: staticReflector};
|
||||||
}
|
}
|
||||||
|
@ -14,4 +14,5 @@ export interface AotCompilerOptions {
|
|||||||
translations?: string;
|
translations?: string;
|
||||||
missingTranslation?: MissingTranslationStrategy;
|
missingTranslation?: MissingTranslationStrategy;
|
||||||
enableLegacyTemplate?: boolean;
|
enableLegacyTemplate?: boolean;
|
||||||
|
enableSummariesForJit?: boolean
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {AotCompiler, AotCompilerHost, AotCompilerOptions, CompileSummaryKind, GeneratedFile, createAotCompiler, toTypeScript} from '@angular/compiler';
|
import {AotCompiler, AotCompilerHost, AotCompilerOptions, CompileSummaryKind, GeneratedFile, toTypeScript} from '@angular/compiler';
|
||||||
|
|
||||||
import {MockDirectory, compile, setup} from './test_util';
|
import {MockDirectory, compile, setup} from './test_util';
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ describe('aot summaries for jit', () => {
|
|||||||
|
|
||||||
function compileApp(rootDir: MockDirectory, options: {useSummaries?: boolean} = {}):
|
function compileApp(rootDir: MockDirectory, options: {useSummaries?: boolean} = {}):
|
||||||
{genFiles: GeneratedFile[], outDir: MockDirectory} {
|
{genFiles: GeneratedFile[], outDir: MockDirectory} {
|
||||||
return compile([rootDir, angularFiles], options);
|
return compile([rootDir, angularFiles], {...options, enableSummariesForJit: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should create @Injectable summaries', () => {
|
it('should create @Injectable summaries', () => {
|
||||||
|
@ -79,9 +79,8 @@ export class RequestOptions {
|
|||||||
responseType: ResponseContentType|null;
|
responseType: ResponseContentType|null;
|
||||||
|
|
||||||
// TODO(Dzmitry): remove search when this.search is removed
|
// TODO(Dzmitry): remove search when this.search is removed
|
||||||
constructor(
|
constructor(opts: RequestOptionsArgs = {}) {
|
||||||
{method, headers, body, url, search, params, withCredentials,
|
const {method, headers, body, url, search, params, withCredentials, responseType} = opts;
|
||||||
responseType}: RequestOptionsArgs = {}) {
|
|
||||||
this.method = method != null ? normalizeMethodName(method) : null;
|
this.method = method != null ? normalizeMethodName(method) : null;
|
||||||
this.headers = headers != null ? headers : null;
|
this.headers = headers != null ? headers : null;
|
||||||
this.body = body != null ? body : null;
|
this.body = body != null ? body : null;
|
||||||
|
@ -65,7 +65,8 @@ export class ResponseOptions {
|
|||||||
*/
|
*/
|
||||||
type: ResponseType|null;
|
type: ResponseType|null;
|
||||||
url: string|null;
|
url: string|null;
|
||||||
constructor({body, status, headers, statusText, type, url}: ResponseOptionsArgs = {}) {
|
constructor(opts: ResponseOptionsArgs = {}) {
|
||||||
|
const {body, status, headers, statusText, type, url} = opts;
|
||||||
this.body = body != null ? body : null;
|
this.body = body != null ? body : null;
|
||||||
this.status = status != null ? status : null;
|
this.status = status != null ? status : null;
|
||||||
this.headers = headers != null ? headers : null;
|
this.headers = headers != null ? headers : null;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "@angular/tsc-wrapped",
|
"name": "@angular/tsc-wrapped",
|
||||||
"version": "4.2.0",
|
"version": "4.2.1",
|
||||||
"description": "Wraps the tsc CLI, allowing extensions.",
|
"description": "Wraps the tsc CLI, allowing extensions.",
|
||||||
"homepage": "https://github.com/angular/angular/tree/master/tools/tsc-wrapped",
|
"homepage": "https://github.com/angular/angular/blob/master/tools/@angular/tsc-wrapped",
|
||||||
"bugs": "https://github.com/angular/angular/issues",
|
"bugs": "https://github.com/angular/angular/issues",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"Alex Eagle <alexeagle@google.com>",
|
"Alex Eagle <alexeagle@google.com>",
|
||||||
|
@ -81,6 +81,10 @@ interface Options extends ts.CompilerOptions {
|
|||||||
|
|
||||||
// Whether to enable support for <template> and the template attribute (true by default)
|
// Whether to enable support for <template> and the template attribute (true by default)
|
||||||
enableLegacyTemplate?: boolean;
|
enableLegacyTemplate?: boolean;
|
||||||
|
|
||||||
|
// Whether to generate .ngsummary.ts files that allow to use AOTed artifacts
|
||||||
|
// in JIT mode.
|
||||||
|
enableSummariesForJit?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Options;
|
export default Options;
|
||||||
|
4
tools/public_api_guard/http/http.d.ts
vendored
4
tools/public_api_guard/http/http.d.ts
vendored
@ -144,7 +144,7 @@ export declare class RequestOptions {
|
|||||||
/** @deprecated */ search: URLSearchParams;
|
/** @deprecated */ search: URLSearchParams;
|
||||||
url: string | null;
|
url: string | null;
|
||||||
withCredentials: boolean | null;
|
withCredentials: boolean | null;
|
||||||
constructor({method, headers, body, url, search, params, withCredentials, responseType}?: RequestOptionsArgs);
|
constructor(opts?: RequestOptionsArgs);
|
||||||
merge(options?: RequestOptionsArgs): RequestOptions;
|
merge(options?: RequestOptionsArgs): RequestOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ export declare class ResponseOptions {
|
|||||||
headers: Headers | null;
|
headers: Headers | null;
|
||||||
status: number | null;
|
status: number | null;
|
||||||
url: string | null;
|
url: string | null;
|
||||||
constructor({body, status, headers, statusText, type, url}?: ResponseOptionsArgs);
|
constructor(opts?: ResponseOptionsArgs);
|
||||||
merge(options?: ResponseOptionsArgs): ResponseOptions;
|
merge(options?: ResponseOptionsArgs): ResponseOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user