Compare commits
135 Commits
g3
...
8.0.0-beta
Author | SHA1 | Date | |
---|---|---|---|
0a530e6b47 | |||
dc5577dcb1 | |||
a6809e0e7d | |||
ddb935fac7 | |||
afd4a4ed4d | |||
60afe88bcc | |||
2d372f48db | |||
45c6360e5a | |||
6b39c9cf32 | |||
c5799491e7 | |||
b14537a004 | |||
630aaa6bfb | |||
7c8f4e3202 | |||
15eb1e0ce1 | |||
780081def0 | |||
5a724b34bd | |||
03d914a6c2 | |||
98f8b0f328 | |||
5a1d21ebb4 | |||
cbd5d28f71 | |||
9f54d76ef5 | |||
e5201f92fc | |||
3487055d10 | |||
1c07061246 | |||
d11b0c0c41 | |||
1293da1cf7 | |||
7c1f73ac7b | |||
0e201ea9d8 | |||
53be333439 | |||
19081dc9a3 | |||
9e4c0bd815 | |||
deca6a60dd | |||
63013f1aeb | |||
8bfaaf164a | |||
1f469cd7bb | |||
7041e61562 | |||
7316212c1e | |||
aaa16f286d | |||
3e569767e3 | |||
abf69dec5b | |||
701da0099b | |||
f9497bf28b | |||
d7e5535d00 | |||
8d3d75e454 | |||
39345b6fae | |||
06859f1335 | |||
717aa7c6e4 | |||
9cd90532c1 | |||
ff2a55f14f | |||
0abd5f5f03 | |||
cd6581e4f0 | |||
76110d71d3 | |||
a4fb0486c1 | |||
8a13f6b278 | |||
ee7c5ed620 | |||
2ff3d2d421 | |||
33016b8929 | |||
b2c03b8cd4 | |||
fd4c939394 | |||
6759aa68dc | |||
ab4be7bf80 | |||
2b6e107b1e | |||
6a55ba28b2 | |||
33524d9d9c | |||
b99a070f88 | |||
799a5a4915 | |||
4b2407a4db | |||
ed19464be0 | |||
c67f6a7e60 | |||
d4c4a89431 | |||
12c9bd257d | |||
e8768acacc | |||
303eae918d | |||
50f7ab2a06 | |||
22b89ea58a | |||
e8921365b7 | |||
009acd2a6c | |||
333bfa0ffb | |||
eb0e29b269 | |||
71daa11357 | |||
a81fd5f750 | |||
57f7996b6d | |||
27ba4ac982 | |||
6c76dfc568 | |||
78ba503fb9 | |||
1df9908579 | |||
c456b73302 | |||
632669f069 | |||
33963ca0d3 | |||
7b27009e20 | |||
d46a7c8468 | |||
71ec99856a | |||
e958447100 | |||
931d356a10 | |||
e4c1c88cbc | |||
1e5a818719 | |||
e57ed61448 | |||
aaa8a3a957 | |||
80161d5033 | |||
6a66af7a27 | |||
9745f55a65 | |||
c9810064cb | |||
1727fe24fb | |||
4eb6b02f08 | |||
96b800c8bc | |||
dd69e4e780 | |||
401b8eedd5 | |||
8badf9808a | |||
f8c7c3c09c | |||
b17d1a9aa3 | |||
60f6d9e733 | |||
416b0d29b9 | |||
2b836c81a2 | |||
ac3ce0d793 | |||
6c33058856 | |||
50fb629012 | |||
309ffe7e16 | |||
fea2a0f2ac | |||
e0dcd11a49 | |||
3514543e4b | |||
d9162a872d | |||
06056b4a6d | |||
3c11646dd3 | |||
a2f8f5595f | |||
a28b3e3359 | |||
495a4c1754 | |||
17f7bdbd60 | |||
531fa00992 | |||
c412374854 | |||
9724247ad8 | |||
568140fb03 | |||
7951c4feb2 | |||
0f1da49b86 | |||
a5c9fa3c8f | |||
6feef368f6 |
7
.bazelrc
7
.bazelrc
@ -35,8 +35,9 @@ test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test
|
||||
# See https://github.com/bazelbuild/bazel/issues/4603
|
||||
build --symlink_prefix=dist/
|
||||
|
||||
# Performance: avoid stat'ing input files
|
||||
build --watchfs
|
||||
# Disable watchfs as it causes tests to be flaky on Windows
|
||||
# https://github.com/angular/angular/issues/29541
|
||||
build --nowatchfs
|
||||
|
||||
# Turn off legacy external runfiles
|
||||
run --nolegacy_external_runfiles
|
||||
@ -118,7 +119,7 @@ build --define=compile=legacy
|
||||
# Load default settings for Remote Build Execution
|
||||
# When updating, the URLs of bazel_toolchains in packages/bazel/package.bzl
|
||||
# may also need to be updated (see https://github.com/angular/angular/pull/27935)
|
||||
import %workspace%/third_party/github.com/bazelbuild/bazel-toolchains/bazelrc/bazel-0.21.0.bazelrc
|
||||
import %workspace%/third_party/github.com/bazelbuild/bazel-toolchains/bazelrc/bazel-0.24.0.bazelrc
|
||||
|
||||
# Increase the default number of jobs by 50% because our build has lots of
|
||||
# parallelism
|
||||
|
@ -2,15 +2,17 @@
|
||||
# We do this by copying this file to /etc/bazel.bazelrc at the start of the build.
|
||||
# See documentation in /docs/BAZEL.md
|
||||
|
||||
# Save downloaded repositories in a location that can be cached by CodeFresh. This helps us
|
||||
# speeding up the analysis time significantly with Bazel managed node dependencies on the CI.
|
||||
# build --repository_cache=C:/codefresh/volume/bazel_repository_cache
|
||||
# Save downloaded repositories in a location that can be cached by CodeFresh and shared between
|
||||
# builds. This helps speed up the analysis time significantly with Bazel managed node dependencies
|
||||
# on the CI.
|
||||
# https://codefresh.io/docs/docs/configure-ci-cd-pipeline/introduction-to-codefresh-pipelines/#caching-the-artifacts-of-your-build-system
|
||||
build --repository_cache=C:/codefresh/volume/bazel_repository_cache
|
||||
|
||||
# Don't be spammy in the logs
|
||||
# TODO(gmagolan): Hide progress again once build performance improves
|
||||
# Presently, CircleCI can timeout during bazel test ... with the following
|
||||
# error: Too long with no output (exceeded 10m0s)
|
||||
# build --noshow_progress
|
||||
build --noshow_progress
|
||||
|
||||
# Print all the options that apply to the build.
|
||||
# This helps us diagnose which options override others
|
||||
|
@ -17,8 +17,6 @@ steps:
|
||||
commands:
|
||||
# Install dependencies
|
||||
- yarn install --frozen-lockfile --non-interactive --network-timeout 100000 --no-progress
|
||||
# Create symlinks needed for Windows.
|
||||
- scripts\windows\create-symlinks.cmd
|
||||
# Add Bazel CI config
|
||||
- copy .codefresh\bazel.rc %ProgramData%\bazel.bazelrc
|
||||
# Run tests
|
||||
|
13
.github/CODEOWNERS
vendored
13
.github/CODEOWNERS
vendored
@ -399,10 +399,10 @@
|
||||
|
||||
|
||||
# ================================================
|
||||
# packages/compiler-cli/src/ngcc/
|
||||
# packages/compiler-cli/ngcc/
|
||||
# ================================================
|
||||
|
||||
/packages/compiler-cli/src/ngcc/** @angular/fw-ngcc @angular/framework-global-approvers
|
||||
/packages/compiler-cli/ngcc/** @angular/fw-ngcc @angular/framework-global-approvers
|
||||
|
||||
|
||||
|
||||
@ -414,6 +414,7 @@
|
||||
|
||||
/packages/compiler-cli/src/ngtools/** @angular/tools-cli @angular/framework-global-approvers
|
||||
/aio/content/guide/ivy.md @angular/tools-cli @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/web-worker.md @angular/tools-cli @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
@ -432,6 +433,7 @@
|
||||
/packages/platform-browser-dynamic/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/platform-webworker/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/platform-webworker-dynamic/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/examples/common/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/architecture-components.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/architecture-modules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
@ -512,6 +514,7 @@
|
||||
/aio/content/guide/module-types.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/template-syntax.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/built-in-template-functions/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/event-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/interpolation/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
@ -627,6 +630,7 @@
|
||||
/packages/service-worker/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/service-worker-getting-started.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/service-worker-getting-started/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/app-shell.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/service-worker-communications.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/service-worker-config.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/service-worker-devops.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
@ -753,6 +757,10 @@ testing/** @angular/fw-test
|
||||
/aio/content/examples/toh-pt4/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/toh-pt5/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/toh-pt6/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/getting-started-v0/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/getting-started/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/getting-started/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/getting-started/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
@ -779,7 +787,6 @@ testing/** @angular/fw-test
|
||||
/aio/content/guide/npm-packages.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/browser-support.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/typescript-configuration.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/quickstart/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/setup.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/setup/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/build.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
2
.github/angular-robot.yml
vendored
2
.github/angular-robot.yml
vendored
@ -46,7 +46,7 @@ merge:
|
||||
- "packages/bazel/src/ng_package/**"
|
||||
- "packages/bazel/src/protractor/**"
|
||||
- "packages/bazel/src/schematics/**"
|
||||
- "packages/compiler-cli/src/ngcc/**"
|
||||
- "packages/compiler-cli/ngcc/**"
|
||||
- "packages/docs/**"
|
||||
- "packages/elements/schematics/**"
|
||||
- "packages/examples/**"
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,6 +13,7 @@ pubspec.lock
|
||||
.idea/
|
||||
.settings/
|
||||
.vscode/launch.json
|
||||
.vscode/settings.json
|
||||
*.swo
|
||||
modules/.settings
|
||||
modules/.vscode
|
||||
|
23
.vscode/README.md
vendored
Normal file
23
.vscode/README.md
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
# VSCode Configuration
|
||||
|
||||
This folder contains opt-in [Workspace Settings](https://code.visualstudio.com/docs/getstarted/settings) and [Extension Recommendations](https://code.visualstudio.com/docs/editor/extension-gallery#_workspace-recommended-extensions) that the Angular team recommends using when working on this repository.
|
||||
|
||||
## Usage
|
||||
|
||||
To use the recommended settings follow the steps below:
|
||||
|
||||
- install <https://marketplace.visualstudio.com/items?itemName=xaver.clang-format>
|
||||
- copy `.vscode/recommended-settings.json` to `.vscode/settings.json`
|
||||
- restart the editor
|
||||
|
||||
If you already have your custom workspace settings you should instead manually merge the file content.
|
||||
|
||||
This isn't an automatic process so you will need to repeat it when settings are updated.
|
||||
|
||||
To see the recommended extensions select "Extensions: Show Recommended Extensions" in the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).
|
||||
|
||||
## Editing `.vscode/recommended-settings.json`
|
||||
|
||||
If you wish to add extra configuration items please keep in mind any settings you add here will be used by many users.
|
||||
|
||||
Try to keep these settings to things that help facilitate the development process and avoid altering the user workflow whenever possible.
|
@ -1,4 +1,7 @@
|
||||
{
|
||||
// Format js and ts files on save with `clang-format.executable`
|
||||
// If `clang-format.executable` is not being used, these two settings should be removed otherwise it will break existing formatting.
|
||||
// You can instead run `yarn gulp format` to manually format your code.
|
||||
"[javascript]": {
|
||||
"editor.formatOnSave": true,
|
||||
},
|
||||
@ -8,6 +11,7 @@
|
||||
// Please install https://marketplace.visualstudio.com/items?itemName=xaver.clang-format to take advantage of `clang-format` in VSCode.
|
||||
// (See https://clang.llvm.org/docs/ClangFormat.html for more info `clang-format`.)
|
||||
"clang-format.executable": "${workspaceRoot}/node_modules/.bin/clang-format",
|
||||
// Exclude third party modules and build artifacts from the editor watchers/searches.
|
||||
"files.watcherExclude": {
|
||||
"**/.git/objects/**": true,
|
||||
"**/.git/subtree-cache/**": true,
|
@ -5,13 +5,17 @@ package(default_visibility = ["//visibility:public"])
|
||||
load("//tools:defaults.bzl", "karma_web_test")
|
||||
|
||||
exports_files([
|
||||
"tsconfig.json",
|
||||
"LICENSE",
|
||||
"protractor-perf.conf.js",
|
||||
"karma-js.conf.js",
|
||||
"browser-providers.conf.js",
|
||||
])
|
||||
|
||||
alias(
|
||||
name = "tsconfig.json",
|
||||
actual = "//packages:tsconfig-build.json",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "web_test_bootstrap_scripts",
|
||||
# do not sort
|
||||
|
72
CHANGELOG.md
72
CHANGELOG.md
@ -1,3 +1,73 @@
|
||||
<a name="8.0.0-beta.11"></a>
|
||||
# [8.0.0-beta.11](https://github.com/angular/angular/compare/8.0.0-beta.10...8.0.0-beta.11) (2019-04-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** Update schematics to support routing ([#29548](https://github.com/angular/angular/issues/29548)) ([401b8ee](https://github.com/angular/angular/commit/401b8ee))
|
||||
* **bazel:** use //:tsconfig.json as the default for ng_module ([#29670](https://github.com/angular/angular/issues/29670)) ([b14537a](https://github.com/angular/angular/commit/b14537a))
|
||||
* **compiler-cli:** ngcc - cope with processing entry-points multiple times ([#29657](https://github.com/angular/angular/issues/29657)) ([6b39c9c](https://github.com/angular/angular/commit/6b39c9c))
|
||||
* **core:** static-query schematic should detect static queries in getters. ([#29609](https://github.com/angular/angular/issues/29609)) ([33016b8](https://github.com/angular/angular/commit/33016b8))
|
||||
|
||||
|
||||
### build
|
||||
|
||||
* **bazel:** update to nodejs rules 0.27.8 ([#29508](https://github.com/angular/angular/issues/29508)) ([d9162a8](https://github.com/angular/angular/commit/d9162a8))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* remove [@angular](https://github.com/angular)/http dependency from [@angular](https://github.com/angular)/platform-server ([#29408](https://github.com/angular/angular/issues/29408)) ([9745f55](https://github.com/angular/angular/commit/9745f55))
|
||||
* **compiler-cli:** ngcc - make logging more configurable ([#29591](https://github.com/angular/angular/issues/29591)) ([8d3d75e](https://github.com/angular/angular/commit/8d3d75e))
|
||||
* **core:** Add "AbstractType<T>" interface ([#29295](https://github.com/angular/angular/issues/29295)) ([afd4a4e](https://github.com/angular/angular/commit/afd4a4e)), closes [#26491](https://github.com/angular/angular/issues/26491)
|
||||
* **core:** template-var-assignment update schematic ([#29608](https://github.com/angular/angular/issues/29608)) ([7c8f4e3](https://github.com/angular/angular/commit/7c8f4e3))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **bazel:** @bazel/typescript is now a peerDependency of @angular/bazel so user's of @angular/bazel must add @bazel/typescript to their package.json
|
||||
|
||||
|
||||
|
||||
<a name="7.2.12"></a>
|
||||
## [7.2.12](https://github.com/angular/angular/compare/7.2.11...7.2.12) (2019-04-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **common:** escape query selector used when anchor scrolling ([#29577](https://github.com/angular/angular/issues/29577)) ([7671c73](https://github.com/angular/angular/commit/7671c73)), closes [#28193](https://github.com/angular/angular/issues/28193)
|
||||
* **router:** adjust setting navigationTransition when a new navigation cancels an existing one ([#29636](https://github.com/angular/angular/issues/29636)) ([e884c0c](https://github.com/angular/angular/commit/e884c0c)), closes [#29389](https://github.com/angular/angular/issues/29389) [#29590](https://github.com/angular/angular/issues/29590)
|
||||
|
||||
|
||||
|
||||
<a name="8.0.0-beta.10"></a>
|
||||
# [8.0.0-beta.10](https://github.com/angular/angular/compare/8.0.0-beta.9...8.0.0-beta.10) (2019-03-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** allow ng_module users to set createExternalSymbolFactoryReexports ([#29459](https://github.com/angular/angular/issues/29459)) ([21be0fb](https://github.com/angular/angular/commit/21be0fb))
|
||||
* **bazel:** workaround problem reading summary files from node_modules ([#29459](https://github.com/angular/angular/issues/29459)) ([769d960](https://github.com/angular/angular/commit/769d960))
|
||||
* **compiler:** inherit param types when class has a constructor which takes no declared parameters and delegates up ([#29232](https://github.com/angular/angular/issues/29232)) ([0007564](https://github.com/angular/angular/commit/0007564))
|
||||
* **core:** parse incorrect ML open tag as text ([#29328](https://github.com/angular/angular/issues/29328)) ([dafbbf8](https://github.com/angular/angular/commit/dafbbf8)), closes [#29231](https://github.com/angular/angular/issues/29231)
|
||||
* **core:** static-query schematic should detect queries in "ngDoCheck" and "ngOnChanges" ([#29492](https://github.com/angular/angular/issues/29492)) ([09fab58](https://github.com/angular/angular/commit/09fab58))
|
||||
* **router:** support NgFactory promise in loadChildren typings ([#29392](https://github.com/angular/angular/issues/29392)) ([26a8c59](https://github.com/angular/angular/commit/26a8c59))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **bazel:** Upgrade rules_nodejs and rules_sass ([#29388](https://github.com/angular/angular/issues/29388)) ([d6d081e](https://github.com/angular/angular/commit/d6d081e))
|
||||
* **service-worker:** support multiple apps on different subpaths of a domain ([#27080](https://github.com/angular/angular/issues/27080)) ([e721c08](https://github.com/angular/angular/commit/e721c08)), closes [#21388](https://github.com/angular/angular/issues/21388)
|
||||
|
||||
|
||||
|
||||
<a name="7.2.11"></a>
|
||||
## [7.2.11](https://github.com/angular/angular/compare/7.2.10...7.2.11) (2019-03-26)
|
||||
|
||||
This release contains various API docs improvements.
|
||||
|
||||
|
||||
|
||||
<a name="8.0.0-beta.9"></a>
|
||||
# [8.0.0-beta.9](https://github.com/angular/angular/compare/8.0.0-beta.8...8.0.0-beta.9) (2019-03-20)
|
||||
|
||||
@ -54,7 +124,7 @@ Please update your TypeScript version to 3.3
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler-cli:** incorrect metadata bundle for multiple unnamed re-exports ([#29360](https://github.com/angular/angular/issues/29360)) ([cf8d934](https://github.com/angular/angular/commit/cf8d934)), closes [/github.com/angular/material2/blob/master/tools/package-tools/build-release.ts#L78-L85](https://github.com//github.com/angular/material2/blob/master/tools/package-tools/build-release.ts/issues/L78-L85)
|
||||
* **compiler-cli:** incorrect metadata bundle for multiple unnamed re-exports ([#29360](https://github.com/angular/angular/issues/29360)) ([cf8d934](https://github.com/angular/angular/commit/cf8d934)), closes [github.com/angular/material2/blob/master/tools/package-tools/build-release.ts#L78-L85](https://github.com/angular/material2/blob/master/tools/package-tools/build-release.ts#L78-L85)
|
||||
|
||||
|
||||
|
||||
|
@ -15,8 +15,8 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
# Fetch rules_nodejs so we can install our npm dependencies
|
||||
http_archive(
|
||||
name = "build_bazel_rules_nodejs",
|
||||
sha256 = "fb87ed5965cef93188af9a7287511639403f4b0da418961ce6defb9dcf658f51",
|
||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.27.7/rules_nodejs-0.27.7.tar.gz"],
|
||||
sha256 = "213dcf7e72f3acd4d1e369b7a356f3e5d9560f380bd655b13b7c0ea425d7c419",
|
||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.27.9/rules_nodejs-0.27.9.tar.gz"],
|
||||
)
|
||||
|
||||
# Check the bazel version and download npm dependencies
|
||||
|
@ -41,16 +41,6 @@ Here are the most important tasks you might need to use:
|
||||
- `yarn example-e2e --filter=foo` - limit e2e tests to those containing the word "foo"
|
||||
- `yarn example-e2e --setup --local` - run e2e tests with the local version of Angular contained in the "dist" folder
|
||||
|
||||
## Developing on Windows
|
||||
The `packages/` directory may contain Linux-specific symlinks, which are not recognized by Windows.
|
||||
These unresolved links cause the docs generation process to fail because it cannot locate certain files.
|
||||
|
||||
> Hint: The following steps require administration rights or [Windows Developer Mode](https://docs.microsoft.com/en-us/windows/uwp/get-started/enable-your-device-for-development) enabled!
|
||||
|
||||
To fix this problem, run `scripts/windows/create-symlinks.sh`. This command creates temporary files where the symlinks used to be. Make sure not to commit those files with your documentation changes.
|
||||
When you are done making and testing your documentation changes, you can restore the original symlinks and delete the temporary files by running `scripts/windows/remove-symlinks.sh`.
|
||||
|
||||
It's necessary to remove the temporary files, because otherwise they're displayed as local changes in your git working copy and certain operations are blocked.
|
||||
|
||||
## Using ServiceWorker locally
|
||||
|
||||
|
@ -0,0 +1,21 @@
|
||||
'use strict'; // necessary for es6 output in node
|
||||
|
||||
import { browser, element, by } from 'protractor';
|
||||
|
||||
describe('Getting Started V0', () => {
|
||||
beforeEach(() => {
|
||||
return browser.get('/');
|
||||
});
|
||||
|
||||
it('should display "My Store" in the top bar', async() => {
|
||||
const title = await element(by.css('app-root app-top-bar h1')).getText();
|
||||
|
||||
expect(title).toEqual('My Store');
|
||||
});
|
||||
|
||||
it('should display "Products" on the homepage', async() => {
|
||||
const title = await element(by.css('app-root app-product-list h2')).getText();
|
||||
|
||||
expect(title).toEqual('Products');
|
||||
});
|
||||
});
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"useCommonBoilerplate": false,
|
||||
"projectType": "getting-started"
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
p {
|
||||
font-family: Lato;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
<app-top-bar></app-top-bar>
|
||||
|
||||
<div class="container">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
@ -0,0 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: [ './app.component.css' ]
|
||||
})
|
||||
export class AppComponent {}
|
@ -0,0 +1,25 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { TopBarComponent } from './top-bar/top-bar.component';
|
||||
import { ProductListComponent } from './product-list/product-list.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
ReactiveFormsModule,
|
||||
RouterModule.forRoot([
|
||||
{ path: '', component: ProductListComponent },
|
||||
])
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
TopBarComponent,
|
||||
ProductListComponent
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule { }
|
@ -0,0 +1 @@
|
||||
<h2>Products</h2>
|
@ -0,0 +1,16 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
selector: 'app-product-list',
|
||||
templateUrl: './product-list.component.html',
|
||||
styleUrls: ['./product-list.component.css']
|
||||
})
|
||||
export class ProductListComponent {
|
||||
products = products;
|
||||
|
||||
share() {
|
||||
window.alert('The product has been shared!');
|
||||
}
|
||||
}
|
17
aio/content/examples/getting-started-v0/src/app/products.ts
Normal file
17
aio/content/examples/getting-started-v0/src/app/products.ts
Normal file
@ -0,0 +1,17 @@
|
||||
export const products = [
|
||||
{
|
||||
name: 'Phone XL',
|
||||
price: 799,
|
||||
description: 'A large phone with one of the best screens'
|
||||
},
|
||||
{
|
||||
name: 'Phone Mini',
|
||||
price: 699,
|
||||
description: 'A great phone with one of the best cameras'
|
||||
},
|
||||
{
|
||||
name: 'Phone Standard',
|
||||
price: 299,
|
||||
description: ''
|
||||
}
|
||||
];
|
@ -0,0 +1,5 @@
|
||||
<a [routerLink]="['/']">
|
||||
<h1>My Store</h1>
|
||||
</a>
|
||||
|
||||
<a [routerLink]="['/cart']" class="button fancy-button"><i class="material-icons">shopping_cart</i>Checkout</a>
|
@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-top-bar',
|
||||
templateUrl: './top-bar.component.html',
|
||||
styleUrls: ['./top-bar.component.css']
|
||||
})
|
||||
export class TopBarComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"type": "Overnight",
|
||||
"price": 25.99
|
||||
},
|
||||
{
|
||||
"type": "2-Day",
|
||||
"price": 9.99
|
||||
},
|
||||
{
|
||||
"type": "Postal",
|
||||
"price": 2.99
|
||||
}
|
||||
]
|
18
aio/content/examples/getting-started-v0/src/index.html
Normal file
18
aio/content/examples/getting-started-v0/src/index.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Angular Getting Started</title>
|
||||
<base href="/" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/icon?family=Material+Icons"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
@ -1,9 +1,8 @@
|
||||
// #docregion
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
import { environment } from './environments/environment';
|
||||
|
||||
import { AppModule } from './app/app.module';
|
||||
import { environment } from './environments/environment';
|
||||
|
||||
if (environment.production) {
|
||||
enableProdMode();
|
9
aio/content/examples/getting-started-v0/stackblitz.json
Normal file
9
aio/content/examples/getting-started-v0/stackblitz.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"description": "Getting Started",
|
||||
"files":[
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[0-9].*"
|
||||
],
|
||||
"tags": ["Angular", "getting started", "tutorial"]
|
||||
}
|
118
aio/content/examples/getting-started/e2e/src/app.e2e-spec.ts
Normal file
118
aio/content/examples/getting-started/e2e/src/app.e2e-spec.ts
Normal file
@ -0,0 +1,118 @@
|
||||
'use strict'; // necessary for es6 output in node
|
||||
|
||||
import { browser, element, by, ExpectedConditions as EC, logging, ElementFinder, ElementArrayFinder } from 'protractor';
|
||||
|
||||
describe('Getting Started', () => {
|
||||
const pageElements = {
|
||||
topBarHeader: element(by.css('app-root app-top-bar h1')),
|
||||
topBarLinks: element(by.css('app-root app-top-bar a')),
|
||||
topBarCheckoutLink: element(by.cssContainingText('app-root app-top-bar a', 'Checkout')),
|
||||
productListHeader: element(by.css('app-root app-product-list h2')),
|
||||
productListItems: element.all(by.css('app-root app-product-list h3')),
|
||||
productListLinks: element.all(by.css('app-root app-product-list a')),
|
||||
productDetailsPage: element(by.css('app-root app-product-details div')),
|
||||
cartPage: element(by.css('app-root app-cart'))
|
||||
};
|
||||
|
||||
describe('General', () => {
|
||||
beforeAll(async() => {
|
||||
await browser.get('/');
|
||||
});
|
||||
|
||||
it('should display "My Store"', async() => {
|
||||
const title = await pageElements.topBarHeader.getText();
|
||||
|
||||
expect(title).toEqual('My Store');
|
||||
});
|
||||
|
||||
it('should display "Products" on the homepage', async() => {
|
||||
const title = await pageElements.productListHeader.getText();
|
||||
|
||||
expect(title).toEqual('Products');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Product List', () => {
|
||||
beforeAll(async() => {
|
||||
await browser.get('/');
|
||||
});
|
||||
|
||||
it('should display 3 items', async() => {
|
||||
const products = await pageElements.productListItems;
|
||||
|
||||
expect(products.length).toEqual(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Product Details', () => {
|
||||
beforeEach(async() => {
|
||||
await browser.get('/');
|
||||
});
|
||||
|
||||
it('should display information for a product', async() => {
|
||||
await pageElements.productListLinks.get(0).click();
|
||||
|
||||
const product = pageElements.productDetailsPage;
|
||||
const productHeader = await product.element(by.css('h3')).getText();
|
||||
const productPrice = await product.element(by.css('h4')).getText();
|
||||
const productDescription = await product.element(by.css('p')).getText();
|
||||
|
||||
expect(await product.isDisplayed()).toBeTruthy();
|
||||
expect(productHeader).toBe('Phone XL');
|
||||
expect(productPrice).toBe('$799.00');
|
||||
expect(productDescription).toBe('A large phone with one of the best screens');
|
||||
});
|
||||
|
||||
it('should add the product to the cart', async() => {
|
||||
await pageElements.productListLinks.get(0).click();
|
||||
|
||||
const product = pageElements.productDetailsPage;
|
||||
const buyButton = await product.element(by.css('button'));
|
||||
const checkoutLink = pageElements.topBarCheckoutLink;
|
||||
|
||||
await buyButton.click();
|
||||
await browser.wait(EC.alertIsPresent(), 1000);
|
||||
await browser.switchTo().alert().accept();
|
||||
await checkoutLink.click();
|
||||
|
||||
const cartItems = await element.all(by.css('app-root app-cart div.cart-item'));
|
||||
expect(cartItems.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Cart', () => {
|
||||
|
||||
beforeEach(async() => {
|
||||
await browser.get('/');
|
||||
});
|
||||
|
||||
it('should go through the checkout process', async() => {
|
||||
await pageElements.productListLinks.get(0).click();
|
||||
|
||||
const checkoutLink = pageElements.topBarCheckoutLink;
|
||||
const productDetailsPage = pageElements.productDetailsPage;
|
||||
const buyButton = await productDetailsPage.element(by.css('button'));
|
||||
|
||||
const cartPage = pageElements.cartPage;
|
||||
const inputFields = cartPage.all(by.css('form input'));
|
||||
|
||||
const purchaseButton = await cartPage.element(by.css('button'));
|
||||
const nameField = inputFields.get(0);
|
||||
const addressField = inputFields.get(1);
|
||||
|
||||
await buyButton.click();
|
||||
await browser.wait(EC.alertIsPresent(), 1000);
|
||||
await browser.switchTo().alert().accept();
|
||||
await checkoutLink.click();
|
||||
|
||||
await nameField.sendKeys('Customer');
|
||||
await addressField.sendKeys('Address');
|
||||
await purchaseButton.click();
|
||||
|
||||
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
||||
const cartMessages = logs.filter(({ message }) => message.includes('Your order has been submitted'));
|
||||
|
||||
expect(cartMessages.length).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
4
aio/content/examples/getting-started/example-config.json
Normal file
4
aio/content/examples/getting-started/example-config.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"useCommonBoilerplate": false,
|
||||
"projectType": "getting-started"
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
<app-top-bar></app-top-bar>
|
||||
|
||||
<div class="container">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
@ -1,10 +1,9 @@
|
||||
// #docregion
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: '<h1>{{title}}</h1>',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'Angular Modules';
|
||||
}
|
55
aio/content/examples/getting-started/src/app/app.module.ts
Normal file
55
aio/content/examples/getting-started/src/app/app.module.ts
Normal file
@ -0,0 +1,55 @@
|
||||
// #docplaster
|
||||
// #docregion http-client-module-import, http-client-module
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
// #enddocregion http-client-module-import
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { TopBarComponent } from './top-bar/top-bar.component';
|
||||
import { ProductListComponent } from './product-list/product-list.component';
|
||||
import { ProductAlertsComponent } from './product-alerts/product-alerts.component';
|
||||
import { ProductDetailsComponent } from './product-details/product-details.component';
|
||||
// #enddocregion http-client-module
|
||||
import { CartComponent } from './cart/cart.component';
|
||||
import { ShippingComponent } from './shipping/shipping.component';
|
||||
|
||||
// #docregion product-details-route, http-client-module, shipping-route, cart-route
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
// #enddocregion product-details-route, cart-route
|
||||
HttpClientModule,
|
||||
// #docregion product-details-route, cart-route
|
||||
ReactiveFormsModule,
|
||||
RouterModule.forRoot([
|
||||
{ path: '', component: ProductListComponent },
|
||||
{ path: 'products/:productId', component: ProductDetailsComponent },
|
||||
// #enddocregion product-details-route
|
||||
{ path: 'cart', component: CartComponent },
|
||||
// #enddocregion cart-route, http-client-module
|
||||
{ path: 'shipping', component: ShippingComponent },
|
||||
// #enddocregion shipping-route
|
||||
// #docregion product-details-route, http-client-module, shipping-route, cart-route
|
||||
])
|
||||
],
|
||||
// #enddocregion product-details-route, cart-route
|
||||
declarations: [
|
||||
AppComponent,
|
||||
TopBarComponent,
|
||||
ProductListComponent,
|
||||
ProductAlertsComponent,
|
||||
ProductDetailsComponent,
|
||||
// #enddocregion http-client-module
|
||||
CartComponent,
|
||||
ShippingComponent
|
||||
// #docregion http-client-module
|
||||
],
|
||||
bootstrap: [
|
||||
AppComponent
|
||||
]
|
||||
})
|
||||
export class AppModule { }
|
@ -0,0 +1,13 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
// #docregion v1
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class CartService {
|
||||
|
||||
constructor() {}
|
||||
|
||||
}
|
39
aio/content/examples/getting-started/src/app/cart.service.ts
Normal file
39
aio/content/examples/getting-started/src/app/cart.service.ts
Normal file
@ -0,0 +1,39 @@
|
||||
// #docplaster
|
||||
// #docregion import-http
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
// #enddocregion import-http
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
// #docregion props, methods, inject-http, get-shipping
|
||||
export class CartService {
|
||||
items = [];
|
||||
// #enddocregion props, methods
|
||||
|
||||
constructor(
|
||||
private http: HttpClient
|
||||
) {}
|
||||
// #enddocregion inject-http
|
||||
// #docregion methods
|
||||
|
||||
addToCart(product) {
|
||||
this.items.push(product);
|
||||
}
|
||||
|
||||
getItems() {
|
||||
return this.items;
|
||||
}
|
||||
|
||||
clearCart() {
|
||||
this.items = [];
|
||||
return this.items;
|
||||
}
|
||||
// #enddocregion methods
|
||||
|
||||
getShippingPrices() {
|
||||
return this.http.get('/assets/shipping.json');
|
||||
}
|
||||
// #docregion props, methods, import-inject
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-cart',
|
||||
templateUrl: './cart.component.html',
|
||||
styleUrls: ['./cart.component.css']
|
||||
})
|
||||
export class CartComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
<!-- #docplaster -->
|
||||
<!-- #docregion prices -->
|
||||
<h3>Cart</h3>
|
||||
<!-- #enddocregion prices -->
|
||||
|
||||
<p>
|
||||
<a routerLink="/shipping">Shipping Prices</a>
|
||||
</p>
|
||||
<!-- #docregion prices -->
|
||||
|
||||
<div class="cart-item" *ngFor="let item of items">
|
||||
<span>{{ item.name }} </span>
|
||||
<span>{{ item.price | currency }}</span>
|
||||
</div>
|
||||
<!-- #enddocregion prices -->
|
@ -0,0 +1,21 @@
|
||||
// #docplaster
|
||||
// #docregion imports
|
||||
import { Component } from '@angular/core';
|
||||
import { CartService } from '../cart.service';
|
||||
// #enddocregion imports
|
||||
|
||||
@Component({
|
||||
selector: 'app-cart',
|
||||
templateUrl: './cart.component.html',
|
||||
styleUrls: ['./cart.component.css']
|
||||
})
|
||||
// #docregion inject-cart, items, submit
|
||||
export class CartComponent {
|
||||
// #enddocregion inject-cart
|
||||
items;
|
||||
// #docregion inject-cart
|
||||
|
||||
constructor(
|
||||
private cartService: CartService
|
||||
) { }
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
// #docplaster
|
||||
// #docregion imports
|
||||
import { Component } from '@angular/core';
|
||||
import { CartService } from '../cart.service';
|
||||
// #enddocregion imports
|
||||
|
||||
@Component({
|
||||
selector: 'app-cart',
|
||||
templateUrl: './cart.component.html',
|
||||
styleUrls: ['./cart.component.css']
|
||||
})
|
||||
// #docregion props-services, submit
|
||||
export class CartComponent {
|
||||
items;
|
||||
|
||||
constructor(
|
||||
private cartService: CartService
|
||||
) {
|
||||
this.items = this.cartService.getItems();
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<!-- #docplaster -->
|
||||
<!-- #docregion checkout-form-1, checkout-form-2 -->
|
||||
<h3>Cart</h3>
|
||||
|
||||
<p>
|
||||
<a routerLink="/shipping">Shipping Prices</a>
|
||||
</p>
|
||||
|
||||
<div class="cart-item" *ngFor="let item of items">
|
||||
<span>{{ item.name }} </span>
|
||||
<span>{{ item.price | currency }}</span>
|
||||
</div>
|
||||
|
||||
<form [formGroup]="checkoutForm" (ngSubmit)="onSubmit(checkoutForm.value)">
|
||||
<!-- #enddocregion checkout-form-1 -->
|
||||
<div>
|
||||
<label>Name</label>
|
||||
<input type="text" formControlName="name">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Address</label>
|
||||
<input type="text" formControlName="address">
|
||||
</div>
|
||||
|
||||
<button class="button" type="submit">Purchase</button>
|
||||
<!-- #docregion checkout-form-1 -->
|
||||
</form>
|
@ -0,0 +1,40 @@
|
||||
// #docplaster
|
||||
// #docregion imports
|
||||
import { Component } from '@angular/core';
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
|
||||
import { CartService } from '../cart.service';
|
||||
// #enddocregion imports
|
||||
|
||||
@Component({
|
||||
selector: 'app-cart',
|
||||
templateUrl: './cart.component.html',
|
||||
styleUrls: ['./cart.component.css']
|
||||
})
|
||||
// #docregion props-services, submit
|
||||
export class CartComponent {
|
||||
items;
|
||||
checkoutForm;
|
||||
|
||||
constructor(
|
||||
private cartService: CartService,
|
||||
private formBuilder: FormBuilder,
|
||||
) {
|
||||
this.items = this.cartService.getItems();
|
||||
|
||||
this.checkoutForm = this.formBuilder.group({
|
||||
name: '',
|
||||
address: ''
|
||||
});
|
||||
}
|
||||
|
||||
// #enddocregion props-services
|
||||
onSubmit(customerData) {
|
||||
// Process checkout data here
|
||||
console.warn('Your order has been submitted', customerData);
|
||||
|
||||
this.items = this.cartService.clearCart();
|
||||
this.checkoutForm.reset();
|
||||
}
|
||||
// #docregion props-services
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
<p *ngIf="product.price > 700">
|
||||
<button>Notify Me</button>
|
||||
</p>
|
@ -0,0 +1,19 @@
|
||||
// #docplaster
|
||||
// #docregion as-generated, imports
|
||||
import { Component } from '@angular/core';
|
||||
// #enddocregion as-generated
|
||||
import { Input } from '@angular/core';
|
||||
// #enddocregion imports
|
||||
// #docregion as-generated
|
||||
|
||||
@Component({
|
||||
selector: 'app-product-alerts',
|
||||
templateUrl: './product-alerts.component.html',
|
||||
styleUrls: ['./product-alerts.component.css']
|
||||
})
|
||||
// #docregion input-decorator
|
||||
export class ProductAlertsComponent {
|
||||
// #enddocregion as-generated
|
||||
@Input() product;
|
||||
// #docregion as-generated
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
<p *ngIf="product.price > 700">
|
||||
<button (click)="notify.emit()">Notify Me</button>
|
||||
</p>
|
@ -0,0 +1,17 @@
|
||||
// #docplaster
|
||||
// #docregion imports
|
||||
import { Component } from '@angular/core';
|
||||
import { Input } from '@angular/core';
|
||||
import { Output, EventEmitter } from '@angular/core';
|
||||
// #enddocregion imports
|
||||
|
||||
@Component({
|
||||
selector: 'app-product-alerts',
|
||||
templateUrl: './product-alerts.component.html',
|
||||
styleUrls: ['./product-alerts.component.css']
|
||||
})
|
||||
// #docregion input-output
|
||||
export class ProductAlertsComponent {
|
||||
@Input() product;
|
||||
@Output() notify = new EventEmitter();
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
// #docplaster
|
||||
// #docregion imports
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
// #enddocregion imports
|
||||
|
||||
@Component({
|
||||
selector: 'app-product-details',
|
||||
templateUrl: './product-details.component.html',
|
||||
styleUrls: ['./product-details.component.css']
|
||||
})
|
||||
// #docregion props-methods, add-to-cart
|
||||
export class ProductDetailsComponent implements OnInit {
|
||||
product;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
) { }
|
||||
|
||||
// #enddocregion props-methods
|
||||
// #docregion get-product
|
||||
ngOnInit() {
|
||||
this.route.paramMap.subscribe(params => {
|
||||
this.product = products[+params.get('productId')];
|
||||
});
|
||||
}
|
||||
// #enddocregion get-product
|
||||
// #docregion props-methods
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
<!-- #docplaster -->
|
||||
<!-- #docregion details -->
|
||||
<h2>Product Details</h2>
|
||||
|
||||
<div *ngIf="product">
|
||||
<h3>{{ product.name }}</h3>
|
||||
<h4>{{ product.price | currency }}</h4>
|
||||
<p>{{ product.description }}</p>
|
||||
|
||||
<!-- #enddocregion details -->
|
||||
<button (click)="addToCart(product)">Buy</button>
|
||||
<!-- #docregion details -->
|
||||
</div>
|
@ -0,0 +1,46 @@
|
||||
// #docplaster
|
||||
// #docregion imports, cart-service
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
// #enddocregion imports
|
||||
import { CartService } from '../cart.service';
|
||||
// #enddocregion cart-service
|
||||
|
||||
@Component({
|
||||
selector: 'app-product-details',
|
||||
templateUrl: './product-details.component.html',
|
||||
styleUrls: ['./product-details.component.css']
|
||||
})
|
||||
// #docregion props-methods, get-product, inject-cart-service, add-to-cart
|
||||
export class ProductDetailsComponent implements OnInit {
|
||||
// #enddocregion add-to-cart, get-product, inject-cart-service
|
||||
product;
|
||||
|
||||
// #docregion inject-cart-service
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
// #enddocregion props-methods
|
||||
private cartService: CartService
|
||||
// #docregion props-methods
|
||||
) { }
|
||||
// #enddocregion inject-cart-service
|
||||
|
||||
// #docregion get-product
|
||||
ngOnInit() {
|
||||
// #enddocregion props-methods
|
||||
this.route.paramMap.subscribe(params => {
|
||||
this.product = products[+params.get('productId')];
|
||||
});
|
||||
// #docregion props-methods
|
||||
}
|
||||
|
||||
// #enddocregion props-methods, get-product
|
||||
// #docregion add-to-cart
|
||||
addToCart(product) {
|
||||
window.alert('Your product has been added to the cart!');
|
||||
this.cartService.addToCart(product);
|
||||
}
|
||||
// #docregion props-methods, get-product, inject-cart-service
|
||||
}
|
@ -0,0 +1 @@
|
||||
<h2>Products</h2>
|
@ -0,0 +1,15 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
selector: 'app-product-list',
|
||||
templateUrl: './product-list.component.html',
|
||||
styleUrls: ['./product-list.component.css']
|
||||
})
|
||||
export class ProductListComponent {
|
||||
products = products;
|
||||
|
||||
share() {
|
||||
window.alert('The product has been shared!');
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<!-- #docplaster -->
|
||||
<!-- #docregion ngfor, interpolation -->
|
||||
<h2>Products</h2>
|
||||
|
||||
<div *ngFor="let product of products">
|
||||
<!-- #enddocregion ngfor -->
|
||||
|
||||
<h3>
|
||||
<!-- #enddocregion interpolation -->
|
||||
<a [title]="product.name + ' details'">
|
||||
<!-- #docregion interpolation -->
|
||||
{{ product.name }}
|
||||
<!-- #enddocregion interpolation -->
|
||||
</a>
|
||||
<!-- #docregion interpolation -->
|
||||
</h3>
|
||||
|
||||
<!-- #docregion ngfor -->
|
||||
</div>
|
||||
<!-- #enddocregion ngfor, interpolation -->
|
@ -0,0 +1,15 @@
|
||||
<h2>Products</h2>
|
||||
|
||||
<div *ngFor="let product of products">
|
||||
|
||||
<h3>
|
||||
<a [title]="product.name + ' details'">
|
||||
{{ product.name }}
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
<p *ngIf="product.description">
|
||||
Description: {{ product.description }}
|
||||
</p>
|
||||
|
||||
</div>
|
@ -0,0 +1,19 @@
|
||||
<h2>Products</h2>
|
||||
|
||||
<div *ngFor="let product of products">
|
||||
|
||||
<h3>
|
||||
<a [title]="product.name + ' details'">
|
||||
{{ product.name }}
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
<p *ngIf="product.description">
|
||||
Description: {{ product.description }}
|
||||
</p>
|
||||
|
||||
<button (click)="share()">
|
||||
Share
|
||||
</button>
|
||||
|
||||
</div>
|
@ -0,0 +1,28 @@
|
||||
<h2>Products</h2>
|
||||
|
||||
<div *ngFor="let product of products">
|
||||
|
||||
<!-- #docregion product-details -->
|
||||
<h3>
|
||||
<a [title]="product.name + ' details'">
|
||||
{{ product.name }}
|
||||
</a>
|
||||
</h3>
|
||||
<!-- #enddocregion product-details -->
|
||||
|
||||
<p *ngIf="product.description">
|
||||
Description: {{ product.description }}
|
||||
</p>
|
||||
|
||||
<!-- #docregion app-product-alerts -->
|
||||
<button (click)="share()">
|
||||
Share
|
||||
</button>
|
||||
|
||||
<app-product-alerts
|
||||
[product]="product">
|
||||
</app-product-alerts>
|
||||
<!-- #enddocregion app-product-alerts -->
|
||||
|
||||
</div>
|
||||
|
@ -0,0 +1,27 @@
|
||||
<h2>Products</h2>
|
||||
|
||||
<div *ngFor="let product of products">
|
||||
|
||||
<h3>
|
||||
<a [title]="product.name + ' details'">
|
||||
{{ product.name }}
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
<p *ngIf="product.description">
|
||||
Description: {{ product.description }}
|
||||
</p>
|
||||
|
||||
<!-- #docregion on-notify -->
|
||||
<button (click)="share()">
|
||||
Share
|
||||
</button>
|
||||
|
||||
<app-product-alerts
|
||||
[product]="product"
|
||||
(notify)="onNotify()">
|
||||
</app-product-alerts>
|
||||
<!-- #enddocregion on-notify -->
|
||||
|
||||
</div>
|
||||
|
@ -0,0 +1,26 @@
|
||||
<h2>Products</h2>
|
||||
|
||||
<!-- #docregion router-link -->
|
||||
<div *ngFor="let product of products; index as productId">
|
||||
|
||||
<h3>
|
||||
<a [title]="product.name + ' details'" [routerLink]="['/products', productId]">
|
||||
{{ product.name }}
|
||||
</a>
|
||||
</h3>
|
||||
<!-- #enddocregion router-link -->
|
||||
<p *ngIf="product.description">
|
||||
Description: {{ product.description }}
|
||||
</p>
|
||||
|
||||
<button (click)="share()">
|
||||
Share
|
||||
</button>
|
||||
|
||||
<app-product-alerts
|
||||
[product]="product"
|
||||
(notify)="onNotify()">
|
||||
</app-product-alerts>
|
||||
<!-- #docregion router-link -->
|
||||
</div>
|
||||
<!-- #enddocregion router-link -->
|
@ -0,0 +1,21 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
selector: 'app-product-list',
|
||||
templateUrl: './product-list.component.html',
|
||||
styleUrls: ['./product-list.component.css']
|
||||
})
|
||||
// #docregion on-notify
|
||||
export class ProductListComponent {
|
||||
products = products;
|
||||
|
||||
share() {
|
||||
window.alert('The product has been shared!');
|
||||
}
|
||||
|
||||
onNotify() {
|
||||
window.alert('You will be notified when the product goes on sale');
|
||||
}
|
||||
}
|
17
aio/content/examples/getting-started/src/app/products.ts
Normal file
17
aio/content/examples/getting-started/src/app/products.ts
Normal file
@ -0,0 +1,17 @@
|
||||
export const products = [
|
||||
{
|
||||
name: 'Phone XL',
|
||||
price: 799,
|
||||
description: 'A large phone with one of the best screens'
|
||||
},
|
||||
{
|
||||
name: 'Phone Mini',
|
||||
price: 699,
|
||||
description: 'A great phone with one of the best cameras'
|
||||
},
|
||||
{
|
||||
name: 'Phone Standard',
|
||||
price: 299,
|
||||
description: ''
|
||||
}
|
||||
];
|
@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shipping',
|
||||
templateUrl: './shipping.component.html',
|
||||
styleUrls: ['./shipping.component.css']
|
||||
})
|
||||
export class Shipping1Component implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
<h3>Shipping Prices</h3>
|
||||
|
||||
<div class="shipping-item" *ngFor="let shipping of shippingCosts | async">
|
||||
<span>{{ shipping.type }} </span>
|
||||
<span>{{ shipping.price | currency }}</span>
|
||||
</div>
|
@ -0,0 +1,22 @@
|
||||
// #docplaster
|
||||
// #docregion imports
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { CartService } from '../cart.service';
|
||||
// #enddocregion
|
||||
|
||||
@Component({
|
||||
selector: 'app-shipping',
|
||||
templateUrl: './shipping.component.html',
|
||||
styleUrls: ['./shipping.component.css']
|
||||
})
|
||||
// #docregion props, ctor
|
||||
export class ShippingComponent {
|
||||
shippingCosts;
|
||||
// #enddocregion props
|
||||
|
||||
constructor(private cartService: CartService) {
|
||||
this.shippingCosts = this.cartService.getShippingPrices();
|
||||
}
|
||||
// #docregion props
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
<a>
|
||||
<h1>My Store</h1>
|
||||
</a>
|
||||
|
||||
<a class="button fancy-button">
|
||||
<i class="material-icons">shopping_cart</i>Checkout
|
||||
</a>
|
@ -0,0 +1,7 @@
|
||||
<a [routerLink]="['/']">
|
||||
<h1>My Store</h1>
|
||||
</a>
|
||||
|
||||
<a [routerLink]="['/cart']" class="button fancy-button">
|
||||
<i class="material-icons">shopping_cart</i>Checkout
|
||||
</a>
|
@ -0,0 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-top-bar',
|
||||
templateUrl: './top-bar.component.html',
|
||||
styleUrls: ['./top-bar.component.css']
|
||||
})
|
||||
export class TopBarComponent {
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"type": "Overnight",
|
||||
"price": 25.99
|
||||
},
|
||||
{
|
||||
"type": "2-Day",
|
||||
"price": 9.99
|
||||
},
|
||||
{
|
||||
"type": "Postal",
|
||||
"price": 2.99
|
||||
}
|
||||
]
|
18
aio/content/examples/getting-started/src/index.html
Normal file
18
aio/content/examples/getting-started/src/index.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Angular Getting Started</title>
|
||||
<base href="/" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/icon?family=Material+Icons"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
@ -1,11 +1,12 @@
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module.0';
|
||||
import { AppModule } from './app/app.module';
|
||||
import { environment } from './environments/environment';
|
||||
|
||||
if (environment.production) {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||
.catch(err => console.error(err));
|
9
aio/content/examples/getting-started/stackblitz.json
Normal file
9
aio/content/examples/getting-started/stackblitz.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"description": "Getting Started",
|
||||
"files":[
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[0-9].*"
|
||||
],
|
||||
"tags": ["Angular", "getting started", "tutorial"]
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
{
|
||||
"description": "Contact NgModule v.1",
|
||||
"files": [
|
||||
"src/app/app.component.1b.ts",
|
||||
"src/app/app.module.1b.ts",
|
||||
"src/app/highlight.directive.ts",
|
||||
"src/app/title.component.html",
|
||||
"src/app/title.component.ts",
|
||||
"src/app/user.service.ts",
|
||||
|
||||
"src/app/contact/awesome.pipe.ts",
|
||||
"src/app/contact/contact.component.css",
|
||||
"src/app/contact/contact.component.html",
|
||||
"src/app/contact/contact.component.3.ts",
|
||||
"src/app/contact/contact.service.ts",
|
||||
"src/app/contact/contact-highlight.directive.ts",
|
||||
|
||||
"src/main.1b.ts",
|
||||
"src/styles.css",
|
||||
"src/index.1b.html"
|
||||
],
|
||||
"main": "src/index.1b.html",
|
||||
"tags": ["NgModule"]
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
{
|
||||
"description": "Contact NgModule v.2",
|
||||
"files": [
|
||||
"src/app/app.component.2.ts",
|
||||
"src/app/app.module.2.ts",
|
||||
"src/app/highlight.directive.ts",
|
||||
"src/app/title.component.html",
|
||||
"src/app/title.component.ts",
|
||||
"src/app/user.service.ts",
|
||||
|
||||
"src/app/contact/contact.component.css",
|
||||
"src/app/contact/contact.component.html",
|
||||
"src/app/contact/contact.service.ts",
|
||||
|
||||
"src/app/contact/awesome.pipe.ts",
|
||||
"src/app/contact/contact.component.3.ts",
|
||||
"src/app/contact/contact.module.2.ts",
|
||||
"src/app/contact/contact-highlight.directive.ts",
|
||||
|
||||
"src/main.2.ts",
|
||||
"src/styles.css",
|
||||
"src/index.2.html"
|
||||
],
|
||||
"main": "src/index.2.html",
|
||||
"tags": ["NgModule"]
|
||||
}
|
@ -1,223 +0,0 @@
|
||||
'use strict'; // necessary for es6 output in node
|
||||
|
||||
import { browser, element, by } from 'protractor';
|
||||
|
||||
describe('NgModule', function () {
|
||||
|
||||
// helpers
|
||||
const gold = 'rgba(255, 215, 0, 1)';
|
||||
const powderblue = 'rgba(176, 224, 230, 1)';
|
||||
const lightgray = 'rgba(211, 211, 211, 1)';
|
||||
const white = 'rgba(0, 0, 0, 0)';
|
||||
|
||||
function getCommonsSectionStruct() {
|
||||
const buttons = element.all(by.css('nav a'));
|
||||
|
||||
return {
|
||||
title: element.all(by.tagName('h1')).get(0),
|
||||
welcome: element.all(by.css('app-title p i')).get(0),
|
||||
contactButton: buttons.get(0),
|
||||
crisisButton: buttons.get(1),
|
||||
heroesButton: buttons.get(2)
|
||||
};
|
||||
}
|
||||
|
||||
function getContactSectionStruct() {
|
||||
const buttons = element.all(by.css('app-contact form button'));
|
||||
|
||||
return {
|
||||
header: element.all(by.css('app-contact h2')).get(0),
|
||||
popupMessage: element.all(by.css('app-contact div')).get(0),
|
||||
contactNameHeader: element.all(by.css('app-contact form h3')).get(0),
|
||||
input: element.all(by.css('app-contact form input')).get(0),
|
||||
validationError: element.all(by.css('app-contact form .alert')).get(0),
|
||||
saveButton: buttons.get(0), // can't be tested
|
||||
nextContactButton: buttons.get(1),
|
||||
newContactButton: buttons.get(2)
|
||||
};
|
||||
}
|
||||
|
||||
function getCrisisSectionStruct() {
|
||||
return {
|
||||
title: element.all(by.css('ng-component h3')).get(0),
|
||||
items: element.all(by.css('ng-component a')),
|
||||
itemId: element.all(by.css('ng-component div')).get(0),
|
||||
listLink: element.all(by.css('ng-component a')).get(0),
|
||||
};
|
||||
}
|
||||
|
||||
function getHeroesSectionStruct() {
|
||||
return {
|
||||
header: element.all(by.css('ng-component h2')).get(0),
|
||||
title: element.all(by.css('ng-component h3')).get(0),
|
||||
items: element.all(by.css('ng-component a')),
|
||||
itemId: element.all(by.css('ng-component ng-component div div')).get(0),
|
||||
itemInput: element.all(by.css('ng-component ng-component input')).get(0),
|
||||
listLink: element.all(by.css('ng-component ng-component a')).get(0),
|
||||
};
|
||||
}
|
||||
|
||||
// tests
|
||||
function appTitleTests(color: string, name?: string) {
|
||||
return function() {
|
||||
it('should have a gray header', function() {
|
||||
const commons = getCommonsSectionStruct();
|
||||
expect(commons.title.getCssValue('backgroundColor')).toBe(color);
|
||||
});
|
||||
|
||||
it('should welcome us', function () {
|
||||
const commons = getCommonsSectionStruct();
|
||||
expect(commons.welcome.getText()).toBe('Welcome, ' + (name || 'Sherlock Holmes'));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function contactTests(color: string, name?: string) {
|
||||
return function() {
|
||||
it('shows the contact\'s owner', function() {
|
||||
const contacts = getContactSectionStruct();
|
||||
expect(contacts.header.getText()).toBe('Contact of ' + (name || 'Sherlock Holmes'));
|
||||
});
|
||||
|
||||
it('can cycle between contacts', function () {
|
||||
const contacts = getContactSectionStruct();
|
||||
const nextButton = contacts.nextContactButton;
|
||||
expect(contacts.contactNameHeader.getText()).toBe('Awesome Sam Spade');
|
||||
expect(contacts.contactNameHeader.getCssValue('backgroundColor')).toBe(color);
|
||||
nextButton.click().then(function () {
|
||||
expect(contacts.contactNameHeader.getText()).toBe('Awesome Nick Danger');
|
||||
return nextButton.click();
|
||||
}).then(function () {
|
||||
expect(contacts.contactNameHeader.getText()).toBe('Awesome Nancy Drew');
|
||||
});
|
||||
});
|
||||
|
||||
it('can change an existing contact', function () {
|
||||
const contacts = getContactSectionStruct();
|
||||
contacts.input.sendKeys('a');
|
||||
expect(contacts.input.getCssValue('backgroundColor')).toBe(color);
|
||||
expect(contacts.contactNameHeader.getText()).toBe('Awesome Sam Spadea');
|
||||
});
|
||||
|
||||
it('can create a new contact', function () {
|
||||
const contacts = getContactSectionStruct();
|
||||
const newContactButton = contacts.newContactButton;
|
||||
newContactButton.click().then(function () {
|
||||
expect(contacts.validationError.getText()).toBe('Name is required');
|
||||
contacts.input.sendKeys('John Doe');
|
||||
expect(contacts.contactNameHeader.getText()).toBe('Awesome John Doe');
|
||||
expect(contacts.validationError.getText()).toBe('');
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
describe('index.html', function () {
|
||||
beforeEach(function () {
|
||||
browser.get('');
|
||||
});
|
||||
|
||||
describe('app-title', appTitleTests(white, 'Miss Marple'));
|
||||
|
||||
describe('contact', contactTests(lightgray, 'Miss Marple'));
|
||||
|
||||
describe('crisis center', function () {
|
||||
beforeEach(function () {
|
||||
getCommonsSectionStruct().crisisButton.click();
|
||||
});
|
||||
|
||||
it('shows a list of crisis', function () {
|
||||
const crisis = getCrisisSectionStruct();
|
||||
expect(crisis.title.getText()).toBe('Crisis List');
|
||||
expect(crisis.items.count()).toBe(4);
|
||||
expect(crisis.items.get(0).getText()).toBe('1 - Dragon Burning Cities');
|
||||
});
|
||||
|
||||
it('can navigate to one crisis details', function () {
|
||||
const crisis = getCrisisSectionStruct();
|
||||
crisis.items.get(0).click().then(function() {
|
||||
expect(crisis.itemId.getText()).toBe('Crisis id: 1');
|
||||
return crisis.listLink.click();
|
||||
}).then(function () {
|
||||
// We are back to the list
|
||||
expect(crisis.items.count()).toBe(4);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('heroes', function () {
|
||||
beforeEach(function () {
|
||||
getCommonsSectionStruct().heroesButton.click();
|
||||
});
|
||||
|
||||
it('shows a list of heroes', function() {
|
||||
const heroes = getHeroesSectionStruct();
|
||||
expect(heroes.header.getText()).toBe('Heroes of Miss Marple');
|
||||
expect(heroes.title.getText()).toBe('Hero List');
|
||||
expect(heroes.items.count()).toBe(6);
|
||||
expect(heroes.items.get(0).getText()).toBe('11 - Mr. Nice');
|
||||
});
|
||||
|
||||
it('can navigate and edit one hero details', function () {
|
||||
const heroes = getHeroesSectionStruct();
|
||||
heroes.items.get(0).click().then(function () {
|
||||
expect(heroes.itemId.getText()).toBe('Id: 11');
|
||||
heroes.itemInput.sendKeys(' try');
|
||||
return heroes.listLink.click();
|
||||
}).then(function () {
|
||||
// We are back to the list
|
||||
expect(heroes.items.count()).toBe(6);
|
||||
expect(heroes.items.get(0).getText()).toBe('11 - Mr. Nice try');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// describe('index.0.html', function() {
|
||||
// beforeEach(function () {
|
||||
// browser.get('index.0.html');
|
||||
// });
|
||||
|
||||
// it('has a title', function () {
|
||||
// const title = element.all(by.tagName('h1')).get(0);
|
||||
// expect(title.getText()).toBe('Minimal NgModule');
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('index.1.html', function () {
|
||||
// beforeEach(function () {
|
||||
// browser.get('index.1.html');
|
||||
// });
|
||||
|
||||
// describe('app-title', appTitleTests(powderblue));
|
||||
// });
|
||||
|
||||
// describe('index.1b.html', function () {
|
||||
// beforeEach(function () {
|
||||
// browser.get('index.1b.html');
|
||||
// });
|
||||
|
||||
// describe('app-title', appTitleTests(powderblue));
|
||||
|
||||
// describe('contact', contactTests(powderblue));
|
||||
// });
|
||||
|
||||
// describe('index.2.html', function () {
|
||||
// beforeEach(function () {
|
||||
// browser.get('index.2.html');
|
||||
// });
|
||||
|
||||
// describe('app-title', appTitleTests(gold));
|
||||
|
||||
// describe('contact', contactTests(powderblue));
|
||||
// });
|
||||
|
||||
// describe('index.3.html', function () {
|
||||
// beforeEach(function () {
|
||||
// browser.get('index.3.html');
|
||||
// });
|
||||
|
||||
// describe('app-title', appTitleTests(gold));
|
||||
// });
|
||||
|
||||
});
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"description": "Minimal NgModule",
|
||||
"files": [
|
||||
"src/app/app.component.0.ts",
|
||||
"src/app/app.module.0.ts",
|
||||
"src/main.0.ts",
|
||||
"src/styles.css",
|
||||
"src/index.0.html"
|
||||
],
|
||||
"main": "src/index.0.html",
|
||||
"tags": ["NgModule"]
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
{
|
||||
"description": "NgModule v.3",
|
||||
"files": [
|
||||
"src/app/app.component.3.ts",
|
||||
"src/app/app.module.3.ts",
|
||||
"src/app/app-routing.module.3.ts",
|
||||
|
||||
"src/app/highlight.directive.ts",
|
||||
"src/app/title.component.html",
|
||||
"src/app/title.component.ts",
|
||||
"src/app/user.service.ts",
|
||||
|
||||
"src/app/contact/contact.component.css",
|
||||
"src/app/contact/contact.component.html",
|
||||
"src/app/contact/contact.service.ts",
|
||||
|
||||
"src/app/contact/awesome.pipe.ts",
|
||||
"src/app/contact/contact.component.3.ts",
|
||||
"src/app/contact/contact.module.3.ts",
|
||||
"src/app/contact/contact-routing.module.3.ts",
|
||||
"src/app/contact/contact-highlight.directive.ts",
|
||||
|
||||
"src/app/crisis/*.ts",
|
||||
|
||||
"src/app/hero/hero-detail.component.ts",
|
||||
"src/app/hero/hero-list.component.ts",
|
||||
"src/app/hero/hero.service.ts",
|
||||
|
||||
"src/app/hero/hero.component.3.ts",
|
||||
"src/app/hero/hero.module.3.ts",
|
||||
"src/app/hero/hero-routing.module.3.ts",
|
||||
"src/app/hero/highlight.directive.ts",
|
||||
|
||||
"src/main.3.ts",
|
||||
"src/styles.css",
|
||||
"src/index.3.html"
|
||||
],
|
||||
"main": "src/index.3.html",
|
||||
"tags": ["NgModule"]
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { ContactModule } from './contact/contact.module.3';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: 'contact', pathMatch: 'full'},
|
||||
{ path: 'crisis', loadChildren: './crisis/crisis.module#CrisisModule' },
|
||||
{ path: 'heroes', loadChildren: './hero/hero.module.3#HeroModule' }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
ContactModule,
|
||||
RouterModule.forRoot(routes)
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule {}
|
@ -1,30 +0,0 @@
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { ContactModule } from './contact/contact.module';
|
||||
|
||||
// #docregion routes
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: 'contact', pathMatch: 'full'},
|
||||
// #docregion lazy-routes
|
||||
{ path: 'crisis', loadChildren: './crisis/crisis.module#CrisisModule' },
|
||||
{ path: 'heroes', loadChildren: './hero/hero.module#HeroModule' }
|
||||
// #enddocregion lazy-routes
|
||||
];
|
||||
// #enddocregion routes
|
||||
|
||||
@NgModule({
|
||||
// #docregion imports
|
||||
imports: [
|
||||
ContactModule,
|
||||
// #docregion forRoot
|
||||
RouterModule.forRoot(routes),
|
||||
// #enddocregion forRoot
|
||||
],
|
||||
// #enddocregion imports
|
||||
// #docregion exports
|
||||
exports: [RouterModule]
|
||||
// #enddocregion exports
|
||||
})
|
||||
export class AppRoutingModule {}
|
@ -1,17 +0,0 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
// #enddocregion
|
||||
/*
|
||||
// #docregion template
|
||||
template: '<h1 highlight>{{title}}</h1>'
|
||||
// #enddocregion template
|
||||
*/
|
||||
// #docregion
|
||||
template: '<app-title></app-title>'
|
||||
})
|
||||
export class AppComponent {}
|
||||
// #enddocregion
|
@ -1,13 +0,0 @@
|
||||
// #docregion
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
// #docregion template
|
||||
template: `
|
||||
<app-title></app-title>
|
||||
<app-contact></app-contact>
|
||||
`
|
||||
// #enddocregion template
|
||||
})
|
||||
export class AppComponent {}
|
@ -1,10 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: `
|
||||
<app-title></app-title>
|
||||
<app-contact></app-contact>
|
||||
`
|
||||
})
|
||||
export class AppComponent {}
|
@ -1,17 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
// #docregion template
|
||||
template: `
|
||||
<app-title></app-title>
|
||||
<nav>
|
||||
<a routerLink="contact" routerLinkActive="active">Contact</a>
|
||||
<a routerLink="crisis" routerLinkActive="active">Crisis Center</a>
|
||||
<a routerLink="heroes" routerLinkActive="active">Heroes</a>
|
||||
</nav>
|
||||
<router-outlet></router-outlet>
|
||||
`
|
||||
// #enddocregion template
|
||||
})
|
||||
export class AppComponent {}
|
@ -1,17 +0,0 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: `
|
||||
<app-title></app-title>
|
||||
<nav>
|
||||
<a routerLink="contact" routerLinkActive="active">Contact</a>
|
||||
<a routerLink="crisis" routerLinkActive="active">Crisis Center</a>
|
||||
<a routerLink="heroes" routerLinkActive="active">Heroes</a>
|
||||
</nav>
|
||||
<router-outlet></router-outlet>
|
||||
`
|
||||
})
|
||||
export class AppComponent {}
|
@ -1,13 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
import { AppComponent } from './app.component.0';
|
||||
|
||||
@NgModule({
|
||||
// #docregion imports
|
||||
imports: [ BrowserModule ],
|
||||
// #enddocregion imports
|
||||
declarations: [ AppComponent ],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule { }
|
@ -1,52 +0,0 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
/* Angular Imports */
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
/* App Imports */
|
||||
// #enddocregion
|
||||
import { AppComponent } from './app.component.1';
|
||||
/*
|
||||
// #docregion
|
||||
import { AppComponent } from './app.component';
|
||||
// #enddocregion
|
||||
*/
|
||||
// #docregion
|
||||
import { HighlightDirective } from './highlight.directive';
|
||||
import { TitleComponent } from './title.component';
|
||||
import { UserService } from './user.service';
|
||||
|
||||
/* Contact Related Imports */
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { AwesomePipe } from './contact/awesome.pipe';
|
||||
import { ContactComponent } from './contact/contact.component.3';
|
||||
import {
|
||||
ContactHighlightDirective as ContactHighlightDirective
|
||||
} from './contact/contact-highlight.directive';
|
||||
|
||||
@NgModule({
|
||||
// #docregion imports
|
||||
imports: [ BrowserModule, FormsModule ],
|
||||
// #enddocregion imports
|
||||
// #docregion declarations, directive, component
|
||||
declarations: [
|
||||
AppComponent,
|
||||
HighlightDirective,
|
||||
// #enddocregion directive
|
||||
TitleComponent,
|
||||
// #enddocregion component
|
||||
|
||||
AwesomePipe,
|
||||
ContactComponent,
|
||||
ContactHighlightDirective
|
||||
// #docregion directive, component
|
||||
],
|
||||
// #enddocregion declarations, directive, component
|
||||
// #docregion providers
|
||||
providers: [ UserService ],
|
||||
// #enddocregion providers
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule { }
|
@ -1,46 +0,0 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
/* Angular Imports */
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
/* App Imports */
|
||||
// #enddocregion
|
||||
import { AppComponent } from './app.component.1b';
|
||||
/*
|
||||
// #docregion
|
||||
import { AppComponent } from './app.component';
|
||||
// #enddocregion
|
||||
*/
|
||||
// #docregion
|
||||
import { HighlightDirective } from './highlight.directive';
|
||||
import { TitleComponent } from './title.component';
|
||||
import { UserService } from './user.service';
|
||||
|
||||
/* Contact Imports */
|
||||
// #enddocregion
|
||||
import { ContactComponent } from './contact/contact.component.3';
|
||||
/*
|
||||
// #docregion
|
||||
import { ContactComponent } from './contact/contact.component';
|
||||
// #enddocregion
|
||||
*/
|
||||
// #docregion
|
||||
import { AwesomePipe } from './contact/awesome.pipe';
|
||||
import { ContactService } from './contact/contact.service';
|
||||
import { ContactHighlightDirective } from './contact/contact-highlight.directive';
|
||||
|
||||
@NgModule({
|
||||
imports: [ BrowserModule, FormsModule ],
|
||||
// #docregion declarations
|
||||
declarations: [
|
||||
AppComponent, HighlightDirective, TitleComponent,
|
||||
AwesomePipe, ContactComponent, ContactHighlightDirective
|
||||
],
|
||||
// #docregion providers
|
||||
providers: [ ContactService, UserService ],
|
||||
// #enddocregion providers
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule { }
|
@ -1,36 +0,0 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
/* Angular Imports */
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
/* App Imports */
|
||||
// #enddocregion
|
||||
import { AppComponent } from './app.component.2';
|
||||
/*
|
||||
// #docregion
|
||||
import { AppComponent } from './app.component';
|
||||
// #enddocregion
|
||||
*/
|
||||
// #docregion
|
||||
import { HighlightDirective } from './highlight.directive';
|
||||
import { TitleComponent } from './title.component';
|
||||
import { UserService } from './user.service';
|
||||
|
||||
/* Contact Imports */
|
||||
// #enddocregion
|
||||
import { ContactModule } from './contact/contact.module.2';
|
||||
/*
|
||||
// #docregion
|
||||
import { ContactModule } from './contact/contact.module';
|
||||
// #enddocregion
|
||||
*/
|
||||
// #docregion
|
||||
|
||||
@NgModule({
|
||||
imports: [ BrowserModule, ContactModule ],
|
||||
declarations: [ AppComponent, HighlightDirective, TitleComponent ],
|
||||
providers: [ UserService ],
|
||||
bootstrap: [ AppComponent ],
|
||||
})
|
||||
export class AppModule { }
|
@ -1,39 +0,0 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
// #docregion v4
|
||||
/* Angular Imports */
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
/* App Imports */
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
/* Core Modules */
|
||||
import { CoreModule } from './core/core.module';
|
||||
|
||||
/* Routing Module */
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
|
||||
@NgModule({
|
||||
// #docregion import-for-root
|
||||
imports: [
|
||||
BrowserModule,
|
||||
// #enddocregion v4
|
||||
// #enddocregion import-for-root
|
||||
/*
|
||||
// #docregion v4
|
||||
CoreModule,
|
||||
// #enddocregion v4
|
||||
*/
|
||||
// #docregion import-for-root
|
||||
CoreModule.forRoot({userName: 'Miss Marple'}),
|
||||
// #docregion v4
|
||||
AppRoutingModule
|
||||
],
|
||||
// #enddocregion import-for-root
|
||||
declarations: [ AppComponent ],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule { }
|
||||
// #enddocregion v4
|
||||
// #enddocregion
|
@ -1,14 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { ContactComponent } from './contact.component.3';
|
||||
|
||||
const routes = [
|
||||
{ path: 'contact', component: ContactComponent}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [ RouterModule.forChild(routes) ],
|
||||
exports: [ RouterModule ]
|
||||
})
|
||||
export class ContactRoutingModule {}
|
@ -1,16 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { ContactComponent } from './contact.component';
|
||||
|
||||
// #docregion routing
|
||||
const routes = [
|
||||
{ path: 'contact', component: ContactComponent}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [ RouterModule.forChild(routes) ],
|
||||
exports: [ RouterModule ]
|
||||
})
|
||||
export class ContactRoutingModule {}
|
||||
// #enddocregion
|
@ -1,53 +0,0 @@
|
||||
// #docregion
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { Contact, ContactService } from './contact.service';
|
||||
import { UserService } from '../user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-contact',
|
||||
templateUrl: './contact.component.html',
|
||||
styleUrls: [ './contact.component.css' ]
|
||||
})
|
||||
export class ContactComponent implements OnInit {
|
||||
contact: Contact;
|
||||
contacts: Contact[];
|
||||
|
||||
msg = 'Loading contacts ...';
|
||||
userName = '';
|
||||
|
||||
constructor(private contactService: ContactService, userService: UserService) {
|
||||
this.userName = userService.userName;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.contactService.getContacts().subscribe(contacts => {
|
||||
this.msg = '';
|
||||
this.contacts = contacts;
|
||||
this.contact = contacts[0];
|
||||
});
|
||||
}
|
||||
|
||||
next() {
|
||||
let ix = 1 + this.contacts.indexOf(this.contact);
|
||||
if (ix >= this.contacts.length) { ix = 0; }
|
||||
this.contact = this.contacts[ix];
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
// POST-DEMO TODO: do something like save it
|
||||
this.displayMessage('Saved ' + this.contact.name);
|
||||
}
|
||||
|
||||
newContact() {
|
||||
this.displayMessage('New contact');
|
||||
this.contact = {id: 42, name: ''};
|
||||
this.contacts.push(this.contact);
|
||||
}
|
||||
|
||||
/** Display a message briefly, then remove it. */
|
||||
displayMessage(msg: string) {
|
||||
this.msg = msg;
|
||||
setTimeout(() => this.msg = '', 1500);
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
/* #docregion */
|
||||
.ng-valid[required] {
|
||||
border-left: 5px solid #42A948; /* green */
|
||||
}
|
||||
|
||||
.ng-invalid {
|
||||
border-left: 5px solid #a94442; /* red */
|
||||
}
|
||||
|
||||
.alert {
|
||||
padding: 15px;
|
||||
margin: 8px 0;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.alert-danger {
|
||||
color: #a94442;
|
||||
background-color: #f2dede;
|
||||
border-color: #ebccd1;
|
||||
}
|
||||
|
||||
.msg {
|
||||
color: blue;
|
||||
background-color: whitesmoke;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
padding-top: 12px;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
<!-- #docregion -->
|
||||
<h2>Contact of {{userName}}</h2>
|
||||
<div *ngIf="msg" class="msg">{{msg}}</div>
|
||||
|
||||
<form *ngIf="contacts" (ngSubmit)="onSubmit()" #contactForm="ngForm">
|
||||
<!-- #docregion awesome -->
|
||||
<h3 highlight>{{ contact.name | awesome }}</h3>
|
||||
<!-- #enddocregion awesome -->
|
||||
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
|
||||
<!-- #docregion ngModel -->
|
||||
<input type="text" class="form-control" required
|
||||
[(ngModel)]="contact.name"
|
||||
name="name" #name="ngModel" >
|
||||
<!-- #enddocregion ngModel -->
|
||||
|
||||
<div [hidden]="name.valid" class="alert alert-danger">
|
||||
Name is required
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="button-group">
|
||||
<button type="submit" class="btn btn-default"
|
||||
[disabled]="!contactForm.form.valid">
|
||||
Save</button>
|
||||
|
||||
<button type="button" class="btn" (click)="next()"
|
||||
[disabled]="!contactForm.form.valid">
|
||||
Next Contact</button>
|
||||
|
||||
<button type="button" class="btn" (click)="newContact()">
|
||||
New Contact</button>
|
||||
</div>
|
||||
</form>
|
||||
<!-- #enddocregion -->
|
@ -1,54 +0,0 @@
|
||||
// Exact copy except import UserService from core
|
||||
// #docregion
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { Contact, ContactService } from './contact.service';
|
||||
import { UserService } from '../core/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-contact',
|
||||
templateUrl: './contact.component.html',
|
||||
styleUrls: [ './contact.component.css' ]
|
||||
})
|
||||
export class ContactComponent implements OnInit {
|
||||
contact: Contact;
|
||||
contacts: Contact[];
|
||||
|
||||
msg = 'Loading contacts ...';
|
||||
userName = '';
|
||||
|
||||
constructor(private contactService: ContactService, userService: UserService) {
|
||||
this.userName = userService.userName;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.contactService.getContacts().subscribe(contacts => {
|
||||
this.msg = '';
|
||||
this.contacts = contacts;
|
||||
this.contact = contacts[0];
|
||||
});
|
||||
}
|
||||
|
||||
next() {
|
||||
let ix = 1 + this.contacts.indexOf(this.contact);
|
||||
if (ix >= this.contacts.length) { ix = 0; }
|
||||
this.contact = this.contacts[ix];
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
// POST-DEMO TODO: do something like save it
|
||||
this.displayMessage('Saved ' + this.contact.name);
|
||||
}
|
||||
|
||||
newContact() {
|
||||
this.displayMessage('New contact');
|
||||
this.contact = {id: 42, name: ''};
|
||||
this.contacts.push(this.contact);
|
||||
}
|
||||
|
||||
/** Display a message briefly, then remove it. */
|
||||
displayMessage(msg: string) {
|
||||
this.msg = msg;
|
||||
setTimeout(() => this.msg = '', 1500);
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule
|
||||
],
|
||||
declarations: []
|
||||
})
|
||||
export class ContactModule { }
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user