diff --git a/.bazelignore b/.bazelignore index a4f2c566f4..64c85b64d2 100644 --- a/.bazelignore +++ b/.bazelignore @@ -1,7 +1,10 @@ +.git node_modules dist aio/content aio/node_modules aio/tools/examples/shared/node_modules integration/bazel +integration/bazel-schematics/demo +integration/platform-server/node_modules packages/bazel/node_modules diff --git a/.bazelrc b/.bazelrc index a778c2bf5e..49d20925c2 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,20 +1,3 @@ -################################ -# Settings for Angular team members only -################################ -# To enable this feature check the "Remote caching" section in docs/BAZEL.md. -build:angular-team --remote_http_cache=https://storage.googleapis.com/angular-team-cache - -############################### -# Typescript / Angular / Sass # -############################### - -# Make compilation fast, by keeping a few copies of the compilers -# running as daemons, and cache SourceFile AST's to reduce parse time. -build --strategy=AngularTemplateCompile=worker -# TODO(alexeagle): re-enable after fixing worker instability with rxjs typings -# build --strategy=TypeScriptCompile=worker -build --strategy=TypeScriptCompile=standalone - # Enable debugging tests with --config=debug test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test_strategy=exclusive --test_timeout=9999 --nocache_test_results @@ -35,11 +18,8 @@ test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test # See https://github.com/bazelbuild/bazel/issues/4603 build --symlink_prefix=dist/ -# 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 +build --nolegacy_external_runfiles run --nolegacy_external_runfiles test --nolegacy_external_runfiles @@ -53,22 +33,6 @@ build --incompatible_strict_action_env run --incompatible_strict_action_env test --incompatible_strict_action_env -############################### -# Saucelabs support # -# Turn on these settings with # -# --config=saucelabs # -############################### - -# Expose SauceLabs environment to actions -# These environment variables are needed by -# web_test_karma to run on Saucelabs -test:saucelabs --action_env=SAUCE_USERNAME -test:saucelabs --action_env=SAUCE_ACCESS_KEY -test:saucelabs --action_env=SAUCE_READY_FILE -test:saucelabs --action_env=SAUCE_PID_FILE -test:saucelabs --action_env=SAUCE_TUNNEL_IDENTIFIER -test:saucelabs --define=KARMA_WEB_TEST_MODE=SL_REQUIRED - ############################### # Release support # # Turn on these settings with # @@ -91,37 +55,43 @@ query --output=label_kind # By default, failing tests don't print any output, it goes to the log file test --test_output=errors -# Show which actions are run under workers, -# and print all the actions running in parallel. -# Helps to demonstrate that bazel uses all the cores on the machine. -build --experimental_ui -test --experimental_ui - ################################ # Settings for CircleCI # ################################ -# Bazel flags for CircleCI are in /.circleci/bazel.rc +# Bazel flags for CircleCI are in /.circleci/bazel.linux.rc and /.circleci/bazel.windows.rc ################################ # Temporary Settings for Ivy # ################################ -# to determine if the compiler used should be Ivy or ViewEngine one can use `--define=compile=aot` on -# any bazel target. This is a temporary flag until codebase is permanently switched to Ivy. -build --define=compile=legacy +# To determine if the compiler used should be Ivy instead of ViewEngine, one can use `--config=ivy` +# on any bazel target. This is a temporary flag until codebase is permanently switched to Ivy. +build --define=angular_ivy_enabled=False -############################### -# Remote Build Execution support -# Turn on these settings with -# --config=remote -############################### +build:view-engine --define=angular_ivy_enabled=False +build:ivy --define=angular_ivy_enabled=True -# Load default settings for Remote Build Execution. -import %workspace%/third_party/github.com/bazelbuild/bazel-toolchains/bazelrc/.bazelrc.notoolchain +################################## +# Remote Build Execution support # +# Turn on these settings with # +# --config=remote # +################################## + +# The following --define=EXECUTOR=remote will be able to be removed +# once https://github.com/bazelbuild/bazel/issues/7254 is fixed +build:remote --define=EXECUTOR=remote + +# Set a higher timeout value, just in case. +build:remote --remote_timeout=600 # Increase the default number of jobs by 50% because our build has lots of # parallelism build:remote --jobs=150 +build:remote --google_default_credentials + +# Force remote exeuctions to consider the entire run as linux +build:remote --cpu=k8 +build:remote --host_cpu=k8 # Toolchain and platform related flags build:remote --host_javabase=@rbe_ubuntu1604_angular//java:jdk @@ -135,13 +105,26 @@ build:remote --extra_execution_platforms=//tools:rbe_ubuntu1604-angular build:remote --host_platform=//tools:rbe_ubuntu1604-angular build:remote --platforms=//tools:rbe_ubuntu1604-angular -# Remote instance. +# Remote instance and caching build:remote --remote_instance_name=projects/internal-200822/instances/default_instance +build:remote --project_id=internal-200822 +build:remote --remote_cache=remotebuildexecution.googleapis.com +build:remote --remote_executor=remotebuildexecution.googleapis.com -# Do not accept remote cache. -# We need to understand the security risks of using prior build artifacts. -build:remote --remote_accept_cached=false +############################### +# NodeJS rules settings +# These settings are required for rules_nodejs +############################### -# Load any settings specific to the current user. Needs to be last statement in this -# config, as the user configuration should be able to overwrite flags from this file. +# Turn on managed directories feature in Bazel +# This allows us to avoid installing a second copy of node_modules +common --experimental_allow_incremental_repository_updates + +#################################################### +# User bazel configuration +# NOTE: This needs to be the *last* entry in the config. +#################################################### + +# Load any settings which are specific to the current user. Needs to be *last* statement +# in this config, as the user configuration should be able to overwrite flags from this file. try-import .bazelrc.user diff --git a/.circleci/bazel.common.rc b/.circleci/bazel.common.rc new file mode 100644 index 0000000000..ab84c0ed80 --- /dev/null +++ b/.circleci/bazel.common.rc @@ -0,0 +1,19 @@ +# Settings in this file should be OS agnostic. Use the bazel..rc files for OS specific settings. + +# Don't be spammy in the logs +build --noshow_progress + +# Print all the options that apply to the build. +# This helps us diagnose which options override others +# (e.g. /etc/bazel.bazelrc vs. tools/bazel.rc) +build --announce_rc + +# Retry in the event of flakes, eg. https://circleci.com/gh/angular/angular/31309 +test --flaky_test_attempts=2 + +# More details on failures +build --verbose_failures=true + +# For saucelabs tests we don't want to enable flaky test attempts. Karma has its own integrated +# retry mechanism and we do not want to retry unnecessarily if Karma already tried multiple times. +test:saucelabs --flaky_test_attempts=1 diff --git a/.circleci/bazel.rc b/.circleci/bazel.linux.rc similarity index 55% rename from .circleci/bazel.rc rename to .circleci/bazel.linux.rc index 315c2667d0..f79956d523 100644 --- a/.circleci/bazel.rc +++ b/.circleci/bazel.linux.rc @@ -2,29 +2,16 @@ # We do this by copying this file to /etc/bazel.bazelrc at the start of the build. # See documentation in /docs/BAZEL.md +# Import config items common to both Linux and Windows setups. +# https://docs.bazel.build/versions/master/guide.html#bazelrc-syntax-and-semantics +import %workspace%/.circleci/bazel.common.rc + # Save downloaded repositories in a location that can be cached by CircleCI. This helps us # speeding up the analysis time significantly with Bazel managed node dependencies on the CI. build --repository_cache=/home/circleci/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 - -# Print all the options that apply to the build. -# This helps us diagnose which options override others -# (e.g. /etc/bazel.bazelrc vs. tools/bazel.rc) -build --announce_rc - # Workaround https://github.com/bazelbuild/bazel/issues/3645 # Bazel doesn't calculate the memory ceiling correctly when running under Docker. # Limit Bazel to consuming resources that fit in CircleCI "xlarge" class # https://circleci.com/docs/2.0/configuration-reference/#resource_class build --local_resources=14336,8.0,1.0 - -# Retry in the event of flakes, eg. https://circleci.com/gh/angular/angular/31309 -test --flaky_test_attempts=2 - -# More details on failures -build --verbose_failures=true diff --git a/.circleci/bazel.windows.rc b/.circleci/bazel.windows.rc new file mode 100644 index 0000000000..eee8e7e791 --- /dev/null +++ b/.circleci/bazel.windows.rc @@ -0,0 +1,17 @@ +# These options are enabled when running on CI +# We do this by copying this file to $env:ProgramData\bazel.bazelrc at the start of the build. +# See documentation in /docs/BAZEL.md + +# Import config items common to both Linux and Windows setups. +# https://docs.bazel.build/versions/master/guide.html#bazelrc-syntax-and-semantics +import %workspace%/.circleci/bazel.common.rc + +# Save downloaded repositories in a location that can be cached by CircleCI. This helps us +# speeding up the analysis time significantly with Bazel managed node dependencies on the CI. +build --repository_cache=C:/Users/circleci/bazel_repository_cache + +# All windows jobs run on master and should use http caching +build --remote_http_cache=https://storage.googleapis.com/angular-team-cache +build --remote_accept_cached=true +build --remote_upload_local_results=true +build --google_default_credentials diff --git a/.circleci/config.yml b/.circleci/config.yml index 682bc0c2e6..ead922855a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,128 +7,248 @@ # To validate changes, use an online parser, eg. # http://yaml-online-parser.appspot.com/ -# Note that the browser docker image comes with Chrome and Firefox preinstalled. This is just -# needed for jobs that run tests without Bazel. Bazel runs tests with browsers that will be -# fetched by the Webtesting rules. Therefore for jobs that run tests with Bazel, we don't need a -# docker image with browsers pre-installed. -# **NOTE 1**: If you change the version of the `*-browsers` docker image, make sure the -# `CI_CHROMEDRIVER_VERSION_ARG` env var (in `.circleci/env.sh`) points to a ChromeDriver -# version that is compatible with the Chrome version in the image. -# **NOTE 2**: If you change the version of the docker images, also change the `cache_key` suffix. -var_1: &default_docker_image circleci/node:10.12 -var_2: &browsers_docker_image circleci/node:10.12-browsers +# CircleCI configuration version +# Version 2.1 allows for extra config reuse features +# https://circleci.com/docs/2.0/reusing-config/#getting-started-with-config-reuse +version: 2.1 + # We don't want to include the current branch name in the cache key because that would prevent # PRs from being able to restore the cache since the branch names are always different for PRs. # The cache key should only consist of dynamic values that change whenever something in the # cache changes. For example: # 1) yarn lock file changes --> cached "node_modules" are different. # 2) bazel repository definitions change --> cached bazel repositories are different. -# **NOTE 1 **: If you change the cache key prefix, also sync the restore_cache fallback to match. +# Windows needs its own cache key because binaries in node_modules are different. +# **NOTE 1 **: If you change the cache key prefix, also sync the cache_key_fallback to match. # **NOTE 2 **: Keep the static part of the cache key as prefix to enable correct fallbacks. # See https://circleci.com/docs/2.0/caching/#restoring-cache for how prefixes work in CircleCI. -var_3: &cache_key v3-angular-node-10.12-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }} +var_3: &cache_key v3-angular-node-10.16-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }} +var_4: &cache_key_fallback v3-angular-node-10.16- +var_3_win: &cache_key_win v5-angular-win-node-12.0-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }} +var_4_win: &cache_key_win_fallback v5-angular-win-node-12.0- -# Initializes the CI environment by setting up common environment variables. -var_4: &init_environment - run: - name: Initializing environment (setting up variables, overwriting Yarn) - # Overwrite the yarn installed in the docker container with our own version. - command: | - ./.circleci/env.sh - ourYarn=$(realpath ./third_party/github.com/yarnpkg/yarn/releases/download/v1.13.0/bin/yarn.js) - sudo chmod a+x $ourYarn - sudo ln -fs $ourYarn /usr/local/bin/yarn - echo "Yarn version: $(yarn --version)" +# Cache key for the Material unit tests job. **Note** when updating the SHA in the cache keys, +# also update the SHA for the "MATERIAL_REPO_COMMIT" environment variable. +var_5: &material_unit_tests_cache_key v5-angular-material-c734deb14bb28579ba59e7e065a39e3c4ed54458 +var_6: &material_unit_tests_cache_key_fallback v5-angular-material- - # Add GitHub to known hosts. - mkdir -p ~/.ssh - echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' >> ~/.ssh/known_hosts - - # use git+ssh instead of https - git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true - git config --global gc.auto 0 || true - - -var_5: &setup_bazel_remote_execution - run: - name: "Setup bazel RBE remote execution" - command: | - openssl aes-256-cbc -d -in .circleci/gcp_token -k "$CI_REPO_NAME" -out /home/circleci/.gcp_credentials - echo "export GOOGLE_APPLICATION_CREDENTIALS=/home/circleci/.gcp_credentials" >> $BASH_ENV - sudo bash -c "echo 'build --config=remote' >> /etc/bazel.bazelrc" - -# Settings common to each job -var_6: &job_defaults - working_directory: ~/ng - docker: - - image: *default_docker_image - -# After checkout, rebase on top of target branch. -var_7: &post_checkout - run: - name: Rebase PR on target branch - command: > - if [[ -n "${CIRCLE_PR_NUMBER}" ]]; then - # User is required for rebase. - git config user.name "angular-ci" - git config user.email "angular-ci" - # Rebase PR on top of target branch. - node tools/rebase-pr.js angular/angular ${CIRCLE_PR_NUMBER} - else - echo "This build is not over a PR, nothing to do." - fi - -var_8: &yarn_install - run: - name: Running Yarn install - command: | - # Yarn's requests sometimes take more than 10mins to complete. - # Print something to stdout, to prevent CircleCI from failing due to not output. - while true; do sleep 60; echo "[`date`] Keeping alive..."; done & - KEEP_ALIVE_PID=$! - yarn install --frozen-lockfile --non-interactive - kill $KEEP_ALIVE_PID - -var_9: &setup_circleci_bazel_config - run: - name: Setting up CircleCI bazel configuration - command: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc - -var_10: &restore_cache - restore_cache: - keys: - - *cache_key - # This fallback should be the cache_key without variables. - - v3-angular-node-10.12- - -# Branch filter that can be specified for jobs that should only run on publish branches -# (e.g. master or the patch branch) -var_12: &publish_branches_filter - branches: - only: - - master - # e.g. 7.0.x, 7.1.x, etc. - - /\d+\.\d+\.x/ - -# Workspace initially persisted by the `install` job, and then enhanced by `test_aio` and -# `build-npm-packages`. +# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and +# `build-ivy-npm-packages`. # https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs # https://circleci.com/blog/deep-diving-into-circleci-workspaces/ -var_13: &attach_workspace - attach_workspace: - at: ~/ +var_7: &workspace_location ~/ -version: 2 +# Filter to run a job on builds for pull requests only. +var_8: &only_on_pull_requests + filters: + branches: + only: + - /pull\/\d+/ + +# Filter to skip a job on builds for pull requests. +var_9: &skip_on_pull_requests + filters: + branches: + ignore: + - /pull\/\d+/ + +# Filter to run a job on builds for the master branch only. +var_10: &only_on_master + filters: + branches: + only: + - master + +# Executor Definitions +# https://circleci.com/docs/2.0/reusing-config/#authoring-reusable-executors +# **NOTE 1**: Pin to exact images using an ID (SHA). See https://circleci.com/docs/2.0/circleci-images/#using-a-docker-image-id-to-pin-an-image-to-a-fixed-version. +# (Using the tag in not necessary when pinning by ID, but include it anyway for documentation purposes.) +# **NOTE 2**: If you change the version of the docker images, also change the `cache_key` suffix. +# **NOTE 3**: If you change the version of the `*-browsers` docker image, make sure the +# `CI_CHROMEDRIVER_VERSION_ARG` env var (in `.circleci/env.sh`) points to a ChromeDriver +# version that is compatible with the Chrome version in the image. +executors: + default-executor: + parameters: + resource_class: + type: string + default: medium + docker: + - image: circleci/node:10.16@sha256:75c05084fff4afa3683a03c5a04a4a3ad95c536ff2439d8fe14e7e1f5c58b09a + resource_class: << parameters.resource_class >> + working_directory: ~/ng + + browsers-executor: + parameters: + resource_class: + type: string + default: medium + docker: + # The browser docker image comes with Chrome and Firefox preinstalled. This is just + # needed for jobs that run tests without Bazel. Bazel runs tests with browsers that will be + # fetched by the Webtesting rules. Therefore for jobs that run tests with Bazel, we don't need a + # docker image with browsers pre-installed. + - image: circleci/node:10.16-browsers@sha256:d2a96fe1cbef51257ee626b5f645e64dade3e886f00ba9cb7e8ea65b4efe8db1 + resource_class: << parameters.resource_class >> + working_directory: ~/ng + + windows-executor: + working_directory: ~/ng + resource_class: windows.medium + # CircleCI windows VMs do have the GitBash shell available: + # https://github.com/CircleCI-Public/windows-preview-docs#shells + # But in this specific case we really should not use it because Bazel must not be ran from + # GitBash. These issues discuss why: + # https://github.com/bazelbuild/bazel/issues/5751 + # https://github.com/bazelbuild/bazel/issues/5724#issuecomment-410194038 + # https://github.com/bazelbuild/bazel/issues/6339#issuecomment-441600879 + shell: powershell.exe -ExecutionPolicy Bypass + machine: + # Windows preview image that includes the following: + # - Visual Studio 2019 build tools + # - Node 12 + # - yarn 1.17 + # - Python 3 3.7.4 + image: windows-server-2019-vs2019:201908-02 + +# Command Definitions +# https://circleci.com/docs/2.0/reusing-config/#authoring-reusable-commands +commands: + custom_attach_workspace: + description: Attach workspace at a predefined location + steps: + - attach_workspace: + at: *workspace_location + + # Overwrite the yarn installed in the docker container with our own version. + overwrite_yarn: + description: Overwrite yarn with our own version + steps: + - run: + name: Overwrite yarn + command: | + localYarnPath=`node ./.circleci/get-vendored-yarn-path.js` + sudo chmod a+x $localYarnPath + sudo ln -fs $localYarnPath /usr/local/bin/yarn + - run: node --version + - run: yarn --version + + # Initializes the CI environment by setting up common environment variables. + init_environment: + description: Initializing environment (setting up variables, overwriting Yarn) + steps: + - run: ./.circleci/env.sh + - overwrite_yarn + - run: + # Configure git as the CircleCI `checkout` command does. + # This is needed because we only checkout on the setup job. + # Add GitHub to known hosts + name: Configure git + command: | + mkdir -p ~/.ssh + echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' >> ~/.ssh/known_hosts + git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true + git config --global gc.auto 0 || true + + # Normally this would be an individual job instead of a command. + # But startup and setup time for each invidual windows job are high enough to discourage + # many small jobs, so instead we use a command for setup unless the gain becomes significant. + setup_win: + description: Setup windows node environment + steps: + # Use the Linux workspace directly, as it already has checkout, rebased and node modules. + - custom_attach_workspace + # Install Bazel pre-requisites that aren't in the preconfigured CircleCI Windows VM. + - run: ./.circleci/windows-env.ps1 + - run: + # Overwrite the yarn installed in the docker container with our own version. + name: Overwrite yarn with our own version + command: ./.circleci/windows-yarn-setup.ps1 + - run: node --version + - run: yarn --version + - restore_cache: + keys: + - *cache_key_win + - *cache_key_win_fallback + # Reinstall to get windows binaries. + - run: yarn install --frozen-lockfile --non-interactive + - setup_circleci_bazel_config_win + # Install @bazel/bazel globally and use that for the first run. + # Workaround for https://github.com/bazelbuild/rules_nodejs/issues/894 + - run: yarn global add @bazel/bazel@$env:BAZEL_VERSION + - run: bazel info + + setup_circleci_bazel_config: + description: Set up CircleCI bazel configuration on Linux + steps: + - run: sudo cp .circleci/bazel.linux.rc $HOME/.bazelrc + + setup_circleci_bazel_config_win: + description: Set up CircleCI bazel configuration on Windows + steps: + - run: copy .circleci\bazel.windows.rc $env:USERPROFILE\.bazelrc + - run: mkdir $env:APPDATA\gcloud + # We need ensure that the same default digest is used for encoding and decoding + # with openssl. Openssl versions might have different default digests which can + # cause decryption failures based on the openssl version. https://stackoverflow.com/a/39641378/4317734 + - run: openssl aes-256-cbc -d -in .circleci\gcp_token -md md5 -out "$env:APPDATA\gcloud\application_default_credentials.json" -k "$env:CIRCLE_PROJECT_REPONAME" + + setup_bazel_rbe: + description: Setup bazel RBE remote execution + steps: + # We need ensure that the same default digest is used for encoding and decoding + # with openssl. Openssl versions might have different default digests which can + # cause decryption failures based on the openssl version. https://stackoverflow.com/a/39641378/4317734 + - run: openssl aes-256-cbc -d -in .circleci/gcp_token -md md5 -k "$CI_REPO_NAME" -out /home/circleci/.gcp_credentials + - run: echo "export GOOGLE_APPLICATION_CREDENTIALS=/home/circleci/.gcp_credentials" >> $BASH_ENV + - run: ./.circleci/setup-rbe.sh .bazelrc.user + + notify_webhook_on_fail: + description: Notify a webhook about failure + parameters: + # `webhook_url_env_var` are secret env vars defined in CircleCI project settings. + # The URLs come from https://angular-team.slack.com/apps/A0F7VRE7N-circleci. + webhook_url_env_var: + type: env_var_name + steps: + - run: + when: on_fail + command: | + notificationJson="{\"text\":\":x: \`$CIRCLE_JOB\` job for $CIRCLE_BRANCH branch failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}" + curl --request POST --header "Content-Type: application/json" --data "$notificationJson" ${<< parameters.webhook_url_env_var >>} + +# Job definitions +# Jobs can include parameters that are passed in the workflow job invocation. +# https://circleci.com/docs/2.0/reusing-config/#authoring-parameterized-jobs jobs: setup: - <<: *job_defaults + executor: default-executor steps: - checkout - - *post_checkout + - run: + name: Rebase PR on target branch + # After checkout, rebase on top of target branch. + command: > + if [[ -n "${CIRCLE_PR_NUMBER}" ]]; then + # User is required for rebase. + git config user.name "angular-ci" + git config user.email "angular-ci" + # Rebase PR on top of target branch. + node tools/rebase-pr.js angular/angular ${CIRCLE_PR_NUMBER} + else + echo "This build is not over a PR, nothing to do." + fi # This cache is saved in the build-npm-packages so that Bazel cache is also included. - - *restore_cache - - *init_environment - - *yarn_install + - restore_cache: + keys: + - *cache_key + - *cache_key_fallback + - init_environment + - run: + name: Running Yarn install + command: yarn install --frozen-lockfile --non-interactive + # Yarn's requests sometimes take more than 10mins to complete. + no_output_timeout: 45m - run: yarn --cwd aio install --frozen-lockfile --non-interactive # Make the bazel directories and add a file to them if they don't exist already so that # persist_to_workspace does not fail. @@ -138,19 +258,18 @@ jobs: touch ~/bazel_repository_cache/MARKER fi # Persist any changes at this point to be reused by further jobs. - # **NOTE 1 **: Folders persisted here should be kept in sync with `var_13: &attach_workspace`. - # **NOTE 2 **: To add new content to the workspace, always persist on the same root. + # **NOTE**: To add new content to the workspace, always persist on the same root. - persist_to_workspace: - root: ~/ + root: *workspace_location paths: - ./ng - ./bazel_repository_cache lint: - <<: *job_defaults + executor: default-executor steps: - - *attach_workspace - - *init_environment + - custom_attach_workspace + - init_environment - run: 'yarn bazel:format -mode=check || (echo "BUILD files not formatted. Please run ''yarn bazel:format''" ; exit 1)' @@ -159,36 +278,39 @@ jobs: (echo -e "\n.bzl files have lint errors. Please run ''yarn bazel:lint-fix''"; exit 1)' - run: yarn gulp lint + - run: node tools/verify-codeownership test: - <<: *job_defaults - resource_class: xlarge + executor: + name: default-executor + resource_class: xlarge steps: - - *attach_workspace - - *init_environment - - *setup_circleci_bazel_config - # Enable remote/sibling docker which is needed by auto-selection of toolchain configs for RBE. - - setup_remote_docker + - custom_attach_workspace + - init_environment + - setup_circleci_bazel_config # Setup remote execution and run RBE-compatible tests. - - *setup_bazel_remote_execution - - run: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only + - setup_bazel_rbe + - run: + command: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only + no_output_timeout: 20m # Temporary job to test what will happen when we flip the Ivy flag to true test_ivy_aot: - <<: *job_defaults - resource_class: xlarge + executor: + name: default-executor + resource_class: xlarge steps: - - *attach_workspace - - *init_environment - - *setup_circleci_bazel_config - # Enable remote/sibling docker which is needed by auto-selection of toolchain configs for RBE. - - setup_remote_docker - - *setup_bazel_remote_execution + - custom_attach_workspace + - init_environment + - setup_circleci_bazel_config + - setup_bazel_rbe # We need to explicitly specify the --symlink_prefix option because otherwise we would # not be able to easily find the output bin directory when uploading artifacts for size # measurements. - - run: yarn test-ivy-aot //... --symlink_prefix=dist/ + - run: + command: yarn test-ivy-aot //... --symlink_prefix=dist/ + no_output_timeout: 20m # Publish bundle artifacts which will be used to calculate the size change. **Note**: Make # sure that the size plugin from the Angular robot fetches the artifacts from this CircleCI @@ -209,113 +331,127 @@ jobs: path: dist/bin/packages/core/test/bundling/todo/bundle.min.js.br destination: core/todo/bundle.br - test_saucelabs_bazel: - <<: *job_defaults - # In order to avoid the bottleneck of having a slow host machine, we acquire a better - # container for this job. This is necessary because we launch a lot of browsers concurrently - # and therefore the tunnel and Karma need to process a lot of file requests and tests. - resource_class: xlarge + # This job is currently a PoC for running tests on SauceLabs via bazel. It runs a subset of the + # tests in `legacy-unit-tests-saucelabs` (see + # [BUILD.bazel](https://github.com/angular/angular/blob/ef44f51d5/BUILD.bazel#L66-L92)). + # + # NOTE: This is currently limited to master builds only. See the `default_workflow` configuration. + saucelabs_view_engine: + executor: + name: default-executor + # In order to avoid the bottleneck of having a slow host machine, we acquire a better + # container for this job. This is necessary because we launch a lot of browsers concurrently + # and therefore the tunnel and Karma need to process a lot of file requests and tests. + resource_class: xlarge steps: - - *attach_workspace - - *init_environment - - *setup_circleci_bazel_config + - custom_attach_workspace + - init_environment + - setup_circleci_bazel_config + - setup_bazel_rbe - run: - name: Preparing environment for running tests on Saucelabs. - command: setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev) + name: Run Bazel tests in saucelabs + # All web tests are contained within a single //:saucelabs_unit_tests_poc target + # for Saucelabs as running each set of tests as a separate target will attempt to acquire + # too many browsers on Saucelabs (7 per target currently) and some tests will always + # fail to acquire browsers. For example: + # 14 02 2019 19:52:33.170:WARN [launcher]: chrome beta on SauceLabs have not captured in 180000 ms, killing. + # //packages/forms/test:web_test_sauce TIMEOUT in 315.0s + command: | + ./scripts/saucelabs/run-bazel-via-tunnel.sh \ + --tunnel-id angular-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX} \ + --username $SAUCE_USERNAME \ + --key $(echo $SAUCE_ACCESS_KEY | rev) \ + -- yarn bazel test //:saucelabs_unit_tests_poc --config=saucelabs + no_output_timeout: 20m + - notify_webhook_on_fail: + webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL + + saucelabs_ivy: + executor: + name: default-executor + # In order to avoid the bottleneck of having a slow host machine, we acquire a better + # container for this job. This is necessary because we launch a lot of browsers concurrently + # and therefore the tunnel and Karma need to process a lot of file requests and tests. + resource_class: xlarge + steps: + - custom_attach_workspace + - init_environment + - setup_circleci_bazel_config + - setup_bazel_rbe - run: - name: Starting Saucelabs tunnel - command: ./scripts/saucelabs/start-tunnel.sh - background: true - # Waits for the Saucelabs tunnel to be ready. This ensures that we don't run tests - # too early without Saucelabs not being ready. - - run: ./scripts/saucelabs/wait-for-tunnel.sh - # All web tests are contained within a single //:test_web_all target for Saucelabs - # as running each set of tests as a separate target will attempt to acquire too - # many browsers on Saucelabs (7 per target currently) and some tests will always - # fail to acquire browsers. For example: - # 14 02 2019 19:52:33.170:WARN [launcher]: chrome beta on SauceLabs have not captured in 180000 ms, killing. - # //packages/forms/test:web_test_sauce TIMEOUT in 315.0s - - run: yarn bazel test --config=saucelabs //:test_web_all - - run: ./scripts/saucelabs/stop-tunnel.sh + name: Run Bazel tests on Saucelabs + # Runs the //:saucelabs_tests target with Saucelabs and Ivy. + command: | + ./scripts/saucelabs/run-bazel-via-tunnel.sh \ + --tunnel-id angular-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX} \ + --username $SAUCE_USERNAME \ + --key $(echo $SAUCE_ACCESS_KEY | rev) \ + -- yarn bazel test //:saucelabs_unit_tests --config=ivy --config=saucelabs + no_output_timeout: 20m test_aio: - <<: *job_defaults - docker: - # Needed because the AIO tests and the PWA score test depend on Chrome being available. - - image: *browsers_docker_image + # Needed because the AIO tests and the PWA score test depend on Chrome being available. + executor: browsers-executor steps: - - *attach_workspace - - *init_environment + - custom_attach_workspace + - init_environment + # Compile dependencies to ivy + # Running `ngcc` here (instead of implicitly via `ng build`) allows us to take advantage of + # the parallel, async mode speed-up (~20-25s on CI). + - run: yarn --cwd aio ngcc --properties es2015 # Build aio - run: yarn --cwd aio build --progress=false # Lint the code - run: yarn --cwd aio lint - # Run PWA-score tests - # (Run before unit and e2e tests, which destroy the `dist/` directory.) - - run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE - # Check the bundle sizes. - # (Run before unit and e2e tests, which destroy the `dist/` directory.) - - run: yarn --cwd aio payload-size # Run unit tests - run: yarn --cwd aio test --progress=false --watch=false # Run e2e tests - run: yarn --cwd aio e2e --configuration=ci + # Run PWA-score tests + - run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE + # Run accessibility tests + - run: yarn --cwd aio test-a11y-score-localhost + # Check the bundle sizes. + - run: yarn --cwd aio payload-size # Run unit tests for Firebase redirects - run: yarn --cwd aio redirects-test deploy_aio: - <<: *job_defaults - docker: # Needed because before deploying the deploy-production script runs the PWA score tests. - - image: *browsers_docker_image + executor: browsers-executor steps: - - *attach_workspace - - *init_environment + - custom_attach_workspace + - init_environment # Deploy angular.io to production (if necessary) - run: setPublicVar_CI_STABLE_BRANCH - run: yarn --cwd aio deploy-production test_aio_local: - <<: *job_defaults - docker: - # Needed because the AIO tests and the PWA score test depend on Chrome being available. - - image: *browsers_docker_image + parameters: + viewengine: + type: boolean + default: false + # Needed because the AIO tests and the PWA score test depend on Chrome being available. + executor: browsers-executor steps: - - *attach_workspace - - *init_environment + - custom_attach_workspace + - init_environment # Build aio (with local Angular packages) - - run: yarn --cwd aio build-local --progress=false - # Run PWA-score tests - # (Run before unit and e2e tests, which destroy the `dist/` directory.) - - run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE + - run: yarn --cwd aio build-local<<# parameters.viewengine >>-with-viewengine<>-ci # Run unit tests - run: yarn --cwd aio test --progress=false --watch=false # Run e2e tests - run: yarn --cwd aio e2e --configuration=ci - - test_aio_local_ivy: - <<: *job_defaults - docker: - # Needed because the AIO tests and the PWA score test depend on Chrome being available. - - image: *browsers_docker_image - steps: - - *attach_workspace - - *init_environment - # Build aio with Ivy (using local Angular packages) - - run: yarn --cwd aio build-with-ivy --progress=false # Run PWA-score tests - # (Run before unit and e2e tests, which destroy the `dist/` directory.) - run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE - # Run unit tests - - run: yarn --cwd aio test --progress=false --watch=false - # Run e2e tests - - run: yarn --cwd aio e2e --configuration=ci + # Check the bundle sizes. + - run: yarn --cwd aio payload-size aio-local<<# parameters.viewengine >>-viewengine<> test_aio_tools: - <<: *job_defaults + executor: default-executor steps: - - *attach_workspace - - *init_environment + - custom_attach_workspace + - init_environment # Install - run: yarn --cwd aio install --frozen-lockfile --non-interactive - run: yarn --cwd aio extract-cli-command-docs @@ -324,56 +460,42 @@ jobs: - run: ./aio/aio-builds-setup/scripts/test.sh test_docs_examples: - <<: *job_defaults - docker: + parameters: + ivy: + type: boolean + default: false + executor: # Needed because the example e2e tests depend on Chrome. - - image: *browsers_docker_image - parallelism: 4 - resource_class: xlarge - steps: - - *attach_workspace - - *init_environment - # Install aio - - run: yarn --cwd aio install --frozen-lockfile --non-interactive - # Run examples tests. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled. - # Since the parallelism is set to "3", there will be three parallel CircleCI containers - # with either "0", "1" or "2" as node index. This can be passed to the "--shard" argument. - - run: yarn --cwd aio example-e2e --setup --local --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL} - - test_docs_examples_ivy: - <<: *job_defaults - docker: - # Needed because the example e2e tests depend on Chrome. - - image: *browsers_docker_image - resource_class: xlarge - # We increase the parallelism here to five while the "test_docs_examples" job runs with - # a parallelism of four. This is necessary because this job also need to run NGCC which - # takes up more time and we don't want these jobs to impact the overall CI turnaround. + name: browsers-executor + resource_class: xlarge parallelism: 5 steps: - - *attach_workspace - - *init_environment + - custom_attach_workspace + - init_environment # Install aio - run: yarn --cwd aio install --frozen-lockfile --non-interactive - # Rename the Ivy packages dist folder to "dist/packages-dist" as the AIO - # package installer picks up the locally built packages from that location. - # *Note*: We could also adjust the packages installer, but given we won't have - # two different folders of Angular distributions in the future, we should keep - # the packages installer unchanged. - - run: mv dist/packages-dist-ivy-aot dist/packages-dist - # Run examples tests with ivy. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled. - # Since the parallelism is set to "3", there will be three parallel CircleCI containers - # with either "0", "1" or "2" as node index. This can be passed to the "--shard" argument. - - run: yarn --cwd aio example-e2e --setup --local --ivy --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL} + - when: + condition: << parameters.ivy >> + steps: + # Rename the Ivy packages dist folder to "dist/packages-dist" as the AIO + # package installer picks up the locally built packages from that location. + # *Note*: We could also adjust the packages installer, but given we won't have + # two different folders of Angular distributions in the future, we should keep + # the packages installer unchanged. + - run: mv dist/packages-dist-ivy-aot dist/packages-dist + # Run examples tests. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled. + # Since the parallelism is set to "5", there will be five parallel CircleCI containers. + # with either "0", "1", etc as node index. This can be passed to the "--shard" argument. + - run: yarn --cwd aio example-e2e --setup --local <<# parameters.ivy >>--ivy<> --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL} --retry 2 # This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`. aio_preview: - <<: *job_defaults + executor: default-executor environment: AIO_SNAPSHOT_ARTIFACT_PATH: &aio_preview_artifact_path 'aio/tmp/snapshot.tgz' steps: - - *attach_workspace - - *init_environment + - custom_attach_workspace + - init_environment - run: ./aio/scripts/build-artifacts.sh $AIO_SNAPSHOT_ARTIFACT_PATH $CI_PULL_REQUEST $CI_COMMIT - store_artifacts: path: *aio_preview_artifact_path @@ -384,13 +506,11 @@ jobs: # This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`. test_aio_preview: - <<: *job_defaults - docker: - # Needed because the test-preview script runs e2e tests and the PWA score test with Chrome. - - image: *browsers_docker_image + # Needed because the test-preview script runs e2e tests and the PWA score test with Chrome. + executor: browsers-executor steps: - - *attach_workspace - - *init_environment + - custom_attach_workspace + - init_environment - run: yarn --cwd aio install --frozen-lockfile --non-interactive - run: name: Wait for preview and run tests @@ -406,23 +526,23 @@ jobs: # Build the view engine npm packages. No new jobs should depend on this. build-npm-packages: - <<: *job_defaults - resource_class: xlarge + executor: + name: default-executor + resource_class: xlarge steps: - - *attach_workspace - - *init_environment - - *setup_circleci_bazel_config - # Enable remote/sibling docker which is needed by auto-selection of toolchain configs for RBE. - - setup_remote_docker - - *setup_bazel_remote_execution + - custom_attach_workspace + - init_environment + - setup_circleci_bazel_config + - setup_bazel_rbe - - run: scripts/build-packages-dist.sh + - run: node scripts/build-packages-dist.js # Save the npm packages from //packages/... for other workflow jobs to read - persist_to_workspace: - root: ~/ + root: *workspace_location paths: - ng/dist/packages-dist + - ng/dist/zone.js-dist # Save dependencies and bazel repository cache to use on subsequent runs. - save_cache: @@ -434,21 +554,20 @@ jobs: # Build the ivy npm packages. build-ivy-npm-packages: - <<: *job_defaults - resource_class: xlarge + executor: + name: default-executor + resource_class: xlarge steps: - - *attach_workspace - - *init_environment - - *setup_circleci_bazel_config - # Enable remote/sibling docker which is needed by auto-selection of toolchain configs for RBE. - - setup_remote_docker - - *setup_bazel_remote_execution + - custom_attach_workspace + - init_environment + - setup_circleci_bazel_config + - setup_bazel_rbe - - run: scripts/build-ivy-npm-packages.sh + - run: node scripts/build-ivy-npm-packages.js # Save the npm packages from //packages/... for other workflow jobs to read - persist_to_workspace: - root: ~/ + root: *workspace_location paths: - ng/dist/packages-dist-ivy-aot @@ -459,26 +578,55 @@ jobs: # need to re-run manually should be alleviated. # See comments inside the integration/run_tests.sh script. integration_test: - <<: *job_defaults - parallelism: 4 - docker: + executor: # Needed because the integration tests expect Chrome to be installed (e.g cli-hello-world) - - image: *browsers_docker_image - # Note: we run Bazel in one of the integration tests, and it can consume >2G - # of memory. Together with the system under test, this can exhaust the RAM - # on a 4G worker so we use a larger machine here too. - resource_class: xlarge + name: browsers-executor + # Note: we run Bazel in one of the integration tests, and it can consume >2G + # of memory. Together with the system under test, this can exhaust the RAM + # on a 4G worker so we use a larger machine here too. + resource_class: xlarge + parallelism: 4 steps: - - *attach_workspace - - *init_environment + - custom_attach_workspace + - init_environment # Runs the integration tests in parallel across multiple CircleCI container instances. The # amount of container nodes for this job is controlled by the "parallelism" option. - run: ./integration/run_tests.sh ${CIRCLE_NODE_INDEX} ${CIRCLE_NODE_TOTAL} + # This job creates compressed tarballs (`.tgz` files) for all Angular packages and stores them as + # build artifacts. This makes it easy to try out changes from a PR build for testing purposes. + # More info CircleCI build artifacts: https://circleci.com/docs/2.0/artifacts + # + # NOTE: Currently, this job only runs for PR builds. See `publish_snapshot` for non-PR builds. + publish_packages_as_artifacts: + executor: default-executor + environment: + NG_PACKAGES_DIR: &ng_packages_dir 'dist/packages-dist' + NG_PACKAGES_ARCHIVES_DIR: &ng_packages_archives_dir 'dist/packages-dist-archives' + ZONEJS_PACKAGES_DIR: &zonejs_packages_dir 'dist/zone.js-dist' + ZONEJS_PACKAGES_ARCHIVES_DIR: &zonejs_packages_archives_dir 'dist/zone.js-dist-archives' + steps: + - custom_attach_workspace + - init_environment + # Publish `@angular/*` packages. + - run: + name: Create artifacts for @angular/* packages + command: ./scripts/ci/create-package-archives.sh $CI_BRANCH $CI_COMMIT $NG_PACKAGES_DIR $NG_PACKAGES_ARCHIVES_DIR + - store_artifacts: + path: *ng_packages_archives_dir + destination: angular + # Publish `zone.js` package. + - run: + name: Create artifacts for zone.js package + command: ./scripts/ci/create-package-archives.sh $CI_BRANCH $CI_COMMIT $ZONEJS_PACKAGES_DIR $ZONEJS_PACKAGES_ARCHIVES_DIR + - store_artifacts: + path: *zonejs_packages_archives_dir + destination: zone.js + # This job updates the content of repos like github.com/angular/core-builds # for every green build on angular/angular. publish_snapshot: - <<: *job_defaults + executor: default-executor steps: # See below - ideally this job should not trigger for non-upstream builds. # But since it does, we have to check this condition. @@ -492,70 +640,72 @@ jobs: [[ "$CIRCLE_PROJECT_REPONAME" != "angular" ]]; then circleci step halt fi - - *attach_workspace - - *init_environment + - custom_attach_workspace + - init_environment # CircleCI has a config setting to force SSH for all github connections # This is not compatible with our mechanism of using a Personal Access Token # Clear the global setting - run: git config --global --unset "url.ssh://git@github.com.insteadof" - run: name: Decrypt github credentials - command: 'openssl aes-256-cbc -d -in .circleci/github_token -k "${KEY}" -out ~/.git_credentials' + # We need ensure that the same default digest is used for encoding and decoding with + # openssl. Openssl versions might have different default digests which can cause + # decryption failures based on the installed openssl version. https://stackoverflow.com/a/39641378/4317734 + command: 'openssl aes-256-cbc -d -in .circleci/github_token -md md5 -k "${KEY}" -out ~/.git_credentials' - run: ./scripts/ci/publish-build-artifacts.sh aio_monitoring_stable: - <<: *job_defaults - docker: - # This job needs Chrome to be globally installed because the tests run with Protractor - # which does not load the browser through the Bazel webtesting rules. - - image: *browsers_docker_image + # This job needs Chrome to be globally installed because the tests run with Protractor + # which does not load the browser through the Bazel webtesting rules. + executor: browsers-executor steps: - - *attach_workspace - - *init_environment + - custom_attach_workspace + - init_environment - run: setPublicVar_CI_STABLE_BRANCH - run: - name: Check out `aio/` from the stable branch + name: Check out `aio/` and `third_party/github.com/yarnpkg/` from the stable branch command: | + localYarnDir=third_party/github.com/yarnpkg/ + # Remove the directory to ensure there will be only one version available (the one + # checked out from the stable branch below). + rm -rf $localYarnDir git fetch origin $CI_STABLE_BRANCH - git checkout --force origin/$CI_STABLE_BRANCH -- aio/ + git checkout --force origin/$CI_STABLE_BRANCH -- aio/ $localYarnDir + # Overwrite yarn again to use the version from the checked out branch. + - overwrite_yarn - run: name: Run tests against https://angular.io/ command: ./aio/scripts/test-production.sh https://angular.io/ $CI_AIO_MIN_PWA_SCORE - - run: - name: Notify caretaker about failure - # `$SLACK_CARETAKER_WEBHOOK_URL` is a secret env var defined in CircleCI project settings. - # The URL comes from https://angular-team.slack.com/apps/A0F7VRE7N-circleci. - command: 'curl --request POST --header "Content-Type: application/json" --data "{\"text\":\":x: \`$CIRCLE_JOB\` job failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}" $SLACK_CARETAKER_WEBHOOK_URL' - when: on_fail + - notify_webhook_on_fail: + webhook_url_env_var: SLACK_CARETAKER_WEBHOOK_URL + - notify_webhook_on_fail: + webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL aio_monitoring_next: - <<: *job_defaults - docker: - # This job needs Chrome to be globally installed because the tests run with Protractor - # which does not load the browser through the Bazel webtesting rules. - - image: *browsers_docker_image + # This job needs Chrome to be globally installed because the tests run with Protractor + # which does not load the browser through the Bazel webtesting rules. + executor: browsers-executor steps: - - *attach_workspace - - *init_environment + - custom_attach_workspace + - init_environment - run: name: Run tests against https://next.angular.io/ command: ./aio/scripts/test-production.sh https://next.angular.io/ $CI_AIO_MIN_PWA_SCORE - - run: - name: Notify caretaker about failure - # `$SLACK_CARETAKER_WEBHOOK_URL` is a secret env var defined in CircleCI project settings. - # The URL comes from https://angular-team.slack.com/apps/A0F7VRE7N-circleci. - command: 'curl --request POST --header "Content-Type: application/json" --data "{\"text\":\":x: \`$CIRCLE_JOB\` job failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}" $SLACK_CARETAKER_WEBHOOK_URL' - when: on_fail + - notify_webhook_on_fail: + webhook_url_env_var: SLACK_CARETAKER_WEBHOOK_URL + - notify_webhook_on_fail: + webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL legacy-unit-tests-saucelabs: - <<: *job_defaults - # In order to avoid the bottleneck of having a slow host machine, we acquire a better - # container for this job. This is necessary because we launch a lot of browsers concurrently - # and therefore the tunnel and Karma need to process a lot of file requests and tests. - resource_class: xlarge + executor: + name: default-executor + # In order to avoid the bottleneck of having a slow host machine, we acquire a better + # container for this job. This is necessary because we launch a lot of browsers concurrently + # and therefore the tunnel and Karma need to process a lot of file requests and tests. + resource_class: xlarge steps: - - *attach_workspace - - *init_environment + - custom_attach_workspace + - init_environment - run: name: Preparing environment for running tests on Saucelabs. command: | @@ -567,6 +717,7 @@ jobs: background: true - run: yarn tsc -p packages - run: yarn tsc -p modules + - run: yarn bazel build //packages/zone.js:npm_package # Waits for the Saucelabs tunnel to be ready. This ensures that we don't run tests # too early without Saucelabs not being ready. - run: ./scripts/saucelabs/wait-for-tunnel.sh @@ -574,96 +725,158 @@ jobs: - run: ./scripts/saucelabs/stop-tunnel.sh legacy-misc-tests: - <<: *job_defaults + executor: default-executor steps: - - *attach_workspace - - *init_environment + - custom_attach_workspace + - init_environment - run: yarn gulp check-cycle # TODO: disabled because the Bazel packages-dist does not seem to have map files for # the ESM5/ES2015 output. See: https://github.com/angular/angular/issues/27966 # - run: yarn gulp source-map-test - # Job to run unit tests from angular/material2. Needs a browser since all + # Job to run unit tests from angular/components. Needs a browser since all # component unit tests assume they're running in the browser environment. material-unit-tests: - <<: *job_defaults - resource_class: xlarge - docker: - - image: *browsers_docker_image - # The Material unit tests support splitting the browsers across multiple CircleCI - # instances. Since by default this job launches two browsers, we run each browser - # in its own container instance. - # https://github.com/angular/material2/blob/7baeaa797b19da2d2998f0d26f6fede3c8a13714/test/karma.conf.js#L107-L110 - parallelism: 2 - environment: - # The Material unit tests also support launching the same browser multiple times by - # sharding individual specs across the defined multiple instances. - # See: https://github.com/angular/material2/blob/7baeaa797b19da2d2998f0d26f6fede3c8a13714/test/karma.conf.js#L113-L116 - KARMA_PARALLEL_BROWSERS: 3 + executor: + name: browsers-executor + resource_class: xlarge steps: - - *attach_workspace - - *init_environment - - run: - name: "Cloning Material repository" - command: ./scripts/ci/clone_angular_material_repo.sh + - custom_attach_workspace + - init_environment + # Although RBE is configured below for the Material repo, also setup RBE in the Angular repo + # to provision Angular's GCP token into the environment variables. + - setup_bazel_rbe + # Restore the cache before cloning the repository because the clone script re-uses + # the restored repository if present. This reduces the amount of times the components + # repository needs to be cloned (this is slow and increases based on commits in the repo). - restore_cache: - # Material directory must be kept in sync with the `$MATERIAL_REPO_TMP_DIR` env variable. - # It needs to be hardcoded here, because env variables interpolation is not supported. keys: - - v2-angular-material-{{ checksum "/tmp/material2/yarn.lock" }} - - v2-angular-material- + - *material_unit_tests_cache_key + - *material_unit_tests_cache_key_fallback - run: + name: "Fetching Material repository" + command: ./scripts/ci/clone_angular_material_repo.sh + - run: + # Run yarn install to fetch the Bazel binaries as used in the Material repo. name: Installing Material dependencies. - command: yarn --cwd ${MATERIAL_REPO_TMP_DIR} install --frozen-lockfile --non-interactive - # Save the cache before we run the Material unit tests script. This is necessary - # because we don't want to cache the node modules which have been modified to contain - # the attached Ivy package output. + # TODO: remove this once the repo has been updated to use NodeJS v12 and Yarn 1.19.1. + # We temporarily ignore the "engines" because the Angular components repository has + # minimum dependency on NodeJS v12 and Yarn 1.19.1, but the framework repository uses + # older versions. + command: yarn --ignore-engines --cwd ${MATERIAL_REPO_TMP_DIR} install --frozen-lockfile --non-interactive - save_cache: - # Material directory must be kept in sync with the `$MATERIAL_REPO_TMP_DIR` env variable. - # It needs to be hardcoded here, because env variables interpolation is not supported. - key: v2-angular-material-{{ checksum "/tmp/material2/yarn.lock" }} + key: *material_unit_tests_cache_key paths: - - "/tmp/material2/node_modules" + # Material directory must be kept in sync with the `$MATERIAL_REPO_TMP_DIR` env variable. + # It needs to be hardcoded here, because env variables interpolation is not supported. + - "/tmp/material2" + - run: + name: "Setup Bazel RBE remote execution in Material repo" + command: | + ./.circleci/setup-rbe.sh "${MATERIAL_REPO_TMP_DIR}/.bazelrc.user" - run: name: "Running Material unit tests" command: ./scripts/ci/run_angular_material_unit_tests.sh + test_zonejs: + executor: + name: default-executor + resource_class: xlarge + steps: + - custom_attach_workspace + - init_environment + - setup_circleci_bazel_config + - setup_bazel_rbe + # Install + - run: yarn --cwd packages/zone.js install --frozen-lockfile --non-interactive + # Run zone.js tools tests + - run: yarn --cwd packages/zone.js promisetest + - run: yarn --cwd packages/zone.js promisefinallytest + - run: yarn bazel build //packages/zone.js:npm_package && + cp dist/bin/packages/zone.js/npm_package/dist/zone-mix.js ./packages/zone.js/test/extra/ && + cp dist/bin/packages/zone.js/npm_package/dist/zone-patch-electron.js ./packages/zone.js/test/extra/ && + yarn --cwd packages/zone.js electrontest + + # Windows jobs + # Docs: https://circleci.com/docs/2.0/hello-world-windows/ + test_win: + executor: windows-executor + steps: + - setup_win + - run: + # Ran into a command parsing problem where `-browser:chromium-local` was converted to + # `-browser: chromium-local` (a space was added) in https://circleci.com/gh/angular/angular/357511. + # Probably a powershell command parsing thing. There's no problem using a yarn script though. + command: yarn circleci-win-ve + no_output_timeout: 45m + # Save bazel repository cache to use on subsequent runs. + # We don't save node_modules because it's faster to use the linux workspace and reinstall. + - save_cache: + key: *cache_key_win + paths: + - "C:/Users/circleci/bazel_repository_cache" + + test_ivy_aot_win: + executor: windows-executor + steps: + - setup_win + - run: + command: yarn circleci-win-ivy + no_output_timeout: 45m + + workflows: version: 2 default_workflow: jobs: - - setup + - setup: + filters: + branches: + ignore: g3 - lint: requires: - - setup + - setup - test: requires: - - setup + - setup - test_ivy_aot: requires: - - setup + - setup - build-npm-packages: requires: - - setup + - setup - build-ivy-npm-packages: requires: - - setup - - test_aio: - requires: - - setup - - legacy-unit-tests-saucelabs: - requires: - - setup - - deploy_aio: - requires: - - test_aio + - setup - legacy-misc-tests: requires: - build-npm-packages + - legacy-unit-tests-saucelabs: + requires: + - setup + - saucelabs_ivy: + requires: + - test_ivy_aot + - saucelabs_view_engine: + # This job is currently a PoC and a subset of `legacy-unit-tests-saucelabs`. Running on + # master only to avoid wasting resources. + # TODO: Run this job on all branches (including PRs) as soon as it is not a PoC and + # we can remove the legacy saucelabs job. + <<: *only_on_master + requires: + - setup + - test_aio: + requires: + - setup + - deploy_aio: + requires: + - test_aio - test_aio_local: requires: - build-npm-packages - - test_aio_local_ivy: + - test_aio_local: + name: test_aio_local_viewengine + viewengine: true requires: - build-npm-packages - test_aio_tools: @@ -672,22 +885,25 @@ workflows: - test_docs_examples: requires: - build-npm-packages - - test_docs_examples_ivy: + - test_docs_examples: + name: test_docs_examples_ivy + ivy: true requires: - build-ivy-npm-packages - aio_preview: + # Only run on PR builds. (There can be no previews for non-PR builds.) + <<: *only_on_pull_requests requires: - setup - # Only run on PR builds. (There can be no previews for non-PR builds.) - filters: - branches: - only: /pull\/\d+/ - test_aio_preview: requires: - aio_preview - integration_test: requires: - build-npm-packages + - publish_packages_as_artifacts: + requires: + - build-npm-packages - publish_snapshot: # Note: no filters on this job because we want it to run for all upstream branches # We'd really like to filter out pull requests here, but not yet available: @@ -698,9 +914,10 @@ workflows: - test - test_ivy_aot - integration_test + - saucelabs_ivy # Only publish if `aio`/`docs` tests using the locally built Angular packages pass - test_aio_local - - test_aio_local_ivy + - test_aio_local_viewengine - test_docs_examples - test_docs_examples_ivy # Get the artifacts to publish from the build-packages-dist job @@ -711,23 +928,24 @@ workflows: - legacy-misc-tests - material-unit-tests: requires: - - build-ivy-npm-packages - - saucelabs_tests: - jobs: - - setup - - test_saucelabs_bazel: + - build-npm-packages + - test_zonejs: requires: - setup - triggers: - - schedule: - # Runs the Saucelabs legacy tests every hour. We still want to run Saucelabs - # frequently as the caretaker needs up-to-date results when merging PRs or creating - # a new release. Also we primarily moved the Saucelabs job into a cronjob that doesn't - # run for PRs, in order to ensure that PRs are not affected by Saucelabs flakiness or - # incidents. This is still guaranteed (even if we run the job every hour). - cron: "0 * * * *" - filters: *publish_branches_filter + # Windows Jobs + # These are very slow so we run them on non-PRs only for now. + # TODO: remove the filter when CircleCI makes Windows FS faster. + # The Windows jobs are only run after their non-windows counterparts finish successfully. + # This isn't strictly necessary as there is no artifact dependency, but helps economize + # CI resources by not attempting to build when we know should fail. + - test_win: + <<: *skip_on_pull_requests + requires: + - test + - test_ivy_aot_win: + <<: *skip_on_pull_requests + requires: + - test_ivy_aot aio_monitoring: jobs: @@ -740,15 +958,6 @@ workflows: - setup triggers: - schedule: + <<: *only_on_master # Runs AIO monitoring jobs at 10:00AM every day. cron: "0 10 * * *" - filters: - branches: - only: - - master - -# TODO: -# - don't build the g3 branch -# - verify that we are bootstrapping with the right yarn version coming from the docker image -# - check local chrome version pulled from docker image -# - remove /tools/ngcontainer diff --git a/.circleci/env.sh b/.circleci/env.sh index 4ebc6cdc8e..f9734fbfa5 100755 --- a/.circleci/env.sh +++ b/.circleci/env.sh @@ -3,7 +3,6 @@ # Variables readonly projectDir=$(realpath "$(dirname ${BASH_SOURCE[0]})/..") readonly envHelpersPath="$projectDir/.circleci/env-helpers.inc.sh"; -readonly getCommitRangePath="$projectDir/.circleci/get-commit-range.js"; # Load helpers and make them available everywhere (through `$BASH_ENV`). source $envHelpersPath; @@ -19,16 +18,20 @@ setPublicVar PROJECT_ROOT "$projectDir"; setPublicVar CI_AIO_MIN_PWA_SCORE "95"; # This is the branch being built; e.g. `pull/12345` for PR builds. setPublicVar CI_BRANCH "$CIRCLE_BRANCH"; +setPublicVar CI_BUILD_URL "$CIRCLE_BUILD_URL"; # ChromeDriver version compatible with the Chrome version included in the docker image used in # `.circleci/config.yml`. See http://chromedriver.chromium.org/downloads for a list of versions. # This variable is intended to be passed as an arg to the `webdriver-manager update` command (e.g. # `"postinstall": "webdriver-manager update $CI_CHROMEDRIVER_VERSION_ARG"`). -setPublicVar CI_CHROMEDRIVER_VERSION_ARG "--versions.chrome 2.45"; +setPublicVar CI_CHROMEDRIVER_VERSION_ARG "--versions.chrome 75.0.3770.90"; setPublicVar CI_COMMIT "$CIRCLE_SHA1"; -# `CI_COMMIT_RANGE` will only be available when `CIRCLE_COMPARE_URL` is also available (or can be -# retrieved via `get-compare-url.js`), i.e. on push builds (a.k.a. non-PR, non-scheduled builds and -# rerun workflows of such builds). That is fine, since we only need it in push builds. -setPublicVar CI_COMMIT_RANGE "`[[ ${CIRCLE_PR_NUMBER:-false} != false ]] && echo "" || node $getCommitRangePath "$CIRCLE_BUILD_NUM" "$CIRCLE_COMPARE_URL"`"; +# `CI_COMMIT_RANGE` is only used on push builds (a.k.a. non-PR, non-scheduled builds and rerun +# workflows of such builds). +# NOTE: With [CircleCI Pipelines](https://circleci.com/docs/2.0/build-processing) enabled, +# `CIRCLE_COMPARE_URL` is no longer available and the commit range cannot be reliably +# detected. Fall back to only considering the last commit (which is accurate in the majority +# of cases for push builds). +setPublicVar CI_COMMIT_RANGE "`[[ ${CIRCLE_PR_NUMBER:-false} != false ]] && echo "" || echo "$CIRCLE_SHA1~1...$CIRCLE_SHA1"`"; setPublicVar CI_PULL_REQUEST "${CIRCLE_PR_NUMBER:-false}"; setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME"; setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME"; @@ -51,20 +54,13 @@ setSecretVar CI_SECRET_PAYLOAD_FIREBASE_TOKEN "$ANGULAR_PAYLOAD_TOKEN"; #################################################################################################### # Define SauceLabs environment variables for CircleCI. #################################################################################################### -# In order to have a meaningful SauceLabs badge on the repo page, -# the angular2-ci account is used only when pushing commits to master; -# in all other cases, the regular angular-ci account is used. -if [ "${CI_PULL_REQUEST}" = "false" ] && [ "${CI_REPO_OWNER}" = "angular" ] && [ "${CI_BRANCH}" = "master" ]; then - setPublicVar SAUCE_USERNAME "angular2-ci"; - setSecretVar SAUCE_ACCESS_KEY "693ebc16208a-0b5b-1614-8d66-a2662f4e"; -else - setPublicVar SAUCE_USERNAME "angular-ci"; - setSecretVar SAUCE_ACCESS_KEY "9b988f434ff8-fbca-8aa4-4ae3-35442987"; -fi +setPublicVar SAUCE_USERNAME "angular-framework"; +setSecretVar SAUCE_ACCESS_KEY "0c731274ed5f-cbc9-16f4-021a-9835e39f"; +# TODO(josephperrott): Remove environment variables once all saucelabs tests are via bazel method. setPublicVar SAUCE_LOG_FILE /tmp/angular/sauce-connect.log setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock -setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX}" +setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-framework-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX}" # Amount of seconds we wait for sauceconnect to establish a tunnel instance. In order to not # acquire CircleCI instances for too long if sauceconnect failed, we need a connect timeout. setPublicVar SAUCE_READY_FILE_TIMEOUT 120 @@ -77,7 +73,9 @@ setPublicVar SAUCE_READY_FILE_TIMEOUT 120 # their separate build setups. setPublicVar MATERIAL_REPO_TMP_DIR "/tmp/material2" setPublicVar MATERIAL_REPO_URL "https://github.com/angular/material2.git" -setPublicVar MATERIAL_REPO_BRANCH "ivy-2019" +setPublicVar MATERIAL_REPO_BRANCH "master" +# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI "config.yml". +setPublicVar MATERIAL_REPO_COMMIT "c734deb14bb28579ba59e7e065a39e3c4ed54458" # Source `$BASH_ENV` to make the variables available immediately. source $BASH_ENV; diff --git a/.circleci/gcp_token b/.circleci/gcp_token index c77bcf6345..baf1b2b679 100644 Binary files a/.circleci/gcp_token and b/.circleci/gcp_token differ diff --git a/.circleci/get-commit-range.js b/.circleci/get-commit-range.js index 75477105e7..c5f569c6f6 100644 --- a/.circleci/get-commit-range.js +++ b/.circleci/get-commit-range.js @@ -6,9 +6,16 @@ * node get-commit-range [ []] * ``` * - * Returns the value of the `CIRCLE_COMPARE_URL` environment variable (if defined) or, if this is - * not a PR build (i.e. `CIRCLE_PR_NUMBER` is not defined), retrieves the equivalent of - * `CIRCLE_COMPARE_URL` for jobs that are part of a rerun workflow. + * Returns the commit range, either extracting it from `compare-url` (if defined), which is of the + * format of the `CIRCLE_COMPARE_URL` environment variable, or by retrieving the equivalent of + * `CIRCLE_COMPARE_URL` for jobs that are part of a rerun workflow and extracting it from there. + * + * > !!! WARNING !!! + * > !! + * > !! When [CircleCI Pipelines](https://circleci.com/docs/2.0/build-processing) is enabled, the + * > !! `CIRCLE_COMPARE_URL` environment variable is not available at all and this script does not + * > !! work. + * > !!!!!!!!!!!!!!! * * **Context:** * CircleCI sets the `CIRCLE_COMPARE_URL` environment variable (from which we can extract the commit @@ -21,7 +28,7 @@ * (undocumented) fact that the workspace ID happens to be the same as the workflow ID that first * created it. * - * For example, for a job on push build workflow, the CircleCI API will return data that look like: + * For example, for a job on push build workflows, the CircleCI API will return data that look like: * ```js * { * compare: 'THE_COMPARE_URL_WE_ARE_LOOKING_FOR', diff --git a/.circleci/get-vendored-yarn-path.js b/.circleci/get-vendored-yarn-path.js new file mode 100644 index 0000000000..da90083b26 --- /dev/null +++ b/.circleci/get-vendored-yarn-path.js @@ -0,0 +1,36 @@ +#!/usr/bin/env node +'use strict'; + +/** + * **Usage:** + * ``` + * node get-vendored-yarn-path + * ``` + * + * Returns the path to the vendored `yarn.js` script, so that it can be used for setting up yarn + * aliases/symlinks and use the local, vendored yarn script instead of a globally installed one. + * + * **Context:** + * We keep a version of yarn in the repo, at `third_party/github.com/yarnpkg/`. All CI jobs should + * use that version for consistency (and easier updates). The path to the actual `yarn.js` script, + * however, changes depending on the version (e.g. `third_party/github.com/yarnpkg/v1.21.1/...`). + * + * This script infers the correct path, so that we don't have to update the path in several places, + * when we update the version of yarn in `third_party/github.com/yarnpkg/`. + */ + +const {readdirSync} = require('fs'); +const {normalize} = require('path'); + +const yarnDownloadDir = `${__dirname}/../third_party/github.com/yarnpkg/yarn/releases/download`; +const yarnVersionSubdirs = readdirSync(yarnDownloadDir); + +// Based on our current process, there should be exactly one sub-directory inside +// `vendoredYarnDownloadDir` at all times. Throw, if that is not the case. +if (yarnVersionSubdirs.length !== 1) { + throw new Error( + `Expected exactly 1 yarn version in '${yarnDownloadDir}', but found ` + + `${yarnVersionSubdirs.length}: ${yarnVersionSubdirs.join(', ')}`); +} + +console.log(normalize(`${yarnDownloadDir}/${yarnVersionSubdirs[0]}/bin/yarn.js`)); diff --git a/.circleci/setup-rbe.sh b/.circleci/setup-rbe.sh new file mode 100755 index 0000000000..07bbc6bd5d --- /dev/null +++ b/.circleci/setup-rbe.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -u -e -o pipefail + +# The path of the .bazelrc.user file to update should be passed as first parameter to this script. +# This allows to setup RBE for both the Angular repo and the Material repo. +bazelrc_user="$1" + +echo "Writing RBE configuration to ${bazelrc_user}" + +touch ${bazelrc_user} +echo -e 'build --config=remote\n' >> ${bazelrc_user} +echo -e 'build:remote --remote_accept_cached=true\n' >> ${bazelrc_user} +echo "Reading from remote cache for bazel remote jobs." +if [[ "$CI_PULL_REQUEST" == "false" ]]; then + echo -e 'build:remote --remote_upload_local_results=true\n' >> ${bazelrc_user} + echo "Uploading local build results to remote cache." +else + echo -e 'build:remote --remote_upload_local_results=false\n' >> ${bazelrc_user} + echo "Not uploading local build results to remote cache." +fi diff --git a/.circleci/windows-env.ps1 b/.circleci/windows-env.ps1 new file mode 100644 index 0000000000..39008b37b4 --- /dev/null +++ b/.circleci/windows-env.ps1 @@ -0,0 +1,41 @@ +# Install Bazel pre-reqs on Windows +# https://docs.bazel.build/versions/master/install-windows.html +# https://docs.bazel.build/versions/master/windows.html +# Install MSYS2 and packages +choco install msys2 --version 20180531.0.0 --no-progress --package-parameters "/NoUpdate" +C:\tools\msys64\usr\bin\bash.exe -l -c "pacman --needed --noconfirm -S zip unzip patch diffutils git" + +# Add PATH modifications to the Powershell profile. This is the win equivalent of .bash_profile. +# https://docs.microsoft.com/en-us/previous-versions//bb613488(v=vs.85) +new-item -path $profile -itemtype file -force +# Paths for nodejs, npm, yarn, and msys2. Use single quotes to prevent interpolation. +# Add before the original path to use msys2 instead of the installed gitbash. +Add-Content $profile '$Env:path = "${Env:ProgramFiles}\nodejs\;C:\Users\circleci\AppData\Roaming\npm\;${Env:ProgramFiles(x86)}\Yarn\bin\;C:\Users\circleci\AppData\Local\Yarn\bin\;C:\tools\msys64\usr\bin\;" + $Env:path' +# Environment variables for Bazel +Add-Content $profile '$Env:BAZEL_SH = "C:\tools\msys64\usr\bin\bash.exe"' + +# Get the bazel version devdep and store it in a global var for use in the circleci job. +$bazelVersion = & ${Env:ProgramFiles}\nodejs\node.exe -e "console.log(require('./package.json').devDependencies['@bazel/bazel'])" +# This is a tricky situation: we want $bazelVersion to be evaluated but not $Env:BAZEL_VERSION. +# Formatting works https://stackoverflow.com/questions/32127583/expand-variable-inside-single-quotes +$bazelVersionGlobalVar = '$Env:BAZEL_VERSION = "{0}"' -f $bazelVersion +Add-Content $profile $bazelVersionGlobalVar + +# Remove the CircleCI checkout SSH override, because it breaks cloning repositories through Bazel. +# See https://circleci.com/gh/angular/angular/401454 for an example. +# TODO: is this really needed? Maybe there's a better way. It doesn't happen on Linux or on Codefresh. +git config --global --unset url.ssh://git@github.com.insteadOf + + +# These Bazel prereqs aren't needed because the CircleCI image already includes them. +# choco install nodejs --version 10.16.0 --no-progress +# choco install yarn --version 1.16.0 --no-progress +# choco install vcredist2015 --version 14.0.24215.20170201 + +# We don't need VS Build Tools for the tested bazel targets. +# If it's needed again, uncomment these lines. +# VS Build Tools are needed for Bazel C++ targets (like com_google_protobuf) +# choco install visualstudio2019buildtools --version 16.1.2.0 --no-progress --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.Component.VC.Runtime.UCRTSDK --add Microsoft.VisualStudio.Component.Windows10SDK.17763" +# Add-Content $profile '$Env:BAZEL_VC = "${Env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\BuildTools\VC\"' +# Python is needed for Bazel Python targets +# choco install python --version 3.5.1 --no-progress diff --git a/.circleci/windows-yarn-setup.ps1 b/.circleci/windows-yarn-setup.ps1 new file mode 100644 index 0000000000..b53c0b0007 --- /dev/null +++ b/.circleci/windows-yarn-setup.ps1 @@ -0,0 +1,14 @@ +# Use our local, vendored yarn in the global `yarn` command. +$globalYarnDir = "$HOME\AppData\Roaming\yarn" +$localYarnPath = & ${Env:ProgramFiles}\nodejs\node.exe ".\.circleci\get-vendored-yarn-path.js" + +# Create a directory to put the yarn PowerShell script. +New-Item -Path "$globalYarnDir" -ItemType "directory" >$null + +# Create the yarn PowerShell script (using the inferred path to the local yarn script). +Get-Content -Path ".\.circleci\windows-yarn.ps1.template" | + %{$_ -replace "{{ LOCAL_YARN_PATH_PLACEHOLDER }}", "$localYarnPath"} | + Add-Content -Path "$globalYarnDir\yarn.ps1" + +# Add the directory containing the yarn PowerShell script to `PATH`. +Add-Content -Path $profile -Value ('$Env:path = "{0};" + $Env:path' -f $globalYarnDir) diff --git a/.circleci/windows-yarn.ps1.template b/.circleci/windows-yarn.ps1.template new file mode 100644 index 0000000000..1d200352d7 --- /dev/null +++ b/.circleci/windows-yarn.ps1.template @@ -0,0 +1,15 @@ +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + & "$basedir/node$exe" "{{ LOCAL_YARN_PATH_PLACEHOLDER }}" $args + $ret=$LASTEXITCODE +} else { + & "node$exe" "{{ LOCAL_YARN_PATH_PLACEHOLDER }}" $args + $ret=$LASTEXITCODE +} +exit $ret diff --git a/.codefresh/Dockerfile.win-1809 b/.codefresh/Dockerfile.win-1809 deleted file mode 100644 index eff6e1771a..0000000000 --- a/.codefresh/Dockerfile.win-1809 +++ /dev/null @@ -1,120 +0,0 @@ -# escape=` - -ARG core=mcr.microsoft.com/windows/servercore:1809 -ARG target=mcr.microsoft.com/powershell:windowsservercore-1809 - -FROM $core as download - -ARG node_version=10.13.0 -ARG yarn_version=1.13.0 - -SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] - -ENV GPG_VERSION 2.3.4 - -RUN Invoke-WebRequest $('https://files.gpg4win.org/gpg4win-vanilla-{0}.exe' -f $env:GPG_VERSION) -OutFile 'gpg4win.exe' -UseBasicParsing ; ` - Start-Process .\gpg4win.exe -ArgumentList '/S' -NoNewWindow -Wait - -RUN @( ` - '94AE36675C464D64BAFA68DD7434390BDBE9B9C5', ` - 'FD3A5288F042B6850C66B31F09FE44734EB7990E', ` - '71DCFD284A79C3B38668286BC97EC7A07EDE3FC1', ` - 'DD8F2338BAE7501E3DD5AC78C273792F7D83545D', ` - 'C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8', ` - 'B9AE9905FFD7803F25714661B63B535A4C206CA9', ` - '77984A986EBC2AA786BC0F66B01FBB92821C587A', ` - '8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600', ` - '4ED778F539E3634C779C87C6D7062848A1AB005C', ` - 'A48C2BEE680E841632CD4E44F07496B3EB3C1762', ` - 'B9E2F5981AA6E0CD28160D9FF13993A75599653C' ` - ) | foreach { ` - gpg --keyserver ha.pool.sks-keyservers.net --recv-keys $_ ; ` - } - -ENV NODE_VERSION=$node_version - -RUN Invoke-WebRequest $('https://nodejs.org/dist/v{0}/SHASUMS256.txt.asc' -f $env:NODE_VERSION) -OutFile 'SHASUMS256.txt.asc' -UseBasicParsing ; ` - gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc - -RUN Invoke-WebRequest $('https://nodejs.org/dist/v{0}/node-v{0}-win-x64.zip' -f $env:NODE_VERSION) -OutFile 'node.zip' -UseBasicParsing ; ` - $sum = $(cat SHASUMS256.txt.asc | sls $(' node-v{0}-win-x64.zip' -f $env:NODE_VERSION)) -Split ' ' ; ` - if ((Get-FileHash node.zip -Algorithm sha256).Hash -ne $sum[0]) { Write-Error 'SHA256 mismatch' } ; ` - Expand-Archive node.zip -DestinationPath C:\ ; ` - Rename-Item -Path $('C:\node-v{0}-win-x64' -f $env:NODE_VERSION) -NewName 'C:\nodejs' - -ENV YARN_VERSION=$yarn_version - -RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ; ` - Invoke-WebRequest $('https://yarnpkg.com/downloads/{0}/yarn-{0}.msi' -f $env:YARN_VERSION) -OutFile yarn.msi -UseBasicParsing ; ` - $sig = Get-AuthenticodeSignature yarn.msi ; ` - if ($sig.Status -ne 'Valid') { Write-Error 'Authenticode signature is not valid' } ; ` - Write-Output $sig.SignerCertificate.Thumbprint ; ` - if (@( ` - '7E253367F8A102A91D04829E37F3410F14B68A5F', ` - 'AF764E1EA56C762617BDC757C8B0F3780A0CF5F9' ` - ) -notcontains $sig.SignerCertificate.Thumbprint) { Write-Error 'Unknown signer certificate' } ; ` - Start-Process msiexec.exe -ArgumentList '/i', 'yarn.msi', '/quiet', '/norestart' -NoNewWindow -Wait - -ENV GIT_VERSION 2.20.1 -ENV GIT_DOWNLOAD_URL https://github.com/git-for-windows/git/releases/download/v${GIT_VERSION}.windows.1/MinGit-${GIT_VERSION}-busybox-64-bit.zip -ENV GIT_SHA256 9817ab455d9cbd0b09d8664b4afbe4bbf78d18b556b3541d09238501a749486c - -RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ; ` - Invoke-WebRequest -UseBasicParsing $env:GIT_DOWNLOAD_URL -OutFile git.zip; ` - if ((Get-FileHash git.zip -Algorithm sha256).Hash -ne $env:GIT_SHA256) {exit 1} ; ` - Expand-Archive git.zip -DestinationPath C:\git; ` - Remove-Item git.zip - -FROM $target as baseimage - -ENV NPM_CONFIG_LOGLEVEL info - -COPY --from=download /nodejs /nodejs -COPY --from=download [ "/Program Files (x86)/yarn", "/yarn" ] -COPY --from=download /git /git - -ARG SETX=/M -RUN setx %SETX% PATH "%PATH%;C:\nodejs;C:\yarn\bin;C:\git\cmd;C:\git\mingw64\bin;C:\git\usr\bin" - -CMD [ "node.exe" ] - -FROM baseimage - -SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] - -RUN Invoke-WebRequest -UseBasicParsing 'https://www.7-zip.org/a/7z1805-x64.exe' -OutFile 7z.exe; ` - Start-Process -FilePath 'C:\\7z.exe' -ArgumentList '/S', '/D=C:\\7zip0' -NoNewWindow -Wait; ` - Invoke-WebRequest -UseBasicParsing 'http://repo.msys2.org/distrib/x86_64/msys2-base-x86_64-20180531.tar.xz' -OutFile msys2.tar.xz; ` - Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'e', 'msys2.tar.xz' -Wait; ` - Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'x', 'msys2.tar', '-oC:\\' -Wait; ` - Remove-Item msys2.tar.xz; ` - Remove-Item msys2.tar; ` - Remove-Item 7z.exe; ` - Remove-Item -Recurse 7zip; ` - [Environment]::SetEnvironmentVariable('Path', $env:Path + ';C:\msys64\usr\bin', [System.EnvironmentVariableTarget]::Machine); ` - [Environment]::SetEnvironmentVariable('BAZEL_SH', 'C:\msys64\usr\bin\bash.exe', [System.EnvironmentVariableTarget]::Machine) - -# Install VS Build Tools -RUN Invoke-WebRequest -UseBasicParsing https://download.visualstudio.microsoft.com/download/pr/df649173-11e9-4af2-8eb7-0eb02ba8958a/cadb5bdac41e55bb8f6a6b7c45273370/vs_buildtools.exe -OutFile vs_BuildTools.exe; ` - # Installer won't detect DOTNET_SKIP_FIRST_TIME_EXPERIENCE if ENV is used, must use setx /M - setx /M DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1; ` - Start-Process vs_BuildTools.exe ` - -ArgumentList ` - '--add', 'Microsoft.VisualStudio.Workload.VCTools', ` - '--add', 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', ` - '--add', 'Microsoft.Component.VC.Runtime.UCRTSDK', ` - '--add', 'Microsoft.VisualStudio.Component.Windows10SDK.17763', ` - '--quiet', '--norestart', '--nocache' ` - -NoNewWindow -Wait; ` - Remove-Item -Force vs_buildtools.exe; ` - Remove-Item -Force -Recurse \"${Env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\"; ` - Remove-Item -Force -Recurse ${Env:TEMP}\*; ` - Remove-Item -Force -Recurse \"${Env:ProgramData}\Package Cache\"; ` - [Environment]::SetEnvironmentVariable('BAZEL_VC', \"${Env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\BuildTools\VC\", [System.EnvironmentVariableTarget]::Machine) - -# Install Python -RUN Invoke-WebRequest -UseBasicParsing https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe -OutFile python-3.5.1.exe; ` - Start-Process python-3.5.1.exe -ArgumentList '/quiet InstallAllUsers=1 PrependPath=1' -Wait; ` - Remove-Item -Force python-3.5.1.exe - -CMD ["cmd.exe"] diff --git a/.codefresh/README.md b/.codefresh/README.md deleted file mode 100644 index 0f6ec57900..0000000000 --- a/.codefresh/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# CodeFresh configuration - -[![Codefresh build status](https://g.codefresh.io/api/badges/pipeline/angular/angular%2Fangular%2Fangular?type=cf-1)](https://g.codefresh.io/public/accounts/angular/pipelines/angular/angular/angular) - -This folder contains configuration for the [CodeFresh]() based CI checks for this repository. - -## The build pipeline - -CodeFresh uses a several pipeline for each repository. The `codefresh.yml` file defines pipeline [build steps](https://codefresh.io/docs/docs/configure-ci-cd-pipeline/introduction-to-codefresh-pipelines/) for this repository. - -Run results can be seen in the GitHub checks interface and in the [public pipeline](https://g.codefresh.io/public/accounts/angular/pipelines/angular/angular/angular) - -Although most configuration is done via `pipeline.yml`, some options are only available in the online [pipeline settings](https://g.codefresh.io/pipelines/angular/services?repoOwner=angular&repoName=angular&project=angular%2Fangular&context=github&serviceName=angular%2Fangular), which needs a login to access. - - -## Caretaker - -CodeFresh status can be found at . - -Issues related to the CodeFresh setup should be escalated to the Tools Team via the current caretaker, followed by Alex Eagle and Filipe Silva. - -## Rollout strategy - -Currently it is only used for tests on Windows platforms, on the master branch, and without pushing user-facing reports. It's only possible to see current builds in the [public pipeline dashboard](https://g.codefresh.io/public/accounts/angular/pipelines/angular/angular/angular). - -After a week or two of running like this, we should reassess how stable and reliable it is. - -Next steps include: -- building PRs -- showing build status publicly -- blocking PRs that break the build -- expanding the test suite - diff --git a/.codefresh/bazel.rc b/.codefresh/bazel.rc deleted file mode 100644 index 1dd9c1e81f..0000000000 --- a/.codefresh/bazel.rc +++ /dev/null @@ -1,38 +0,0 @@ -# These options are enabled when running on CI -# We do this by copying this file to /etc/bazel.bazelrc at the start of the build. -# See documentation in /docs/BAZEL.md - -# Save built files and 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 -# Setting the output_base to a Docker volume is currently broken because of a Docker bug on Windows: -# https://github.com/moby/moby/issues/37024 -# This affects Bazel because bazel_output_base\external\bazel_tools is an absolute path junction. -# When its fixed we can uncomment this line, and use a different output_base for Ivy tests (they -# use a separate compiler and destructively replace the cache). -# startup --output_base=C:/codefresh/volume/bazel_output_base - -# 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 - -# Print all the options that apply to the build. -# This helps us diagnose which options override others -# (e.g. /etc/bazel.bazelrc vs. tools/bazel.rc) -build --announce_rc - -# Workaround https://github.com/bazelbuild/bazel/issues/3645 -# Bazel doesn't calculate the memory ceiling correctly when running under Docker. -# Limit Bazel to consuming resources that fit in CodeFresh VMs -# TODO(filipesilva): determine the correct memory limit -build --local_resources=10240,8.0,1.0 - -# Retry in the event of flakes, eg. https://circleci.com/gh/angular/angular/31309 -test --flaky_test_attempts=2 - -# More details on failures -build --verbose_failures=true diff --git a/.codefresh/codefresh.yml b/.codefresh/codefresh.yml deleted file mode 100644 index 0c738e78ed..0000000000 --- a/.codefresh/codefresh.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: '1.0' - -steps: - BuildImage: - title: Build Docker image - type: build - image_name: node-bazel-windows - working_directory: ./.codefresh - no_cf_cache: true - build_arguments: - - node_version=10.13.0 - - yarn_version=1.13.0 - dockerfile: ./Dockerfile.win-1809 - - RunTests: - title: Run Bazel tests - image: ${{BuildImage}} - commands: - # Install dependencies - - yarn install --frozen-lockfile --non-interactive --network-timeout 100000 --no-progress - # Add Bazel CI config - - copy .codefresh\bazel.rc %ProgramData%\bazel.bazelrc - # Run tests - # At the moment 'browser:chromium-local' are broken in CI while locally they work - # VE - - yarn bazel test --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only,-browser:chromium-local //... - # Ivy - - yarn bazel test --define=compile=aot --build_tag_filters=-no-ivy-aot,-fixme-ivy-aot --test_tag_filters=-no-ivy-aot,-fixme-ivy-aot,-browser:chromium-local //... diff --git a/.devcontainer/README.md b/.devcontainer/README.md new file mode 100644 index 0000000000..79c5759fb1 --- /dev/null +++ b/.devcontainer/README.md @@ -0,0 +1,31 @@ +# VSCode Remote Development - Developing inside a Containers + +This folder contains configuration files that can be used to opt into working on this repository in a [Docker container](https://www.docker.com/resources/what-container) via [VSCode](https://code.visualstudio.com/)'s Remote Development feature (see below). + +Info on remote development and developing inside a container with VSCode: +- [VSCode: Remote Development](https://code.visualstudio.com/docs/remote/remote-overview) +- [VSCode: Developing inside a Container](https://code.visualstudio.com/docs/remote/containers) +- [VSCode: Remote Development FAQ](https://code.visualstudio.com/docs/remote/faq) + + +## Usage + +_Prerequisite: [Install Docker](https://docs.docker.com/install) on your local environment._ + +To get started, read and follow the instuctions in [Developing inside a Container](https://code.visualstudio.com/docs/remote/containers). The [.devcontainer/](.) directory contains pre-configured `devcontainer.json` and `Dockerfile` files, which you can use to set up remote development with a docker container. + +In a nutshell, you need to: +- Install the [Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension. +- Copy [recommended-Dockerfile](./recommended-Dockerfile) to `Dockerfile` (and optionally tweak to suit your needs). +- Copy [recommended-devcontainer.json](./recommended-devcontainer.json) to `devcontainer.json` (and optionally tweak to suit your needs). +- Open VSCode and bring up the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette). +- Type `Remote-Containers: Open Folder in Container` and choose your local clone of [angular/angular](https://github.com/angular/angular). + +The `.devcontainer/devcontainer.json` and `.devcontainer/Dockerfile` files are ignored by git, so you can have your own local versions. We may occasionally update the template files ([recommended-devcontainer.json](./recommended-devcontainer.json), [recommended-Dockerfile](./recommended-Dockerfile)), in which case you will need to manually update your local copies (if desired). + + +## Updating `recommended-devcontainer.json` and `recommended-Dockerfile` + +You can update and commit the recommended config files (which people use as basis for their local configs), if you find that something is broken, out-of-date or can be improved. + +Please, keep in mind that any changes you make will potentially be used by many people on different environments. Try to keep these config files cross-platform compatible and free of personal preferences. diff --git a/.devcontainer/recommended-Dockerfile b/.devcontainer/recommended-Dockerfile index a004714591..251fc54224 100644 --- a/.devcontainer/recommended-Dockerfile +++ b/.devcontainer/recommended-Dockerfile @@ -1,5 +1,6 @@ # Image metadata and config. -FROM circleci/node:10-browsers +FROM circleci/node:10-browsers # Ideally, the image version should be what we use on CI. + # See `executors > browsers-executor` in `.circleci/config.yml`. LABEL name="Angular dev environment" \ description="This image can be used to create a dev environment for building Angular." \ @@ -15,7 +16,8 @@ USER root # Configure `Node.js`/`npm` and install utilities. RUN npm config --global set user root -RUN npm install --global yarn@1.13.0 # This needs to be in sync with what we use on CI. +RUN npm install --global yarn@latest # Ideally, the version should be what we use on CI. + # See `commands > overwrite_yarn` in `.circleci/config.yml`. # Go! (And keep going.) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 730f816c81..4cfbb5f6a0 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -44,21 +44,20 @@ # alxhub - Alex Rickabaugh # AndrewKushnir - Andrew Kushnir # andrewseguin - Andrew Seguin -# benlesh - Ben Lesh -# brandonroberts - Brandon Roberts +# atscott - Andrew Scott # devversion - Paul Gschwendtner # filipesilva - Filipe Silva # gkalpak - George Kalpakas -# hansl - Hans Larsen # IgorMinar - Igor Minar -# jasonaden - Jason Aden -# jenniferfell - Jennifer Fell +# JiaLiPassion - Jia Li +# JoostK - Joost Koehoorn +# josephperrott - Joey Perrott +# kapunahelewong - Kapunahele Wong # kara - Kara Erickson # kyliau - Keen Yee Liau # matsko - Matias Niemelä # mgechev - Minko Gechev # mhevery - Misko Hevery -# ocombe - Olivier Combe # petebacondarwin - Pete Bacon Darwin # pkozlowski-opensource - Pawel Kozlowski # robwormald - Rob Wormald @@ -86,9 +85,9 @@ # (secret team to avoid review requests, it also doesn't inherit from @angular/framework because nested teams can't be secret) # # - IgorMinar +# - josephperrott # - kara # - mhevery -# - alexeagle # =========================================================== @@ -97,9 +96,8 @@ # Used for approving minor documentation-only changes that don't require engineering review. # (secret team to avoid review requests, it also doesn't inherit from @angular/framework because nested teams can't be secret) # -# - brandonroberts # - gkalpak -# - jenniferfell +# - kapunahelewong # - petebacondarwin @@ -124,10 +122,9 @@ # @angular/tools-cli # =========================================================== # -# - alexeagle # - filipesilva -# - hansl # - mgechev +# - vikerman # =========================================================== @@ -135,6 +132,9 @@ # =========================================================== # # - alxhub +# - AndrewKushnir +# - kara +# - JoostK # =========================================================== @@ -178,7 +178,7 @@ # @angular/fw-forms # =========================================================== # -# - kara +# - AndrewKushnir # =========================================================== @@ -200,7 +200,7 @@ # @angular/fw-router # =========================================================== # -# - jasonaden +# - atscott # =========================================================== @@ -218,7 +218,6 @@ # # - gkalpak # - petebacondarwin -# - jasonaden # =========================================================== @@ -234,7 +233,7 @@ # # - AndrewKushnir # - mhevery -# - ocombe +# - petebacondarwin # - vikerman @@ -246,6 +245,15 @@ # - mhevery +# =========================================================== +# @angular/fw-zones +# =========================================================== +# +# - JiaLiPassion +# - mhevery +# - vikerman + + # =========================================================== # @angular/tools-benchpress # =========================================================== @@ -257,8 +265,8 @@ # @angular/fw-integration # =========================================================== # -# - alexeagle # - IgorMinar +# - josephperrott # - mhevery @@ -266,7 +274,6 @@ # @angular/docs-infra # =========================================================== # -# - brandonroberts # - gkalpak # - IgorMinar # - petebacondarwin @@ -276,8 +283,6 @@ # @angular/fw-docs-intro # =========================================================== # -# - jenniferfell -# - brandonroberts # - IgorMinar # - stephenfluin @@ -286,16 +291,15 @@ # @angular/fw-docs-observables # =========================================================== # -# - benlesh -# - jasonaden +# - alxhub # =========================================================== # @angular/fw-docs-packaging # =========================================================== # -# - alexeagle # - IgorMinar +# - vikerman # =========================================================== @@ -303,10 +307,9 @@ # =========================================================== # # - alan-agius4 -# - alexeagle -# - hansl # - IgorMinar # - mgechev +# - vikerman # =========================================================== @@ -314,11 +317,9 @@ # =========================================================== # # - alan-agius4 -# - alexeagle -# - hansl # - IgorMinar # - mgechev - +# - vikerman # =========================================================== @@ -337,16 +338,23 @@ # =========================================================== -# @angular/fw-dev-infra +# @angular/dev-infra-framework # =========================================================== # -# - alexeagle # - devversion # - filipesilva # - gkalpak # - IgorMinar +# - josephperrott +# =========================================================== +# @angular/fw-size-tracking +# =========================================================== +# +# - IgorMinar +# - kara + @@ -372,6 +380,44 @@ +# ================================================ +# Build, CI & Dev-infra Owners +# ================================================ + +/* @angular/dev-infra-framework +/.buildkite/** @angular/dev-infra-framework +/.circleci/** @angular/dev-infra-framework +/.devcontainer/** @angular/dev-infra-framework +/.github/** @angular/dev-infra-framework +/.vscode/** @angular/dev-infra-framework +/docs/BAZEL.md @angular/dev-infra-framework +/packages/* @angular/dev-infra-framework +/packages/examples/test-utils/** @angular/dev-infra-framework +/packages/private/** @angular/dev-infra-framework +/scripts/** @angular/dev-infra-framework +/third_party/** @angular/dev-infra-framework +/tools/build/** @angular/dev-infra-framework +/tools/cjs-jasmine/** @angular/dev-infra-framework +/tools/gulp-tasks/** @angular/dev-infra-framework +/tools/ngcontainer/** @angular/dev-infra-framework +/tools/npm/** @angular/dev-infra-framework +/tools/npm_workspace/** @angular/dev-infra-framework +/tools/public_api_guard/** @angular/dev-infra-framework +/tools/rxjs/** @angular/dev-infra-framework +/tools/size-tracking/** @angular/dev-infra-framework +/tools/source-map-test/** @angular/dev-infra-framework +/tools/symbol-extractor/** @angular/dev-infra-framework +/tools/testing/** @angular/dev-infra-framework +/tools/ts-api-guardian/** @angular/dev-infra-framework +/tools/tslint/** @angular/dev-infra-framework +/tools/validate-commit-message/** @angular/dev-infra-framework +/tools/yarn/** @angular/dev-infra-framework +/tools/* @angular/dev-infra-framework +*.BAZEL @angular/dev-infra-framework +*.bzl @angular/dev-infra-framework + + + # ================================================ # @angular/animations # ================================================ @@ -398,6 +444,7 @@ # ================================================ /packages/bazel/** @angular/tools-bazel @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/guide/bazel.md @angular/tools-bazel @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes @@ -407,8 +454,12 @@ # ================================================ /packages/compiler/** @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/packages/examples/compiler/** @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /packages/compiler-cli/** @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/guide/angular-compiler-options.md @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/aot-compiler.md @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/guide/aot-metadata-errors.md @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/guide/template-typecheck.md @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes @@ -427,11 +478,11 @@ # ================================================ /packages/compiler-cli/src/ngtools/** @angular/tools-cli @angular/framework-global-approvers +/aio/content/guide/cli-builder.md @angular/tools-cli @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /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 - # ================================================ # @angular/core # @angular/common (except @angular/common/http) @@ -442,12 +493,18 @@ # ================================================ /packages/core/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/packages/examples/core/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /packages/common/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /packages/platform-browser/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/packages/examples/platform-browser/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /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 +/packages/docs/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes + +/aio/content/guide/accessibility.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/examples/accessibility/** @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 @@ -504,6 +561,8 @@ /aio/content/guide/hierarchical-dependency-injection.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/examples/hierarchical-dependency-injection/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/examples/providers-viewproviders/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/examples/resolution-modifiers/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/lazy-loading-ngmodules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/examples/lazy-loading-ngmodules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes @@ -533,6 +592,16 @@ /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 /aio/content/images/guide/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/examples/binding-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/examples/property-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/examples/attribute-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/examples/two-way-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/examples/built-in-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/images/guide/built-in-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/examples/template-reference-variables/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/examples/inputs-outputs/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/images/guide/inputs-outputs/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/examples/template-expression-operators/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/pipes.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/examples/pipes/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes @@ -566,6 +635,7 @@ /packages/common/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /packages/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/packages/examples/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/http.md @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/examples/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/images/guide/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes @@ -588,6 +658,7 @@ # ================================================ /packages/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/packages/examples/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/forms.md @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/examples/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/images/guide/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes @@ -631,6 +702,7 @@ # ================================================ /packages/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/packages/examples/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/router.md @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/examples/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/images/guide/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes @@ -642,6 +714,7 @@ # ================================================ /packages/service-worker/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/packages/examples/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 @@ -668,6 +741,7 @@ /aio/content/examples/upgrade-phonecat-2-hybrid/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/examples/upgrade-phonecat-3-final/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/upgrade-performance.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/guide/upgrade-setup.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/ajs-quick-reference.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/examples/ajs-quick-reference/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes @@ -701,11 +775,11 @@ testing/** @angular/fw-test /packages/compiler/src/i18n/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /packages/compiler/src/render3/view/i18n/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /packages/compiler-cli/src/extract_i18n.ts @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/packages/localize/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/i18n.md @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/examples/i18n/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes - # ================================================ # @angular security # ================================================ @@ -720,6 +794,13 @@ testing/** @angular/fw-test +# ================================================ +# zone.js +# ================================================ + +/packages/zone.js/** @angular/fw-zones @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes + + # ================================================ # benchpress # ================================================ @@ -749,7 +830,6 @@ testing/** @angular/fw-test /aio/tools/** @angular/docs-infra @angular/framework-global-approvers # Hidden docs -/aio/content/guide/change-log.md @angular/docs-infra @angular/framework-global-approvers /aio/content/guide/docs-style-guide.md @angular/docs-infra @angular/framework-global-approvers /aio/content/examples/docs-style-guide/** @angular/docs-infra @angular/framework-global-approvers /aio/content/images/guide/docs-style-guide/** @angular/docs-infra @angular/framework-global-approvers @@ -762,9 +842,8 @@ testing/** @angular/fw-test # Docs: getting started & tutorial # ================================================ -/aio/content/guide/quickstart.md @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes -/aio/content/examples/cli-quickstart/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes -/aio/content/images/guide/cli-quickstart/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/guide/setup-local.md @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/images/guide/setup-local/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/tutorial/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/images/guide/toh/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/examples/toh-pt0/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes @@ -776,8 +855,8 @@ testing/** @angular/fw-test /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 +/aio/content/start/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/images/guide/start/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes # ================================================ @@ -803,17 +882,25 @@ 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/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 /aio/content/images/guide/build/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/deployment.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/images/guide/deployment/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/file-structure.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/releases.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/updating.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/workspace-config.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/deprecations.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes - +/aio/content/guide/migration-renderer.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/guide/migration-undecorated-classes.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/guide/migration-dynamic-flag.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/guide/migration-injectable.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/guide/migration-localize.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/guide/migration-module-with-providers.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/guide/updating-to-version-9.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/guide/ivy-compatibility.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/guide/ivy-compatibility-examples.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes # ================================================ @@ -849,41 +936,6 @@ testing/** @angular/fw-test -# ================================================ -# Build & CI Owners -# ================================================ - -/* @angular/fw-dev-infra -/.buildkite/** @angular/fw-dev-infra -/.circleci/** @angular/fw-dev-infra -/.codefresh/** @angular/fw-dev-infra -/.devcontainer/** @angular/fw-dev-infra -/.github/** @angular/fw-dev-infra -/.vscode/** @angular/fw-dev-infra -/docs/BAZEL.md @angular/fw-dev-infra -/packages/* @angular/fw-dev-infra -/scripts/** @angular/fw-dev-infra -/third_party/** @angular/fw-dev-infra -/tools/build/** @angular/fw-dev-infra -/tools/cjs-jasmine/** @angular/fw-dev-infra -/tools/gulp-tasks/** @angular/fw-dev-infra -/tools/ngcontainer/** @angular/fw-dev-infra -/tools/npm/** @angular/fw-dev-infra -/tools/npm_workspace/** @angular/fw-dev-infra -/tools/public_api_guard/** @angular/fw-dev-infra -/tools/rxjs/** @angular/fw-dev-infra -/tools/source-map-test/** @angular/fw-dev-infra -/tools/symbol-extractor/** @angular/fw-dev-infra -/tools/testing/** @angular/fw-dev-infra -/tools/ts-api-guardian/** @angular/fw-dev-infra -/tools/tslint/** @angular/fw-dev-infra -/tools/validate-commit-message/** @angular/fw-dev-infra -/tools/yarn/** @angular/fw-dev-infra -/tools/* -*.bzl @angular/fw-dev-infra - - - # ================================================ # Material CI # ================================================ @@ -904,6 +956,22 @@ testing/** @angular/fw-test +# ================================================ +# Size tracking +# ================================================ + +/aio/scripts/_payload-limits.json @angular/fw-size-tracking +/integration/_payload-limits.json @angular/fw-size-tracking + + +# ================================================ +# Special cases +# ================================================ + +/aio/content/guide/static-query-migration.md @kara @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes + + + # ================================================ # CODEOWNERS Owners owners ... # ================================================ diff --git a/.github/ISSUE_TEMPLATE/7-angular-components.md b/.github/ISSUE_TEMPLATE/7-angular-components.md new file mode 100644 index 0000000000..181b418b55 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/7-angular-components.md @@ -0,0 +1,13 @@ +--- +name: "\U0001F48EAngular Components" +about: Issues and feature requests for Angular Components + +--- + +🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 + +Please file any Angular Components issues at: https://github.com/angular/components/issues/new + +For the time being, we keep Angular Components issues in a separate repository. + +🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 diff --git a/.github/ISSUE_TEMPLATE/7-angular-material.md b/.github/ISSUE_TEMPLATE/7-angular-material.md deleted file mode 100644 index b023135b0c..0000000000 --- a/.github/ISSUE_TEMPLATE/7-angular-material.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -name: "\U0001F48EAngular Material" -about: Issues and feature requests for Angular Material - ---- - -🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 - -Please file any Angular Material issues at: https://github.com/angular/material2/issues/new - -For the time being, we keep Angular Material issues in a separate repository. - -🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 diff --git a/.github/angular-robot.yml b/.github/angular-robot.yml index 9b2fb295db..1c69dcd509 100644 --- a/.github/angular-robot.yml +++ b/.github/angular-robot.yml @@ -52,6 +52,7 @@ merge: - "packages/elements/schematics/**" - "packages/examples/**" - "packages/language-service/**" + - "packages/localize/**" - "packages/private/**" - "packages/service-worker/**" - "**/.gitignore" @@ -61,10 +62,15 @@ merge: - "**/third_party/**" - "**/tsconfig-build.json" - "**/tsconfig.json" + - "**/rollup.config.js" - "**/BUILD.bazel" - "**/*.md" - "packages/**/integrationtest/**" - "packages/**/test/**" + - "packages/zone.js/*" + - "packages/zone.js/doc/**" + - "packages/zone.js/example/**" + - "packages/zone.js/scripts/**" # comment that will be added to a PR when there is a conflict, leave empty or set to false to disable mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges. diff --git a/.github/workflows/lock-closed.yml b/.github/workflows/lock-closed.yml new file mode 100644 index 0000000000..a8350d626d --- /dev/null +++ b/.github/workflows/lock-closed.yml @@ -0,0 +1,14 @@ +name: Lock closed inactive issues + +on: + schedule: + # Run at 16:00 every day + - cron: '0 16 * * *' + +jobs: + lock_closed: + runs-on: ubuntu-latest + steps: + - uses: angular/dev-infra/github-actions/lock-closed@66462f6 + with: + lock-bot-key: ${{ secrets.LOCK_BOT_PRIVATE_KEY }} diff --git a/.gitignore b/.gitignore index 68ebb8b13a..8b7a3f78e0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,22 +4,26 @@ /bazel-out /integration/bazel/bazel-* e2e_test.* +*.log node_modules -tools/gulp-tasks/cldr/cldr-data/ # Include when developing application packages. pubspec.lock .c9 .idea/ .devcontainer/* +!.devcontainer/README.md !.devcontainer/recommended-devcontainer.json !.devcontainer/recommended-Dockerfile .settings/ .vscode/launch.json .vscode/settings.json +.vscode/tasks.json *.swo modules/.settings modules/.vscode +.vimrc +.nvimrc # Don't check in secret files *secret.js @@ -37,3 +41,5 @@ yarn-error.log # User specific bazel settings .bazelrc.user +.notes.md +baseline.json diff --git a/.nvmrc b/.nvmrc index f9fb144f9a..db24ab967f 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -10.15.0 +10.13.0 diff --git a/.vscode/README.md b/.vscode/README.md index 25b5c495a7..8f43026628 100644 --- a/.vscode/README.md +++ b/.vscode/README.md @@ -1,23 +1,25 @@ # 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. +This folder contains opt-in [Workspace Settings](https://code.visualstudio.com/docs/getstarted/settings), [Tasks](https://code.visualstudio.com/docs/editor/tasks), [Launch Configurations](https://code.visualstudio.com/Docs/editor/debugging#_launch-configurations) 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: +To use the recommended configurations follow the steps below: -- install -- copy `.vscode/recommended-settings.json` to `.vscode/settings.json` +- install the recommneded extensions in `.vscode/extensions.json` +- copy (or link) `.vscode/recommended-settings.json` to `.vscode/settings.json` +- copy (or link) `.vscode/recommended-launch.json` to `.vscode/launch.json` +- copy (or link) `.vscode/recommended-tasks.json` to `.vscode/tasks.json` - restart the editor -If you already have your custom workspace settings you should instead manually merge the file content. +If you already have your custom workspace settings you should instead manually merge the file contents. 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` +## Editing `.vscode/recommended-*.json` files -If you wish to add extra configuration items please keep in mind any settings you add here will be used by many users. +If you wish to add extra configuration items please keep in mind any modifications you make 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. +Try to keep these settings/configuations to things that help facilitate the development process and avoid altering the user workflow whenever possible. diff --git a/.vscode/recommended-launch.json b/.vscode/recommended-launch.json new file mode 100644 index 0000000000..bafab6c732 --- /dev/null +++ b/.vscode/recommended-launch.json @@ -0,0 +1,85 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Attach to bazel test ... --config=debug", + "type": "node", + "request": "attach", + "port": 9229, + "address": "localhost", + "restart": false, + "sourceMaps": true, + "localRoot": "${workspaceRoot}", + "remoteRoot": "${workspaceRoot}", + "stopOnEntry": false, + "timeout": 600000, + }, + { + "name": "Attach to bazel test ... --config=debug (no source maps)", + "type": "node", + "request": "attach", + "port": 9229, + "address": "localhost", + "restart": false, + "sourceMaps": false, + "localRoot": "${workspaceRoot}", + "remoteRoot": "${workspaceRoot}", + "stopOnEntry": false, + "timeout": 600000, + }, + { + "name": "IVY:packages/core/test/acceptance", + "type": "node", + "request": "launch", + "program": "${workspaceFolder}/node_modules/.bin/bazel", + "args": [ + "test", + "--config=ivy", + "packages/core/test/acceptance", + "--config=debug" + ], + "port": 9229, + "address": "localhost", + "restart": true, + "sourceMaps": true, + "timeout": 600000, + }, + { + "name": "IVY:packages/core/test/render3", + "type": "node", + "request": "launch", + "program": "${workspaceFolder}/node_modules/.bin/bazel", + "args": [ + "test", + "--config=ivy", + "packages/core/test/render3", + "--config=debug" + ], + "port": 9229, + "address": "localhost", + "restart": true, + "sourceMaps": true, + "timeout": 600000, + }, + { + "name": "IVY:packages/core/test", + "type": "node", + "request": "launch", + "program": "${workspaceFolder}/node_modules/.bin/bazel", + "args": [ + "test", + "--config=ivy", + "packages/core/test", + "--config=debug" + ], + "port": 9229, + "address": "localhost", + "restart": true, + "sourceMaps": true, + "timeout": 600000, + }, + ] +} diff --git a/.vscode/recommended-tasks.json b/.vscode/recommended-tasks.json new file mode 100644 index 0000000000..b129145b3b --- /dev/null +++ b/.vscode/recommended-tasks.json @@ -0,0 +1,113 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "IVY:packages/core/test/...", + "type": "shell", + "command": "${workspaceFolder}/node_modules/.bin/bazel", + "args": [ + "test", + "--config=ivy", + "packages/core/test", + "packages/core/test/acceptance", + "packages/core/test/render3", + ], + "group": "test", + "presentation": { + "reveal": "always", + "panel": "dedicated", + }, + }, + { + "label": "VE:packages/core/test/...", + "type": "shell", + "command": "${workspaceFolder}/node_modules/.bin/bazel", + "args": [ + "test", + "packages/core/test", + "packages/core/test/acceptance", + "packages/core/test/render3", + ], + "group": "test", + "presentation": { + "reveal": "always", + "panel": "dedicated", + }, + }, + { + "label": "IVY:packages/core/test/acceptance", + "type": "shell", + "command": "${workspaceFolder}/node_modules/.bin/bazel", + "args": [ + "test", + "--config=ivy", + "packages/core/test/acceptance", + ], + "group": "test", + "presentation": { + "reveal": "always", + "panel": "dedicated", + }, + }, + { + "label": "VE:packages/core/test/acceptance", + "type": "shell", + "command": "${workspaceFolder}/node_modules/.bin/bazel", + "args": [ + "test", + "packages/core/test/acceptance", + ], + "group": "test", + "presentation": { + "reveal": "always", + "panel": "dedicated", + }, + }, + { + "label": "IVY:packages/core/test", + "type": "shell", + "command": "${workspaceFolder}/node_modules/.bin/bazel", + "args": [ + "test", + "--config=ivy", + "packages/core/test", + ], + "group": "test", + "presentation": { + "reveal": "always", + "panel": "dedicated", + }, + }, + { + "label": "VE:packages/core/test", + "type": "shell", + "command": "${workspaceFolder}/node_modules/.bin/bazel", + "args": [ + "test", + "packages/core/test", + ], + "group": "test", + "presentation": { + "reveal": "always", + "panel": "dedicated", + }, + }, + { + "label": "IVY:packages/core/test/render3", + "type": "shell", + "command": "${workspaceFolder}/node_modules/.bin/bazel", + "args": [ + "test", + "--config=ivy", + "packages/core/test/render3", + ], + "group": "test", + "presentation": { + "reveal": "always", + "panel": "dedicated", + }, + }, + ], +} diff --git a/BUILD.bazel b/BUILD.bazel index 58ce9abd32..23b7887cd0 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -18,15 +18,15 @@ filegroup( name = "web_test_bootstrap_scripts", # do not sort srcs = [ - "@npm//node_modules/core-js:client/core.js", - "@npm//node_modules/zone.js:dist/zone.js", - "@npm//node_modules/zone.js:dist/zone-testing.js", - "@npm//node_modules/zone.js:dist/task-tracking.js", + "@npm//:node_modules/core-js/client/core.js", + "//packages/zone.js/dist:zone.js", + "//packages/zone.js/dist:zone-testing.js", + "//packages/zone.js/dist:task-tracking.js", "//:test-events.js", "//:shims_for_IE.js", # Including systemjs because it defines `__eval`, which produces correct stack traces. - "@npm//node_modules/systemjs:dist/system.src.js", - "@npm//node_modules/reflect-metadata:Reflect.js", + "@npm//:node_modules/systemjs/dist/system.src.js", + "@npm//:node_modules/reflect-metadata/Reflect.js", ], ) @@ -35,29 +35,50 @@ filegroup( srcs = [ # We also declare the unminfied AngularJS files since these can be used for # local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts) - "@npm//node_modules/angular:angular.js", - "@npm//node_modules/angular:angular.min.js", - "@npm//node_modules/angular-1.5:angular.js", - "@npm//node_modules/angular-1.5:angular.min.js", - "@npm//node_modules/angular-1.6:angular.js", - "@npm//node_modules/angular-1.6:angular.min.js", - "@npm//node_modules/angular-mocks:angular-mocks.js", - "@npm//node_modules/angular-mocks-1.5:angular-mocks.js", - "@npm//node_modules/angular-mocks-1.6:angular-mocks.js", + "@npm//:node_modules/angular/angular.js", + "@npm//:node_modules/angular/angular.min.js", + "@npm//:node_modules/angular-1.5/angular.js", + "@npm//:node_modules/angular-1.5/angular.min.js", + "@npm//:node_modules/angular-1.6/angular.js", + "@npm//:node_modules/angular-1.6/angular.min.js", + "@npm//:node_modules/angular-mocks/angular-mocks.js", + "@npm//:node_modules/angular-mocks-1.5/angular-mocks.js", + "@npm//:node_modules/angular-mocks-1.6/angular-mocks.js", ], ) -# To run a karma_web_test target locally on SauceLabs: -# 1) have SAUCE_USERNAME, SAUCE_ACCESS_KEY (and optionally a SAUCE_TUNNEL_IDENTIFIER) set in your environment -# 2) open a sauce connection with `./scripts/saucelabs/start-tunnel.sh` -# NOTE: start-tunnel.sh uses `node_modules/sauce-connect` which is current linux specific: -# "sauce-connect": "https://saucelabs.com/downloads/sc-4.5.3-linux.tar.gz". -# On OSX or Windows you'll need to use the appropriate sauce-connect binary. -# 3) run target with `yarn bazel test --config=saucelabs ` -# NOTE: --config=saucelabs is required as it makes the SAUCE_XXX environment variables available to -# the action. See /.bazelrc. +# To run a karma_web_test target manually, run the "./scripts/saucelabs/run-bazel-via-tunnel.sh" +# script. Note: If you are on MacOS or Windows, you need to manually start the Saucelabs tunnel +# because the script only supports the linux Saucelabs tunnel binary. We combine all tests into +# a single "karma_web_test" target because running them as separate targets in parallel can result +# in to too many browsers being acquired at the same time. This will then result in tests being +# flaky. This target runs in CI with Saucelabs and Ivy. karma_web_test( - name = "test_web_all", + name = "saucelabs_unit_tests", + # Default timeout is moderate (5min). This causes the test to be terminated while + # Saucelabs browsers keep running. Ultimately resulting in failing tests and browsers + # unnecessarily being acquired. Our specified Saucelabs idle timeout is 10min, so we use + # Bazel's long timeout (15min). This ensures that Karma can shut down properly. + timeout = "long", + tags = [ + "local", + "manual", + "saucelabs", + ], + deps = [ + "//packages/core/test/acceptance:acceptance_lib", + ], +) + +karma_web_test( + # This target runs in CI with View Engine as a Saucelabs and Bazel proof-of-concept. It's a + # subset of the legacy saucelabs tests. + name = "saucelabs_unit_tests_poc", + # Default timeout is moderate (5min). This causes the test to be terminated while + # Saucelabs browsers keep running. Ultimately resulting in failing tests and browsers + # unnecessarily being acquired. Our specified Saucelabs idle timeout is 10min, so we use + # Bazel's long timeout (15min). This ensures that Karma can shut down properly. + timeout = "long", tags = [ "local", "manual", @@ -65,7 +86,7 @@ karma_web_test( ], deps = [ # We combine all tests into a single karma_web_test target - # as running them as seperate targets in parallel leads to too many + # as running them as separate targets in parallel leads to too many # browsers being acquired at once in SauceLabs and the tests flake out # TODO: this is an example subset of tests below, add all remaining angular tests "//packages/common/http/test:test_lib", @@ -74,6 +95,7 @@ karma_web_test( "//packages/core/test:test_lib", "//packages/forms/test:test_lib", "//packages/http/test:test_lib", + "//packages/zone.js/test:karma_jasmine_test_ci", # "//packages/router/test:test_lib", # //packages/router/test:test_lib fails with: # IE 11.0.0 (Windows 8.1.0.0) bootstrap should restore the scrolling position FAILED diff --git a/CHANGELOG.md b/CHANGELOG.md index d69d7162ed..097efad4be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,1356 @@ + +# [9.0.0-rc.8](https://github.com/angular/angular/compare/9.0.0-rc.7...9.0.0-rc.8) (2020-01-08) + + +### Bug Fixes + +* **common:** remove trailing whitespace for CurrencyPipe ([#34642](https://github.com/angular/angular/issues/34642)) ([c42b90b](https://github.com/angular/angular/commit/c42b90b)), closes [#34641](https://github.com/angular/angular/issues/34641) +* **ivy:** append `advance` instructions before `i18nExp` ([#34436](https://github.com/angular/angular/issues/34436)) ([ba4c31c](https://github.com/angular/angular/commit/ba4c31c)) +* **ivy:** correctly associate output bound events with directives ([#34479](https://github.com/angular/angular/issues/34479)) ([fde5067](https://github.com/angular/angular/commit/fde5067)) +* **ivy:** Ensure ngProjectAs marker name appears at even attribute index ([#34617](https://github.com/angular/angular/issues/34617)) ([4f3215d](https://github.com/angular/angular/commit/4f3215d)) +* **ivy:** skip field inheritance if InheritDefinitionFeature is present on parent def ([#34244](https://github.com/angular/angular/issues/34244)) ([22533fb](https://github.com/angular/angular/commit/22533fb)) +* **ivy:** TestBed not unwrapping imports array function when overriding provider ([#34629](https://github.com/angular/angular/issues/34629)) ([963ed71](https://github.com/angular/angular/commit/963ed71)), closes [#34623](https://github.com/angular/angular/issues/34623) +* **language-service:** completions after "let x of |" in ngFor ([#34473](https://github.com/angular/angular/issues/34473)) ([ca8b584](https://github.com/angular/angular/commit/ca8b584)) +* **language-service:** correctly parse expressions in an attribute ([#34517](https://github.com/angular/angular/issues/34517)) ([7a0d6e7](https://github.com/angular/angular/commit/7a0d6e7)) +* **language-service:** The pipe method should not include parentheses ([#34485](https://github.com/angular/angular/issues/34485)) ([2845596](https://github.com/angular/angular/commit/2845596)) +* **ngcc:** capture entry-point dependencies from typings as well as source ([#34494](https://github.com/angular/angular/issues/34494)) ([c692757](https://github.com/angular/angular/commit/c692757)), closes [#34411](https://github.com/angular/angular/issues/34411) +* **ngcc:** do not add trailing commas in UMD imports ([#34545](https://github.com/angular/angular/issues/34545)) ([e6850a3](https://github.com/angular/angular/commit/e6850a3)), closes [#34353](https://github.com/angular/angular/issues/34353) [#34525](https://github.com/angular/angular/issues/34525) + + +### Features + +* **compiler:** record end of expression Token ([#33549](https://github.com/angular/angular/issues/33549)) ([8a25cd4](https://github.com/angular/angular/commit/8a25cd4)), closes [#33477](https://github.com/angular/angular/issues/33477) +* **language-service:** Append symbol type to hover tooltip ([#34515](https://github.com/angular/angular/issues/34515)) ([381b895](https://github.com/angular/angular/commit/381b895)) +* **language-service:** Show documentation on hover ([#34506](https://github.com/angular/angular/issues/34506)) ([1660095](https://github.com/angular/angular/commit/1660095)) + + +### Performance Improvements + +* **ivy:** support simple generic type constraints in local type ctors ([#34021](https://github.com/angular/angular/issues/34021)) ([88adc30](https://github.com/angular/angular/commit/88adc30)) + + + + +# [9.0.0-rc.7](https://github.com/angular/angular/compare/9.0.0-rc.6...9.0.0-rc.7) (2019-12-18) + + +### Bug Fixes + +* **animations:** leaking detached nodes when parent has a leave transition ([#34409](https://github.com/angular/angular/issues/34409)) ([6607fb4](https://github.com/angular/angular/commit/6607fb4)), closes [#25744](https://github.com/angular/angular/issues/25744) +* **common:** ngStyle should ignore undefined values ([#34422](https://github.com/angular/angular/issues/34422)) ([ee1eebd](https://github.com/angular/angular/commit/ee1eebd)), closes [#34310](https://github.com/angular/angular/issues/34310) +* **ivy:** avoid duplicate errors in safe navigations and template guards ([#34417](https://github.com/angular/angular/issues/34417)) ([d6edeab](https://github.com/angular/angular/commit/d6edeab)) +* **ivy:** avoid using __proto__ when reading metadata in JIT mode ([#34305](https://github.com/angular/angular/issues/34305)) ([08ce026](https://github.com/angular/angular/commit/08ce026)) +* **ivy:** don't produce template diagnostics when scope is invalid ([#34460](https://github.com/angular/angular/issues/34460)) ([c1fd629](https://github.com/angular/angular/commit/c1fd629)), closes [#33849](https://github.com/angular/angular/issues/33849) +* **ivy:** generate a better error for template var writes ([#34339](https://github.com/angular/angular/issues/34339)) ([418d586](https://github.com/angular/angular/commit/418d586)), closes [#33674](https://github.com/angular/angular/issues/33674) +* **ivy:** i18n - remove `translate` function when clearing translations ([#34346](https://github.com/angular/angular/issues/34346)) ([1489e5e](https://github.com/angular/angular/commit/1489e5e)), closes [#32781](https://github.com/angular/angular/issues/32781) +* **ivy:** i18n instructions thrown off by sanitizer in IE11 ([#34305](https://github.com/angular/angular/issues/34305)) ([bed62b1](https://github.com/angular/angular/commit/bed62b1)) +* **ivy:** improve ExpressionChangedAfterChecked error ([#34381](https://github.com/angular/angular/issues/34381)) ([7ea3984](https://github.com/angular/angular/commit/7ea3984)) +* **ivy:** inconsistent attribute casing in DebugNode.attributes on IE ([#34305](https://github.com/angular/angular/issues/34305)) ([9bff8e7](https://github.com/angular/angular/commit/9bff8e7)) +* **ivy:** incorrect injectable name logged in warning message on IE ([#34305](https://github.com/angular/angular/issues/34305)) ([60d1d5e](https://github.com/angular/angular/commit/60d1d5e)) +* **ivy:** inheritance in JIT mode not working correctly on IE10 ([#34305](https://github.com/angular/angular/issues/34305)) ([65fb2fd](https://github.com/angular/angular/commit/65fb2fd)) +* **ivy:** inheriting injectable definition from undecorated class not working on IE10 in JIT mode ([#34305](https://github.com/angular/angular/issues/34305)) ([d83599d](https://github.com/angular/angular/commit/d83599d)) +* **ivy:** record correct absolute source span for ngForOf expressions ([#31813](https://github.com/angular/angular/issues/31813)) ([931cb5e](https://github.com/angular/angular/commit/931cb5e)) +* **ivy:** reorder provider type checks to align with VE ([#34433](https://github.com/angular/angular/issues/34433)) ([7916b1e](https://github.com/angular/angular/commit/7916b1e)) +* **ivy:** unknown property and element checks not working correctly in IE ([#34305](https://github.com/angular/angular/issues/34305)) ([0ff54f2](https://github.com/angular/angular/commit/0ff54f2)) +* **ivy:** validate the NgModule declarations field ([#34404](https://github.com/angular/angular/issues/34404)) ([03e236a](https://github.com/angular/angular/commit/03e236a)) +* **language-service:** HTML path should include last node before cursor ([#34440](https://github.com/angular/angular/issues/34440)) ([76e4870](https://github.com/angular/angular/commit/76e4870)) +* **language-service:** Proper completions for properties and events ([#34445](https://github.com/angular/angular/issues/34445)) ([4e41bf9](https://github.com/angular/angular/commit/4e41bf9)) +* **language-service:** Remove completions for let and of in ngFor ([#34434](https://github.com/angular/angular/issues/34434)) ([ab61480](https://github.com/angular/angular/commit/ab61480)) +* **ngcc:** correctly match aliased classes between src and dts files ([#34254](https://github.com/angular/angular/issues/34254)) ([4bffb6b](https://github.com/angular/angular/commit/4bffb6b)), closes [#33593](https://github.com/angular/angular/issues/33593) +* **ngcc:** handle CommonJS re-exports by reference ([#34254](https://github.com/angular/angular/issues/34254)) ([9ca5faa](https://github.com/angular/angular/commit/9ca5faa)) +* **ngcc:** handle imports in dts files when processing UMD ([#34356](https://github.com/angular/angular/issues/34356)) ([81c75cf](https://github.com/angular/angular/commit/81c75cf)) +* **ngcc:** handle UMD re-exports ([#34254](https://github.com/angular/angular/issues/34254)) ([84a7d8a](https://github.com/angular/angular/commit/84a7d8a)) +* **ngcc:** render UMD imports even if no prior imports ([#34353](https://github.com/angular/angular/issues/34353)) ([c26738d](https://github.com/angular/angular/commit/c26738d)), closes [#34138](https://github.com/angular/angular/issues/34138) +* **ngcc:** use the correct identifiers when updating typings files ([#34254](https://github.com/angular/angular/issues/34254)) ([c0c2ab3](https://github.com/angular/angular/commit/c0c2ab3)) + + +### Features + +* **forms:** expand NgModel disabled type to work with strict template type checking ([#34438](https://github.com/angular/angular/issues/34438)) ([b1d4c58](https://github.com/angular/angular/commit/b1d4c58)) +* **ivy:** error in ivy when inheriting a ctor from an undecorated base ([#34460](https://github.com/angular/angular/issues/34460)) ([f563c7c](https://github.com/angular/angular/commit/f563c7c)) +* **ivy:** throw compilation error when providing undecorated classes ([#34460](https://github.com/angular/angular/issues/34460)) ([0638e65](https://github.com/angular/angular/commit/0638e65)) + + +### Performance Improvements + +* **compiler:** optimize cloning cursors state ([#34332](https://github.com/angular/angular/issues/34332)) ([5d871b5](https://github.com/angular/angular/commit/5d871b5)) +* **compiler:** speed up i18n digest computations ([#34332](https://github.com/angular/angular/issues/34332)) ([adb0663](https://github.com/angular/angular/commit/adb0663)) +* **compiler:** use a shared interpolation regex ([#34332](https://github.com/angular/angular/issues/34332)) ([940e62b](https://github.com/angular/angular/commit/940e62b)) +* **ivy:** cache export scopes extracted from declaration files ([#34332](https://github.com/angular/angular/issues/34332)) ([eb9a8ac](https://github.com/angular/angular/commit/eb9a8ac)) +* **ivy:** eagerly parse the template twice during analysis ([#34334](https://github.com/angular/angular/issues/34334)) ([fb4a11a](https://github.com/angular/angular/commit/fb4a11a)) +* **ivy:** reuse prior analysis work during incremental builds ([#34288](https://github.com/angular/angular/issues/34288)) ([c387952](https://github.com/angular/angular/commit/c387952)) +* **ivy:** share instances of `DomElementSchemaRegistry` ([#34332](https://github.com/angular/angular/issues/34332)) ([ce94192](https://github.com/angular/angular/commit/ce94192)) +* **ivy:** use module resolution cache ([#34332](https://github.com/angular/angular/issues/34332)) ([82442c5](https://github.com/angular/angular/commit/82442c5)) + + + + + +# [9.0.0-rc.6](https://github.com/angular/angular/compare/9.0.0-rc.5...9.0.0-rc.6) (2019-12-11) + + +### Bug Fixes + +* **bazel:** improve performance of tsHost.writeFile() ([#34331](https://github.com/angular/angular/issues/34331)) ([d7c459a](https://github.com/angular/angular/commit/d7c459a)) +* **common:** update closure locales to include directionality data ([#34240](https://github.com/angular/angular/issues/34240)) ([a02bde7](https://github.com/angular/angular/commit/a02bde7)) +* **compiler:** ensure localized strings are ES5 compatible for JIT mode ([#34265](https://github.com/angular/angular/issues/34265)) ([26dba21](https://github.com/angular/angular/commit/26dba21)), closes [#34246](https://github.com/angular/angular/issues/34246) +* **compiler:** switch to modern diagnostic formatting ([#34234](https://github.com/angular/angular/issues/34234)) ([60051eb](https://github.com/angular/angular/commit/60051eb)) +* **compiler-cli:** allow declaration-only template type check members ([#34296](https://github.com/angular/angular/issues/34296)) ([bbb9412](https://github.com/angular/angular/commit/bbb9412)) +* **ivy:** add flag to skip non-exported classes ([#33921](https://github.com/angular/angular/issues/33921)) ([#34340](https://github.com/angular/angular/issues/34340)) ([7ed984b](https://github.com/angular/angular/commit/7ed984b)), closes [#33724](https://github.com/angular/angular/issues/33724) +* **ivy:** align TestBed.overrideProvider with what happens with providers in TestBed providers array ([#33769](https://github.com/angular/angular/issues/33769)) ([10a33ef](https://github.com/angular/angular/commit/10a33ef)) +* **ivy:** do not invoke change detection for destroyed views ([#34241](https://github.com/angular/angular/issues/34241)) ([24bbcaf](https://github.com/angular/angular/commit/24bbcaf)) +* **ivy:** handle SafeStyles in [style.prop] correctly ([#34286](https://github.com/angular/angular/issues/34286)) ([b0d5784](https://github.com/angular/angular/commit/b0d5784)), closes [/github.com/angular/angular/blob/master/packages/core/src/render3/styling/bindings.ts#L620](https://github.com//github.com/angular/angular/blob/master/packages/core/src/render3/styling/bindings.ts/issues/L620) +* **ivy:** inherit static coercion members from base classes ([#34296](https://github.com/angular/angular/issues/34296)) ([edfaab6](https://github.com/angular/angular/commit/edfaab6)), closes [#33830](https://github.com/angular/angular/issues/33830) +* **ivy:** properly parenthesize ternary expressions when emitted ([#34221](https://github.com/angular/angular/issues/34221)) ([af36bc6](https://github.com/angular/angular/commit/af36bc6)), closes [#34087](https://github.com/angular/angular/issues/34087) +* **ivy:** throw a better error when DI can't inject a ctor param ([#33739](https://github.com/angular/angular/issues/33739)) ([#34340](https://github.com/angular/angular/issues/34340)) ([676aca1](https://github.com/angular/angular/commit/676aca1)), closes [#33637](https://github.com/angular/angular/issues/33637) +* **language-service:** bug of accessing a string index signature using dot notation ([#34177](https://github.com/angular/angular/issues/34177)) ([72a5a8c](https://github.com/angular/angular/commit/72a5a8c)) +* **language-service:** Remove getExternalFiles() ([#34260](https://github.com/angular/angular/issues/34260)) ([0e911f8](https://github.com/angular/angular/commit/0e911f8)) +* **language-service:** return the js primitive type name ([#34177](https://github.com/angular/angular/issues/34177)) ([b4680a6](https://github.com/angular/angular/commit/b4680a6)) +* **language-service:** Simplify resolution logic in banner ([#34262](https://github.com/angular/angular/issues/34262)) ([7dfd327](https://github.com/angular/angular/commit/7dfd327)) +* **ngcc:** ensure that bundle `rootDir` is the package path ([#34212](https://github.com/angular/angular/issues/34212)) ([69dd516](https://github.com/angular/angular/commit/69dd516)) +* **ngcc:** fix undecorated child migration when `exportAs` is present ([#34014](https://github.com/angular/angular/issues/34014)) ([24d1f9e](https://github.com/angular/angular/commit/24d1f9e)) +* **ngcc:** log Angular error codes correctly ([#34014](https://github.com/angular/angular/issues/34014)) ([3cd43c1](https://github.com/angular/angular/commit/3cd43c1)) +* **ngcc:** report diagnostics from migrations ([#34014](https://github.com/angular/angular/issues/34014)) ([599dcd0](https://github.com/angular/angular/commit/599dcd0)) + + +### Performance Improvements + +* **ivy:** chain listener instructions ([#33720](https://github.com/angular/angular/issues/33720)) ([#34340](https://github.com/angular/angular/issues/34340)) ([d3ec306](https://github.com/angular/angular/commit/d3ec306)) +* **ivy:** chain styling instructions ([#33837](https://github.com/angular/angular/issues/33837)) ([#34340](https://github.com/angular/angular/issues/34340)) ([c66fd06](https://github.com/angular/angular/commit/c66fd06)) + + + + +# [9.0.0-rc.5](https://github.com/angular/angular/compare/9.0.0-rc.4...9.0.0-rc.5) (2019-12-04) + + +### Bug Fixes + +* **bazel:** don't rely on [@angular](https://github.com/angular)/core being as a depedency to install [@angular](https://github.com/angular)/bazel ([#34181](https://github.com/angular/angular/issues/34181)) ([716fc84](https://github.com/angular/angular/commit/716fc84)), closes [#34164](https://github.com/angular/angular/issues/34164) +* **bazel:** reenable template type checking in ng_module ([#34144](https://github.com/angular/angular/issues/34144)) ([572e731](https://github.com/angular/angular/commit/572e731)), closes [/github.com/angular/angular/blob/168abc6d6f52713383411b14980e104c99bfeef5/packages/compiler-cli/src/ngtsc/program.ts#L430-L434](https://github.com//github.com/angular/angular/blob/168abc6d6f52713383411b14980e104c99bfeef5/packages/compiler-cli/src/ngtsc/program.ts/issues/L430-L434) +* **common:** reflect input type in NgForOf context ([#33997](https://github.com/angular/angular/issues/33997)) ([b640d38](https://github.com/angular/angular/commit/b640d38)) +* **common:** reflect input type in NgIf context ([#33997](https://github.com/angular/angular/issues/33997)) ([7504543](https://github.com/angular/angular/commit/7504543)), closes [#31556](https://github.com/angular/angular/issues/31556) +* **compiler:** i18n - trim whitespace from i18n custom ids ([#34154](https://github.com/angular/angular/issues/34154)) ([64317c6](https://github.com/angular/angular/commit/64317c6)), closes [#34147](https://github.com/angular/angular/issues/34147) +* **compiler-cli:** ensure that `ngI18nClosureMode` is guarded in generated code ([#34211](https://github.com/angular/angular/issues/34211)) ([4d02556](https://github.com/angular/angular/commit/4d02556)) +* **core:** ensure that `ngI18nClosureMode` is guarded ([#34211](https://github.com/angular/angular/issues/34211)) ([2546261](https://github.com/angular/angular/commit/2546261)) +* **ivy:** allow insertion of views attached to a different container ([#34156](https://github.com/angular/angular/issues/34156)) ([65cd811](https://github.com/angular/angular/commit/65cd811)), closes [#34152](https://github.com/angular/angular/issues/34152) +* **ivy:** consistenly return -1 from ViewContainerRef.indexOf for non-inserted view ([#34156](https://github.com/angular/angular/issues/34156)) ([0044c66](https://github.com/angular/angular/commit/0044c66)) +* **ivy:** correctly support `ngProjectAs` on templates ([#34200](https://github.com/angular/angular/issues/34200)) ([41ea3c2](https://github.com/angular/angular/commit/41ea3c2)) +* **ivy:** i18n - correctly parse XLIFF placeholders ([#34155](https://github.com/angular/angular/issues/34155)) ([d5a48b2](https://github.com/angular/angular/commit/d5a48b2)), closes [#34151](https://github.com/angular/angular/issues/34151) +* **ivy:** i18n - trim whitespace when parsing metadata ([#34154](https://github.com/angular/angular/issues/34154)) ([f4d714c](https://github.com/angular/angular/commit/f4d714c)) +* **ivy:** incorrectly validating html foreign objects inside svg ([#34178](https://github.com/angular/angular/issues/34178)) ([4836fe0](https://github.com/angular/angular/commit/4836fe0)), closes [#34171](https://github.com/angular/angular/issues/34171) +* **ivy:** support ICUs with pipes ([#34198](https://github.com/angular/angular/issues/34198)) ([eae541b](https://github.com/angular/angular/commit/eae541b)) +* **language-service:** determine correct type for ngFor exported values ([#34089](https://github.com/angular/angular/issues/34089)) ([12e4aa0](https://github.com/angular/angular/commit/12e4aa0)) +* **language-service:** Do not produce diagnostics if metadata for NgModule not found ([#34113](https://github.com/angular/angular/issues/34113)) ([29de8d3](https://github.com/angular/angular/commit/29de8d3)) +* implement Symbol.specics of Promise ([#34162](https://github.com/angular/angular/issues/34162)) ([1bab8c2](https://github.com/angular/angular/commit/1bab8c2)), closes [#34105](https://github.com/angular/angular/issues/34105) [#33989](https://github.com/angular/angular/issues/33989) +* **language-service:** Insert parentheses for method completion ([#33860](https://github.com/angular/angular/issues/33860)) ([fb22f18](https://github.com/angular/angular/commit/fb22f18)) +* **language-service:** Make missing module suggestion instead of error ([#34115](https://github.com/angular/angular/issues/34115)) ([#34193](https://github.com/angular/angular/issues/34193)) ([d2538ca](https://github.com/angular/angular/commit/d2538ca)) +* **language-service:** use host.error() instead of console.error() ([#34114](https://github.com/angular/angular/issues/34114)) ([7a7e999](https://github.com/angular/angular/commit/7a7e999)) +* **ngcc:** render legacy i18n message ids by default ([#34135](https://github.com/angular/angular/issues/34135)) ([93ac362](https://github.com/angular/angular/commit/93ac362)), closes [#34056](https://github.com/angular/angular/issues/34056) + + +### Performance Improvements + +* add js-web-frameworks benchmark ([#34034](https://github.com/angular/angular/issues/34034)) ([bf16b0e](https://github.com/angular/angular/commit/bf16b0e)) +* **ivy:** avoid duplicate state lookup and default function parameters ([#34183](https://github.com/angular/angular/issues/34183)) ([00f7372](https://github.com/angular/angular/commit/00f7372)) + + + + +# [9.0.0-rc.4](https://github.com/angular/angular/compare/9.0.0-rc.3...9.0.0-rc.4) (2019-11-27) + + +### Bug Fixes + +* **bazel:** ng_module should not emit shim files under bazel and Ivy ([#33765](https://github.com/angular/angular/issues/33765)) ([e24ed8d](https://github.com/angular/angular/commit/e24ed8d)) +* **bazel:** update to tsickle 0.37.1 to fix peerDep warnings ([#33788](https://github.com/angular/angular/issues/33788)) ([719ca1d](https://github.com/angular/angular/commit/719ca1d)) +* **core:** allow css custom variables/properties in the style sanitizer ([#33841](https://github.com/angular/angular/issues/33841)) ([61cc7a3](https://github.com/angular/angular/commit/61cc7a3)), closes [#23485](https://github.com/angular/angular/issues/23485) [#23485](https://github.com/angular/angular/issues/23485) +* **core:** remove deprecated and defunct wtf* apis ([#33949](https://github.com/angular/angular/issues/33949)) ([cf42019](https://github.com/angular/angular/commit/cf42019)) +* **ivy:** avoid infinite recursion when evaluation source files ([#33772](https://github.com/angular/angular/issues/33772)) ([b12fde4](https://github.com/angular/angular/commit/b12fde4)), closes [#33734](https://github.com/angular/angular/issues/33734) +* **ivy:** avoid using stale cache in TestBed if module overrides are defined ([#33787](https://github.com/angular/angular/issues/33787)) ([fbd2133](https://github.com/angular/angular/commit/fbd2133)) +* **ivy:** handle non-standard input/output names in template type checking ([#33741](https://github.com/angular/angular/issues/33741)) ([94257ac](https://github.com/angular/angular/commit/94257ac)), closes [#33590](https://github.com/angular/angular/issues/33590) +* **ivy:** i18n - ensure that escaped chars are handled in localized strings ([#34065](https://github.com/angular/angular/issues/34065)) ([00f8d6a](https://github.com/angular/angular/commit/00f8d6a)) +* **ivy:** prevent unknown element check for AOT-compiled components ([#34024](https://github.com/angular/angular/issues/34024)) ([955a312](https://github.com/angular/angular/commit/955a312)) +* **ivy:** remove TNodeType assertion from `directiveInject` instruction ([#33948](https://github.com/angular/angular/issues/33948)) ([90a9043](https://github.com/angular/angular/commit/90a9043)) +* **ivy:** reset style property using ngStyle fix ([#33920](https://github.com/angular/angular/issues/33920)) ([b8ba6b0](https://github.com/angular/angular/commit/b8ba6b0)) +* **ivy:** run pre-order hooks in injection order ([#34026](https://github.com/angular/angular/issues/34026)) ([ebe3229](https://github.com/angular/angular/commit/ebe3229)), closes [#32522](https://github.com/angular/angular/issues/32522) +* **ivy:** support ICUs without "other" cases ([#34042](https://github.com/angular/angular/issues/34042)) ([781003f](https://github.com/angular/angular/commit/781003f)) +* **ivy:** support inserting a `viewRef` that is already present ([#34052](https://github.com/angular/angular/issues/34052)) ([978b500](https://github.com/angular/angular/commit/978b500)), closes [#33924](https://github.com/angular/angular/issues/33924) +* **ivy:** take styles extracted from template into account in JIT mode ([#34017](https://github.com/angular/angular/issues/34017)) ([b659aa3](https://github.com/angular/angular/commit/b659aa3)) +* **ivy:** track changes across failed builds ([#33971](https://github.com/angular/angular/issues/33971)) ([1ffbde1](https://github.com/angular/angular/commit/1ffbde1)), closes [#32214](https://github.com/angular/angular/issues/32214) +* **ivy:** wrap functions from "providers" in parentheses in Closure mode ([#33609](https://github.com/angular/angular/issues/33609)) ([fc6ad19](https://github.com/angular/angular/commit/fc6ad19)), closes [/github.com/angular/tsickle/blob/d7974262571c8a17d684e5ba07680e1b1993afdd/src/jsdoc_transformer.ts#L1021](https://github.com//github.com/angular/tsickle/blob/d7974262571c8a17d684e5ba07680e1b1993afdd/src/jsdoc_transformer.ts/issues/L1021) +* **language-service:** determine index types accessed using dot notation ([#33884](https://github.com/angular/angular/issues/33884)) ([e8ec296](https://github.com/angular/angular/commit/e8ec296)), closes [#29811](https://github.com/angular/angular/issues/29811) [#29811](https://github.com/angular/angular/issues/29811) +* **language-service:** fix error of array-index out of bounds exception ([#33928](https://github.com/angular/angular/issues/33928)) ([b05ce85](https://github.com/angular/angular/commit/b05ce85)) +* **language-service:** function.bind() should not be an error ([#34041](https://github.com/angular/angular/issues/34041)) ([#34046](https://github.com/angular/angular/issues/34046)) ([d22f3d6](https://github.com/angular/angular/commit/d22f3d6)) +* **ngcc:** do not crash on packages that specify typings as an array ([#33973](https://github.com/angular/angular/issues/33973)) ([e456e58](https://github.com/angular/angular/commit/e456e58)), closes [#33646](https://github.com/angular/angular/issues/33646) +* **ngcc:** do not output duplicate ɵprov properties ([#34085](https://github.com/angular/angular/issues/34085)) ([5a8d25d](https://github.com/angular/angular/commit/5a8d25d)) +* **ngcc:** render localized strings when in ES5 format ([#33857](https://github.com/angular/angular/issues/33857)) ([c6695fa](https://github.com/angular/angular/commit/c6695fa)) +* **ngcc:** render UMD global imports correctly ([#34012](https://github.com/angular/angular/issues/34012)) ([83989b8](https://github.com/angular/angular/commit/83989b8)) +* **ngcc:** report errors from `analyze` and `resolve` processing ([#33964](https://github.com/angular/angular/issues/33964)) ([ca5d772](https://github.com/angular/angular/commit/ca5d772)), closes [/github.com/angular/angular/issues/33685#issuecomment-557091719](https://github.com//github.com/angular/angular/issues/33685/issues/issuecomment-557091719) +* **router:** make routerLinkActive work with query params which contain arrays ([#22666](https://github.com/angular/angular/issues/22666)) ([f1bf5b2](https://github.com/angular/angular/commit/f1bf5b2)), closes [#22223](https://github.com/angular/angular/issues/22223) +* **service-worker:** allow creating post api requests after cache failure ([#33930](https://github.com/angular/angular/issues/33930)) ([63c9123](https://github.com/angular/angular/commit/63c9123)), closes [#33793](https://github.com/angular/angular/issues/33793) +* **service-worker:** throw when using the unsupported `versionedFiles` option in config ([#33903](https://github.com/angular/angular/issues/33903)) ([250e6fd](https://github.com/angular/angular/commit/250e6fd)) + + +### Features + +* **language-service:** completions support for indexed types ([#34047](https://github.com/angular/angular/issues/34047)) ([8a565c8](https://github.com/angular/angular/commit/8a565c8)), closes [angular/vscode-ng-language-service#110](https://github.com/angular/vscode-ng-language-service/issues/110) [angular/vscode-ng-language-service#277](https://github.com/angular/vscode-ng-language-service/issues/277) +* **language-service:** completions support for tuple array ([#33928](https://github.com/angular/angular/issues/33928)) ([7faa9bb](https://github.com/angular/angular/commit/7faa9bb)) + + +### Performance Improvements + +* **ivy:** do no work if moving a `viewRef` to the same position ([#34052](https://github.com/angular/angular/issues/34052)) ([d228801](https://github.com/angular/angular/commit/d228801)) +* **ivy:** fix creation time micro-benchmarks ([#34031](https://github.com/angular/angular/issues/34031)) ([457ac3a](https://github.com/angular/angular/commit/457ac3a)) +* **ivy:** R3TestBed - Do not process NgModuleDefs that have already been processed ([#33863](https://github.com/angular/angular/issues/33863)) ([05a18cc](https://github.com/angular/angular/commit/05a18cc)) + + + +# [9.0.0-rc.3](https://github.com/angular/angular/compare/9.0.0-rc.2...9.0.0-rc.3) (2019-11-20) + + +### Bug Fixes + +* **bazel:** add terser as an optional peer dependency ([#33891](https://github.com/angular/angular/issues/33891)) ([2d7b015](https://github.com/angular/angular/commit/2d7b015)) +* **compiler-cli:** Refactor getTsTypeFromBuiltinType ([#33778](https://github.com/angular/angular/issues/33778)) ([09480d3](https://github.com/angular/angular/commit/09480d3)) +* **core:** make QueryList implement Iterable in the type system ([#33536](https://github.com/angular/angular/issues/33536)) ([49571bf](https://github.com/angular/angular/commit/49571bf)), closes [#29842](https://github.com/angular/angular/issues/29842) +* **ivy:** always re-analyze the program during incremental rebuilds ([#33862](https://github.com/angular/angular/issues/33862)) ([30ddadc](https://github.com/angular/angular/commit/30ddadc)), closes [#32388](https://github.com/angular/angular/issues/32388) +* **ivy:** avoid cyclical dependency in imports ([#33831](https://github.com/angular/angular/issues/33831)) ([a61fb76](https://github.com/angular/angular/commit/a61fb76)) +* **ivy:** constant object literals shared across element and component instances ([#33705](https://github.com/angular/angular/issues/33705)) ([93ba4c2](https://github.com/angular/angular/commit/93ba4c2)) +* **ivy:** don't infer template context types when in full mode ([#33537](https://github.com/angular/angular/issues/33537)) ([595375f](https://github.com/angular/angular/commit/595375f)), closes [#33527](https://github.com/angular/angular/issues/33527) +* **ivy:** emit fs-relative paths when rootDir(s) aren't in effect ([#33828](https://github.com/angular/angular/issues/33828)) ([14156bd](https://github.com/angular/angular/commit/14156bd)), closes [#33659](https://github.com/angular/angular/issues/33659) [#33562](https://github.com/angular/angular/issues/33562) +* **ivy:** ExpressionChangedAfterItHasBeenCheckedError for SafeValue ([#33749](https://github.com/angular/angular/issues/33749)) ([cba6b7d](https://github.com/angular/angular/commit/cba6b7d)), closes [#33448](https://github.com/angular/angular/issues/33448) +* **ivy:** extend assertion in `directiveInject` function to support IcuContainers ([#33832](https://github.com/angular/angular/issues/33832)) ([8452458](https://github.com/angular/angular/commit/8452458)) +* **ivy:** i18n - ensure that colons in i18n metadata are not rendered ([#33820](https://github.com/angular/angular/issues/33820)) ([bc28ca7](https://github.com/angular/angular/commit/bc28ca7)) +* **ivy:** i18n - support "\", "`" and "${" sequences in i18n messages ([#33820](https://github.com/angular/angular/issues/33820)) ([b53a1ac](https://github.com/angular/angular/commit/b53a1ac)) +* **ivy:** move setClassMetadata calls into a pure iife ([#33337](https://github.com/angular/angular/issues/33337)) ([213e3c3](https://github.com/angular/angular/commit/213e3c3)) +* **ivy:** properly insert views before ng-container with injected ViewContainerRef ([#33853](https://github.com/angular/angular/issues/33853)) ([c7a3694](https://github.com/angular/angular/commit/c7a3694)) +* **ivy:** properly insert views into ViewContainerRef injected by querying ([#33816](https://github.com/angular/angular/issues/33816)) ([f136dda](https://github.com/angular/angular/commit/f136dda)) +* **ivy:** report watch mode diagnostics correctly ([#33862](https://github.com/angular/angular/issues/33862)) ([d92da13](https://github.com/angular/angular/commit/d92da13)), closes [#32213](https://github.com/angular/angular/issues/32213) +* **ivy:** reset style property value defined using [style.prop.px] ([#33780](https://github.com/angular/angular/issues/33780)) ([de8cf75](https://github.com/angular/angular/commit/de8cf75)) +* **ivy:** retain JIT metadata unless JIT mode is explicitly disabled ([#33671](https://github.com/angular/angular/issues/33671)) ([5267c92](https://github.com/angular/angular/commit/5267c92)) +* **ivy:** shadow all DOM properties in `DebugElement.properties` ([#33781](https://github.com/angular/angular/issues/33781)) ([5be23a3](https://github.com/angular/angular/commit/5be23a3)), closes [#33695](https://github.com/angular/angular/issues/33695) +* **ivy:** support for #id bootstrap selectors ([#33784](https://github.com/angular/angular/issues/33784)) ([9761ebe](https://github.com/angular/angular/commit/9761ebe)), closes [#33485](https://github.com/angular/angular/issues/33485) +* **language-service:** Function alias should be callable ([#33782](https://github.com/angular/angular/issues/33782)) ([ca63353](https://github.com/angular/angular/commit/ca63353)) +* **language-service:** Provide completions for attribute values ([#33839](https://github.com/angular/angular/issues/33839)) ([0e20453](https://github.com/angular/angular/commit/0e20453)) +* **language-service:** Recompute analyzed modules only when source files change ([#33806](https://github.com/angular/angular/issues/33806)) ([9882a82](https://github.com/angular/angular/commit/9882a82)) +* **language-service:** Remove getTemplateReferences() from LanguageService API ([#33807](https://github.com/angular/angular/issues/33807)) ([0688a28](https://github.com/angular/angular/commit/0688a28)) +* **ngcc:** always add exports for `ModuleWithProviders` references ([#33875](https://github.com/angular/angular/issues/33875)) ([f3d8f6a](https://github.com/angular/angular/commit/f3d8f6a)), closes [#33701](https://github.com/angular/angular/issues/33701) +* **ngcc:** correctly associate decorators with aliased classes ([#33878](https://github.com/angular/angular/issues/33878)) ([59a4b76](https://github.com/angular/angular/commit/59a4b76)) +* **ngcc:** correctly include internal .d.ts files ([#33875](https://github.com/angular/angular/issues/33875)) ([0854dc8](https://github.com/angular/angular/commit/0854dc8)) +* **ngcc:** do not emit ES2015 code in ES5 files ([#33514](https://github.com/angular/angular/issues/33514)) ([06e36e5](https://github.com/angular/angular/commit/06e36e5)), closes [#32665](https://github.com/angular/angular/issues/32665) +* **ngcc:** generate correct metadata for classes with getter/setter properties ([#33514](https://github.com/angular/angular/issues/33514)) ([21bd8c9](https://github.com/angular/angular/commit/21bd8c9)), closes [#30569](https://github.com/angular/angular/issues/30569) +* **ngcc:** properly detect origin of constructor param types ([#33901](https://github.com/angular/angular/issues/33901)) ([05d5c4f](https://github.com/angular/angular/commit/05d5c4f)), closes [#33677](https://github.com/angular/angular/issues/33677) +* **router:** make routerLinkActive work with query params which contain arrays ([#22666](https://github.com/angular/angular/issues/22666)) ([8e5ed20](https://github.com/angular/angular/commit/8e5ed20)), closes [#22223](https://github.com/angular/angular/issues/22223) +* **zone.js:** fixes typo of zone.js patch vrdisplaydisconnected property ([#33581](https://github.com/angular/angular/issues/33581)) ([1b7aa05](https://github.com/angular/angular/commit/1b7aa05)), closes [#33579](https://github.com/angular/angular/issues/33579) + + +### Features + +* **bazel:** update ng-add to use bazel v1.1.0 ([#33813](https://github.com/angular/angular/issues/33813)) ([b1d0a4f](https://github.com/angular/angular/commit/b1d0a4f)) +* **core:** missing-injectable migration should migrate empty object literal providers ([#33709](https://github.com/angular/angular/issues/33709)) ([b7c012f](https://github.com/angular/angular/commit/b7c012f)) + + +### Performance Improvements + +* **ivy:** add micro-benchmark focused on directive input update ([#33798](https://github.com/angular/angular/issues/33798)) ([edd624b](https://github.com/angular/angular/commit/edd624b)) +* **ivy:** don't store public input names in two places ([#33798](https://github.com/angular/angular/issues/33798)) ([105616c](https://github.com/angular/angular/commit/105616c)) +* **ivy:** extract template's instruction first create pass processing ([#33856](https://github.com/angular/angular/issues/33856)) ([01af94c](https://github.com/angular/angular/commit/01af94c)) +* **ivy:** Improve performance of transplanted views ([#33702](https://github.com/angular/angular/issues/33702)) ([a16a57e](https://github.com/angular/angular/commit/a16a57e)) + + + + +# [9.0.0-rc.2](https://github.com/angular/angular/compare/9.0.0-rc.1...9.0.0-rc.2) (2019-11-13) + + +### Bug Fixes + +* **common:** rerun cldr to remove � characters ([#33699](https://github.com/angular/angular/issues/33699)) ([011ecdf](https://github.com/angular/angular/commit/011ecdf)) +* **common:** update CLDR generated files after change to npm sources ([#33634](https://github.com/angular/angular/issues/33634)) ([59b25da](https://github.com/angular/angular/commit/59b25da)) +* **common:** update CLDR generated files to 36.0.0 ([#33584](https://github.com/angular/angular/issues/33584)) ([c1bd3bc](https://github.com/angular/angular/commit/c1bd3bc)) +* **compiler:** correctly parse attributes with a dot in the name ([#32256](https://github.com/angular/angular/issues/32256)) ([687582f](https://github.com/angular/angular/commit/687582f)) +* **compiler-cli:** Fix typo $implict ([#33633](https://github.com/angular/angular/issues/33633)) ([7bccef5](https://github.com/angular/angular/commit/7bccef5)) +* **compiler-cli:** Pass SourceFile to getFullText() ([#33660](https://github.com/angular/angular/issues/33660)) ([33f6cd4](https://github.com/angular/angular/commit/33f6cd4)) +* **core:** remove ngcc postinstall migration ([#33727](https://github.com/angular/angular/issues/33727)) ([508bbfd](https://github.com/angular/angular/commit/508bbfd)) +* **core:** support `ngInjectableDef` on types with inherited `ɵprov` ([#33732](https://github.com/angular/angular/issues/33732)) ([4ec079f](https://github.com/angular/angular/commit/4ec079f)) +* **ivy:** auto register NgModules with ID ([#33663](https://github.com/angular/angular/issues/33663)) ([4988094](https://github.com/angular/angular/commit/4988094)) +* **ivy:** better support for i18n attributes on s ([#33599](https://github.com/angular/angular/issues/33599)) ([2046202](https://github.com/angular/angular/commit/2046202)) +* **ivy:** ComponentFactory.create should clear host element content ([#33487](https://github.com/angular/angular/issues/33487)) ([d67a38b](https://github.com/angular/angular/commit/d67a38b)) +* **ivy:** ensure module scope is rebuilt on dependent change ([#33522](https://github.com/angular/angular/issues/33522)) ([71238a9](https://github.com/angular/angular/commit/71238a9)), closes [#32416](https://github.com/angular/angular/issues/32416) +* **ivy:** ensure that the correct `document` is available ([#33712](https://github.com/angular/angular/issues/33712)) ([8362696](https://github.com/angular/angular/commit/8362696)), closes [#33651](https://github.com/angular/angular/issues/33651) +* **ivy:** Handle overrides for {providedIn: AModule} in R3TestBed ([#33606](https://github.com/angular/angular/issues/33606)) ([d09ad82](https://github.com/angular/angular/commit/d09ad82)) +* **ivy:** match directives on namespaced elements ([#33555](https://github.com/angular/angular/issues/33555)) ([99ead47](https://github.com/angular/angular/commit/99ead47)), closes [#32061](https://github.com/angular/angular/issues/32061) +* **ivy:** properly determine the first native node of a view ([#33627](https://github.com/angular/angular/issues/33627)) ([811275c](https://github.com/angular/angular/commit/811275c)) +* **ivy:** properly insert views in front of empty views ([#33647](https://github.com/angular/angular/issues/33647)) ([c5737f4](https://github.com/angular/angular/commit/c5737f4)) +* **ivy:** properly insert views in front of views with an empty element container ([#33647](https://github.com/angular/angular/issues/33647)) ([0b99884](https://github.com/angular/angular/commit/0b99884)) +* **ivy:** provider override via TestBed should remove old providers from the list ([#33706](https://github.com/angular/angular/issues/33706)) ([f45d5dc](https://github.com/angular/angular/commit/f45d5dc)) +* **ivy:** recompile component when template changes in ngc watch mode ([#33551](https://github.com/angular/angular/issues/33551)) ([da01dbc](https://github.com/angular/angular/commit/da01dbc)), closes [#32869](https://github.com/angular/angular/issues/32869) +* **ivy:** recompile component when template changes in ngc watch mode ([#33551](https://github.com/angular/angular/issues/33551)) ([cd8333c](https://github.com/angular/angular/commit/cd8333c)), closes [#32869](https://github.com/angular/angular/issues/32869) +* **ivy:** Run ChangeDetection on transplanted views ([#33644](https://github.com/angular/angular/issues/33644)) ([37ae45e](https://github.com/angular/angular/commit/37ae45e)), closes [#33393](https://github.com/angular/angular/issues/33393) +* **language-service:** Resolve template variable in nested ngFor ([#33676](https://github.com/angular/angular/issues/33676)) ([6615743](https://github.com/angular/angular/commit/6615743)) +* **ngcc:** add default config for `ng2-dragula` ([#33797](https://github.com/angular/angular/issues/33797)) ([ecf38d4](https://github.com/angular/angular/commit/ecf38d4)), closes [#33718](https://github.com/angular/angular/issues/33718) +* **ngcc:** add reexports only once ([#33658](https://github.com/angular/angular/issues/33658)) ([83b635c](https://github.com/angular/angular/commit/83b635c)) +* **ngcc:** ensure that adjacent statements go after helper calls ([#33689](https://github.com/angular/angular/issues/33689)) ([c540061](https://github.com/angular/angular/commit/c540061)) +* generate the new locale files ([#33682](https://github.com/angular/angular/issues/33682)) ([72796b9](https://github.com/angular/angular/commit/72796b9)) +* resolve event listeners not correct when registered outside of ngZone ([#33711](https://github.com/angular/angular/issues/33711)) ([9045e3e](https://github.com/angular/angular/commit/9045e3e)), closes [#33687](https://github.com/angular/angular/issues/33687) +* use full cldr data to support all locales ([#33682](https://github.com/angular/angular/issues/33682)) ([ea83125](https://github.com/angular/angular/commit/ea83125)), closes [#33681](https://github.com/angular/angular/issues/33681) +* **ngcc:** remove `__decorator` calls even when part of the IIFE return statement ([#33777](https://github.com/angular/angular/issues/33777)) ([e1df98b](https://github.com/angular/angular/commit/e1df98b)) +* **ngcc:** support minified ES5 scenarios ([#33777](https://github.com/angular/angular/issues/33777)) ([49e517d](https://github.com/angular/angular/commit/49e517d)) + + +### Performance Improvements + +* **core:** Avoid unnecessary creating provider factory ([#33742](https://github.com/angular/angular/issues/33742)) ([c315881](https://github.com/angular/angular/commit/c315881)) + + +### Reverts + +* "fix(ivy): recompile component when template changes in ngc watch mode ([#33551](https://github.com/angular/angular/issues/33551))" ([#33661](https://github.com/angular/angular/issues/33661)) ([cb55f60](https://github.com/angular/angular/commit/cb55f60)) +* fix(ivy): Only restore registered modules if user compiles modules with TestBed ([#32944](https://github.com/angular/angular/issues/32944)) ([#33663](https://github.com/angular/angular/issues/33663)) ([f8e9c1e](https://github.com/angular/angular/commit/f8e9c1e)) +* fix(ivy): R3TestBed should clean up registered modules after each test ([#32872](https://github.com/angular/angular/issues/32872)) ([#33663](https://github.com/angular/angular/issues/33663)) ([7c4366d](https://github.com/angular/angular/commit/7c4366d)) + +### BREAKING CHANGES + +* **i18n:** The CLDR data has been updated to v36.0.0, which may cause some localized data strings to change. For example, the space separator used in numbers in the `fr` locales changed from `\xa0` to `\u202f` ([c1bd3bc](https://github.com/angular/angular/commit/c1bd3bc)) + + + +## [8.2.14](https://github.com/angular/angular/compare/8.2.13...8.2.14) (2019-11-13) + + +### Bug Fixes + +* **bazel:** exclude [@angular](https://github.com/angular)/cli from metadata build ([b43ae44](https://github.com/angular/angular/commit/b43ae44)), closes [#33502](https://github.com/angular/angular/issues/33502) +* **service-worker:** ensure initialization before handling messages ([#32525](https://github.com/angular/angular/issues/32525)) ([2840670](https://github.com/angular/angular/commit/2840670)), closes [#25611](https://github.com/angular/angular/issues/25611) + + + + + +# [9.0.0-rc.1](https://github.com/angular/angular/compare/9.0.0-rc.0...9.0.0-rc.1) (2019-11-06) + + +### Bug Fixes + +* **compiler-cli:** attach the correct `viaModule` to namespace imports ([#33495](https://github.com/angular/angular/issues/33495)) ([1d141a8](https://github.com/angular/angular/commit/1d141a8)), closes [#32166](https://github.com/angular/angular/issues/32166) +* **compiler-cli:** Pass SourceFile to getLeadingTriviaWidth ([#33588](https://github.com/angular/angular/issues/33588)) ([4b62ba9](https://github.com/angular/angular/commit/4b62ba9)) +* **compiler-cli:** remove unused CLI private exports ([#33242](https://github.com/angular/angular/issues/33242)) ([fc8eeca](https://github.com/angular/angular/commit/fc8eeca)) +* **core:** renderer-to-renderer2 migration not migrating methods ([#33571](https://github.com/angular/angular/issues/33571)) ([d751ca7](https://github.com/angular/angular/commit/d751ca7)) +* **core:** undecorated-classes-with-di migration should report config errors ([#33567](https://github.com/angular/angular/issues/33567)) ([c0ad47a](https://github.com/angular/angular/commit/c0ad47a)) +* **ivy:** avoid implicit any errors in event handlers ([#33550](https://github.com/angular/angular/issues/33550)) ([e2d7b25](https://github.com/angular/angular/commit/e2d7b25)), closes [#33528](https://github.com/angular/angular/issues/33528) +* **ivy:** don't crash on an unknown localref target ([#33454](https://github.com/angular/angular/issues/33454)) ([9db59d0](https://github.com/angular/angular/commit/9db59d0)) +* **ivy:** don't crash on unknown pipe ([#33454](https://github.com/angular/angular/issues/33454)) ([38758d8](https://github.com/angular/angular/commit/38758d8)) +* **ivy:** more descriptive errors for nested i18n sections ([#33583](https://github.com/angular/angular/issues/33583)) ([d9a3892](https://github.com/angular/angular/commit/d9a3892)) +* **language-service:** Should not crash if expr ends unexpectedly ([#33524](https://github.com/angular/angular/issues/33524)) ([9ebac71](https://github.com/angular/angular/commit/9ebac71)) +* **ngcc:** handle new `__spreadArrays` tslib helper ([#33617](https://github.com/angular/angular/issues/33617)) ([d749dd3](https://github.com/angular/angular/commit/d749dd3)), closes [#33614](https://github.com/angular/angular/issues/33614) +* **ngcc:** override `getInternalNameOfClass()` and `getAdjacentNameOfClass()` for ES5 ([#33533](https://github.com/angular/angular/issues/33533)) ([93a23b9](https://github.com/angular/angular/commit/93a23b9)) +* **ngcc:** render adjacent statements after static properties ([#33630](https://github.com/angular/angular/issues/33630)) ([fe12d0d](https://github.com/angular/angular/commit/fe12d0d)), closes [/github.com/angular/angular/pull/33337#issuecomment-545487737](https://github.com//github.com/angular/angular/pull/33337/issues/issuecomment-545487737) +* **ngcc:** render new definitions using the inner name of the class ([#33533](https://github.com/angular/angular/issues/33533)) ([85298e3](https://github.com/angular/angular/commit/85298e3)) +* **service-worker:** ensure initialization before handling messages ([#32525](https://github.com/angular/angular/issues/32525)) ([72eba77](https://github.com/angular/angular/commit/72eba77)), closes [#25611](https://github.com/angular/angular/issues/25611) + + +### Features + +* **common:** support loading locales from a global ([#33523](https://github.com/angular/angular/issues/33523)) ([c5894e0](https://github.com/angular/angular/commit/c5894e0)) +* **ivy:** graceful evaluation of unknown or invalid expressions ([#33453](https://github.com/angular/angular/issues/33453)) ([ce30888](https://github.com/angular/angular/commit/ce30888)) +* **ivy:** implement unknown element detection in jit mode ([#33419](https://github.com/angular/angular/issues/33419)) ([c83f501](https://github.com/angular/angular/commit/c83f501)) +* add a flag in bootstrap to enable coalesce event change detection to improve performance ([#30533](https://github.com/angular/angular/issues/30533)) ([44623a1](https://github.com/angular/angular/commit/44623a1)) + + +### Performance Improvements + +* **ivy:** add new benchmark focused on template creation ([#33511](https://github.com/angular/angular/issues/33511)) ([df1bef3](https://github.com/angular/angular/commit/df1bef3)) +* **ivy:** add ngIf-like directive to the ng_template benchmark ([#33595](https://github.com/angular/angular/issues/33595)) ([e89c2dd](https://github.com/angular/angular/commit/e89c2dd)) +* **ivy:** avoid native node retrieval from LView ([#33511](https://github.com/angular/angular/issues/33511)) ([083d48e](https://github.com/angular/angular/commit/083d48e)) +* **ivy:** avoid repeated native node retrieval and patching ([#33322](https://github.com/angular/angular/issues/33322)) ([41caafc](https://github.com/angular/angular/commit/41caafc)) +* **ivy:** avoid repeated tNode.initialInputs reads ([#33322](https://github.com/angular/angular/issues/33322)) ([4452d6d](https://github.com/angular/angular/commit/4452d6d)) +* **ivy:** move local references into consts array ([#33129](https://github.com/angular/angular/issues/33129)) ([66725b7](https://github.com/angular/angular/commit/66725b7)), closes [#32798](https://github.com/angular/angular/issues/32798) + + + + +# [9.0.0-rc.0](https://github.com/angular/angular/compare/9.0.0-next.15...9.0.0-rc.0) (2019-10-31) + +Please see the [v9 update guide](https://v9.angular.io/guide/updating-to-version-9) for more information. + + + + +# [9.0.0-next.15](https://github.com/angular/angular/compare/9.0.0-next.14...9.0.0-next.15) (2019-10-30) + + +### Bug Fixes + +* **compiler:** i18n - ignore `alt-trans` tags in XLIFF 1.2 ([#33450](https://github.com/angular/angular/issues/33450)) ([936700a](https://github.com/angular/angular/commit/936700a)), closes [#33161](https://github.com/angular/angular/issues/33161) +* **ivy:** descend into ICU containers when collecting rootNodes ([#33493](https://github.com/angular/angular/issues/33493)) ([563a507](https://github.com/angular/angular/commit/563a507)) +* **ivy:** descend into view containers on elements when collecting rootNodes ([#33493](https://github.com/angular/angular/issues/33493)) ([87743f1](https://github.com/angular/angular/commit/87743f1)) +* **ivy:** descend into view containers on ng-container when collecting rootNodes ([#33493](https://github.com/angular/angular/issues/33493)) ([a5167bd](https://github.com/angular/angular/commit/a5167bd)) +* **ivy:** descend into view containers on ng-template when collecting rootNodes ([#33493](https://github.com/angular/angular/issues/33493)) ([502fb7e](https://github.com/angular/angular/commit/502fb7e)) +* **ivy:** ensure overrides for 'multi: true' only appear once in final providers ([#33104](https://github.com/angular/angular/issues/33104)) ([e483aca](https://github.com/angular/angular/commit/e483aca)) +* **ivy:** handle elements with local refs in i18n blocks ([#33415](https://github.com/angular/angular/issues/33415)) ([bd40c89](https://github.com/angular/angular/commit/bd40c89)) +* **ivy:** i18n - support setting locales for each translation file ([#33381](https://github.com/angular/angular/issues/33381)) ([62b2840](https://github.com/angular/angular/commit/62b2840)), closes [#33323](https://github.com/angular/angular/issues/33323) +* **ivy:** i18n - update `localize-translate` to accept target-locales ([#33381](https://github.com/angular/angular/issues/33381)) ([41979d6](https://github.com/angular/angular/commit/41979d6)) +* **language-service:** Improve signature selection for pipes with args ([#33456](https://github.com/angular/angular/issues/33456)) ([1de7579](https://github.com/angular/angular/commit/1de7579)) + + +### Features + +* **bazel:** update [@bazel](https://github.com/bazel)/schematics to Bazel 1.0.0 ([#33476](https://github.com/angular/angular/issues/33476)) ([540d104](https://github.com/angular/angular/commit/540d104)), closes [/github.com/angular/angular/pull/33367#issuecomment-547643246](https://github.com//github.com/angular/angular/pull/33367/issues/issuecomment-547643246) +* **bazel:** update bazel-schematics to use Ivy and new rollup_bundle ([#33435](https://github.com/angular/angular/issues/33435)) ([bf913cc](https://github.com/angular/angular/commit/bf913cc)) +* **ivy:** i18n - support inlining of XTB formatted translation files ([#33444](https://github.com/angular/angular/issues/33444)) ([2c623fd](https://github.com/angular/angular/commit/2c623fd)) +* **language-service:** add support for text replacement ([#33091](https://github.com/angular/angular/issues/33091)) ([da4eb91](https://github.com/angular/angular/commit/da4eb91)) + + +### Performance Improvements + +* **ivy:** avoid generating selectors array for directives without a selector ([#33431](https://github.com/angular/angular/issues/33431)) ([c3e9356](https://github.com/angular/angular/commit/c3e9356)) + + + + +## [8.2.13](https://github.com/angular/angular/compare/8.2.12...8.2.13) (2019-10-30) + + +### Bug Fixes + +* **compiler:** i18n - ignore `alt-trans` tags in XLIFF 1.2 ([#33464](https://github.com/angular/angular/issues/33464)) ([f97c464](https://github.com/angular/angular/commit/f97c464)), closes [#33161](https://github.com/angular/angular/issues/33161) + + + + +# [9.0.0-next.14](https://github.com/angular/angular/compare/9.0.0-next.13...9.0.0-next.14) (2019-10-25) + + +### Bug Fixes + +* **core:** missing-injectable migration should handle forwardRef ([#33286](https://github.com/angular/angular/issues/33286)) ([eeecbf2](https://github.com/angular/angular/commit/eeecbf2)) +* **core:** missing-injectable migration should not migrate providers with "useExisting" ([#33286](https://github.com/angular/angular/issues/33286)) ([4d23b60](https://github.com/angular/angular/commit/4d23b60)) +* **core:** missing-injectable migration should not update type definitions ([#33286](https://github.com/angular/angular/issues/33286)) ([335854f](https://github.com/angular/angular/commit/335854f)) +* **ivy:** allow abstract directives to have an invalid constructor ([#32987](https://github.com/angular/angular/issues/32987)) ([8d15bfa](https://github.com/angular/angular/commit/8d15bfa)), closes [#32981](https://github.com/angular/angular/issues/32981) +* **ivy:** fix broken typechecking test on Windows ([#33376](https://github.com/angular/angular/issues/33376)) ([63f0ded](https://github.com/angular/angular/commit/63f0ded)) +* **ivy:** split checkTypeOfReferences into DOM and non-DOM flags. ([#33365](https://github.com/angular/angular/issues/33365)) ([113411c](https://github.com/angular/angular/commit/113411c)) +* **ivy:** support abstract directives in template type checking ([#33131](https://github.com/angular/angular/issues/33131)) ([a42057d](https://github.com/angular/angular/commit/a42057d)), closes [#30080](https://github.com/angular/angular/issues/30080) +* **language-service:** Do not show HTML elements and attrs for ext template ([#33388](https://github.com/angular/angular/issues/33388)) ([a78b701](https://github.com/angular/angular/commit/a78b701)) +* **ngcc:** prevent reflected decorators from being clobbered ([#33362](https://github.com/angular/angular/issues/33362)) ([0de2dbf](https://github.com/angular/angular/commit/0de2dbf)) + + +### Features + +* **ivy:** add a runtime feature to copy cmp/dir definitions ([#33362](https://github.com/angular/angular/issues/33362)) ([818c514](https://github.com/angular/angular/commit/818c514)) +* **ivy:** add flag to disable checking of text attributes ([#33365](https://github.com/angular/angular/issues/33365)) ([d8ce212](https://github.com/angular/angular/commit/d8ce212)) +* **ivy:** allow the locale to be set via a global property ([#33314](https://github.com/angular/angular/issues/33314)) ([fde8363](https://github.com/angular/angular/commit/fde8363)) +* **ivy:** i18n - inline current locale at compile-time ([#33314](https://github.com/angular/angular/issues/33314)) ([fb84ea7](https://github.com/angular/angular/commit/fb84ea7)) +* **ivy:** input type coercion for template type-checking ([#33243](https://github.com/angular/angular/issues/33243)) ([f1269d9](https://github.com/angular/angular/commit/f1269d9)) +* **ivy:** strictness flags for template type checking ([#33365](https://github.com/angular/angular/issues/33365)) ([0d9be22](https://github.com/angular/angular/commit/0d9be22)) +* **ivy:** verify whether TypeScript version is supported ([#33377](https://github.com/angular/angular/issues/33377)) ([4aa51b7](https://github.com/angular/angular/commit/4aa51b7)) +* **ngcc:** add a migration for undecorated child classes ([#33362](https://github.com/angular/angular/issues/33362)) ([b381497](https://github.com/angular/angular/commit/b381497)) +* **ngcc:** enable migrations to apply schematics to libraries ([#33362](https://github.com/angular/angular/issues/33362)) ([6b26748](https://github.com/angular/angular/commit/6b26748)) +* **ngcc:** migrate services that are missing `@Injectable()` ([#33362](https://github.com/angular/angular/issues/33362)) ([31b9492](https://github.com/angular/angular/commit/31b9492)) + + +### Performance Improvements + +* **ivy:** apply [style]/[class] bindings directly to style/className ([#33336](https://github.com/angular/angular/issues/33336)) ([dcdb433](https://github.com/angular/angular/commit/dcdb433)) +* **ivy:** apply static styles/classes directly to an element's style/className properties ([#33364](https://github.com/angular/angular/issues/33364)) ([5607ad8](https://github.com/angular/angular/commit/5607ad8)) +* **ivy:** improve styling performance ([#33326](https://github.com/angular/angular/issues/33326)) ([d40ee6a](https://github.com/angular/angular/commit/d40ee6a)) + + + + +# [9.0.0-next.13](https://github.com/angular/angular/compare/9.0.0-next.12...9.0.0-next.13) (2019-10-23) + + +### Bug Fixes + +* **bazel:** remove deprecated ng_setup_workspace() function ([#33330](https://github.com/angular/angular/issues/33330)) ([8bc5fb2](https://github.com/angular/angular/commit/8bc5fb2)) +* **compiler:** do not throw when using abstract directive from other compilation unit ([#33347](https://github.com/angular/angular/issues/33347)) ([355e54a](https://github.com/angular/angular/commit/355e54a)) +* **compiler:** ensure that legacy ids are rendered for ICUs ([#33318](https://github.com/angular/angular/issues/33318)) ([5d86e4a](https://github.com/angular/angular/commit/5d86e4a)) +* **ivy:** align VE + Ivy #ref types in fullTemplateTypeCheck: false ([#33261](https://github.com/angular/angular/issues/33261)) ([77240e1](https://github.com/angular/angular/commit/77240e1)) +* **ivy:** handle method calls of local variables in template type checker ([#33132](https://github.com/angular/angular/issues/33132)) ([e2211ed](https://github.com/angular/angular/commit/e2211ed)), closes [#32900](https://github.com/angular/angular/issues/32900) +* **language-service:** Add directive selectors & banana-in-a-box to completions ([#33311](https://github.com/angular/angular/issues/33311)) ([49eec5d](https://github.com/angular/angular/commit/49eec5d)) +* **language-service:** Add global symbol for $any() ([#33245](https://github.com/angular/angular/issues/33245)) ([3f257e9](https://github.com/angular/angular/commit/3f257e9)) +* **language-service:** Preserve CRLF in templates for language-service ([#33241](https://github.com/angular/angular/issues/33241)) ([65a0d2b](https://github.com/angular/angular/commit/65a0d2b)) +* **ngcc:** do not fail when multiple workers try to create the same directory ([#33237](https://github.com/angular/angular/issues/33237)) ([8017229](https://github.com/angular/angular/commit/8017229)), closes [/github.com/angular/angular/pull/33049#issuecomment-540485703](https://github.com//github.com/angular/angular/pull/33049/issues/issuecomment-540485703) + + +### Features + +* **core:** add ModuleWithProviders generic type migration ([#33217](https://github.com/angular/angular/issues/33217)) ([56731f6](https://github.com/angular/angular/commit/56731f6)) +* **ivy:** enable re-export of the compilation scope of NgModules privately ([#33177](https://github.com/angular/angular/issues/33177)) ([c4733c1](https://github.com/angular/angular/commit/c4733c1)), closes [#29361](https://github.com/angular/angular/issues/29361) +* **ivy:** give shim generation its own compiler options ([#33256](https://github.com/angular/angular/issues/33256)) ([d4db746](https://github.com/angular/angular/commit/d4db746)) +* **ngcc:** enable private NgModule re-exports in ngcc on request ([#33177](https://github.com/angular/angular/issues/33177)) ([e030375](https://github.com/angular/angular/commit/e030375)) + + +### Performance Improvements + +* **ivy:** avoid unnecessary i18n pass while processing a template ([#33284](https://github.com/angular/angular/issues/33284)) ([7f7dc7c](https://github.com/angular/angular/commit/7f7dc7c)) + + +### BREAKING CHANGES + +* **bazel:** @angular/bazel ng_setup_workspace() is no longer needed and has been removed. +We assume you will fetch rules_nodejs in your WORKSPACE file, and no other dependencies remain here. +Simply remove any calls to this function and the corresponding load statement. + + + + +## [8.2.12](https://github.com/angular/angular/compare/8.2.11...8.2.12) (2019-10-23) + + +### Bug Fixes + +* **upgrade:** remove unused version export ([#33180](https://github.com/angular/angular/issues/33180)) ([37cbcfa](https://github.com/angular/angular/commit/37cbcfa)) + + + + +# [9.0.0-next.12](https://github.com/angular/angular/compare/9.0.0-next.11...9.0.0-next.12) (2019-10-18) + + +### Bug Fixes + +* **bazel:** Remove angular devkit and restore ngc postinstall ([#32946](https://github.com/angular/angular/issues/32946)) ([f036684](https://github.com/angular/angular/commit/f036684)) +* **common:** remove deprecated support for intl API ([#29250](https://github.com/angular/angular/issues/29250)) ([9e7668f](https://github.com/angular/angular/commit/9e7668f)), closes [#18284](https://github.com/angular/angular/issues/18284) +* **compiler:** absolute source span for template attribute expressions ([#33189](https://github.com/angular/angular/issues/33189)) ([fd4fed1](https://github.com/angular/angular/commit/fd4fed1)) +* **core:** add CLI instructions when localize polyfill is missing ([#33199](https://github.com/angular/angular/issues/33199)) ([5dfbcd5](https://github.com/angular/angular/commit/5dfbcd5)) +* **ivy:** ensure errors are thrown during checkNoChanges for style/class bindings ([#33103](https://github.com/angular/angular/issues/33103)) ([f45c431](https://github.com/angular/angular/commit/f45c431)) +* **ivy:** ensure map-based interpolation works with other map-based sources ([#33236](https://github.com/angular/angular/issues/33236)) ([7b64680](https://github.com/angular/angular/commit/7b64680)) +* **ivy:** handling className as an input properly ([#33188](https://github.com/angular/angular/issues/33188)) ([6f203c9](https://github.com/angular/angular/commit/6f203c9)) +* **ivy:** ignore non-property bindings to inputs in template type checker ([#33130](https://github.com/angular/angular/issues/33130)) ([08cb2fa](https://github.com/angular/angular/commit/08cb2fa)), closes [#32099](https://github.com/angular/angular/issues/32099) [#32496](https://github.com/angular/angular/issues/32496) +* **ivy:** throw better error for missing generic type in ModuleWithProviders ([#33187](https://github.com/angular/angular/issues/33187)) ([0e08ad6](https://github.com/angular/angular/commit/0e08ad6)) +* **ivy:** use container i18n meta if a message is a single ICU ([#33191](https://github.com/angular/angular/issues/33191)) ([7e64bbe](https://github.com/angular/angular/commit/7e64bbe)), closes [#33171](https://github.com/angular/angular/issues/33171) +* **ivy:** use ReflectionHost to check exports when writing an import ([#33192](https://github.com/angular/angular/issues/33192)) ([de44570](https://github.com/angular/angular/commit/de44570)) +* **language-service:** Increase project/script version in MockHost.reset() ([#33200](https://github.com/angular/angular/issues/33200)) ([43241a5](https://github.com/angular/angular/commit/43241a5)) +* **language-service:** reset MockHost after every spec instead of creating new LS ([#33200](https://github.com/angular/angular/issues/33200)) ([11bf767](https://github.com/angular/angular/commit/11bf767)) +* **ngcc:** avoid warning when reflecting on index signature member ([#33198](https://github.com/angular/angular/issues/33198)) ([78214e7](https://github.com/angular/angular/commit/78214e7)), closes [/github.com/angular/angular/blob/4659cc26e/packages/common/http/src/jsonp.ts#L39](https://github.com//github.com/angular/angular/blob/4659cc26e/packages/common/http/src/jsonp.ts/issues/L39) +* **ngcc:** better detection of end of decorator expression ([#33192](https://github.com/angular/angular/issues/33192)) ([5071083](https://github.com/angular/angular/commit/5071083)) +* **ngcc:** Esm5ReflectionHost.getDeclarationOfIdentifier should handle aliased inner declarations ([#33252](https://github.com/angular/angular/issues/33252)) ([bfd07b3](https://github.com/angular/angular/commit/bfd07b3)) +* **ngcc:** report the correct viaModule when reflecting over commonjs ([#33192](https://github.com/angular/angular/issues/33192)) ([afcff73](https://github.com/angular/angular/commit/afcff73)) +* **router:** adjust UrlTree redirect to replace URL if in eager update ([#32988](https://github.com/angular/angular/issues/32988)) ([f6667f8](https://github.com/angular/angular/commit/f6667f8)), closes [#31168](https://github.com/angular/angular/issues/31168) [#27148](https://github.com/angular/angular/issues/27148) +* **upgrade:** remove unused version export ([#33180](https://github.com/angular/angular/issues/33180)) ([becd62d](https://github.com/angular/angular/commit/becd62d)) + + +### Features + +* add a flag in bootstrap to enable coalesce event change detection to improve performance ([#30533](https://github.com/angular/angular/issues/30533)) ([21c1e14](https://github.com/angular/angular/commit/21c1e14)) +* **ivy:** improve debugging experience for styles/classes ([#33179](https://github.com/angular/angular/issues/33179)) ([724707c](https://github.com/angular/angular/commit/724707c)) +* typescript 3.6 support ([#32946](https://github.com/angular/angular/issues/32946)) ([86e1e6c](https://github.com/angular/angular/commit/86e1e6c)), closes [#32380](https://github.com/angular/angular/issues/32380) +* **ivy:** type checking of event bindings ([#33125](https://github.com/angular/angular/issues/33125)) ([6958d11](https://github.com/angular/angular/commit/6958d11)) +* **language-service:** add Angular pseudo elements into completions ([#31248](https://github.com/angular/angular/issues/31248)) ([7c64b8d](https://github.com/angular/angular/commit/7c64b8d)) +* **ngcc:** support --async flag (defaults to true) ([#33192](https://github.com/angular/angular/issues/33192)) ([2196114](https://github.com/angular/angular/commit/2196114)) +* **ngcc:** support ignoreMissingDependencies in ngcc config ([#33192](https://github.com/angular/angular/issues/33192)) ([4da2dda](https://github.com/angular/angular/commit/4da2dda)) + + +### Performance Improvements + +* **ivy:** initialise inputs from static attrs on the first template pass only ([#33195](https://github.com/angular/angular/issues/33195)) ([aef7dca](https://github.com/angular/angular/commit/aef7dca)) +* **ivy:** limit global state read / write in host bindings ([#33195](https://github.com/angular/angular/issues/33195)) ([3e14c2d](https://github.com/angular/angular/commit/3e14c2d)) + + +### Reverts + +* build: remove vendored Babel typings ([#33176](https://github.com/angular/angular/issues/33176)) ([#33215](https://github.com/angular/angular/issues/33215)) ([e9ee685](https://github.com/angular/angular/commit/e9ee685)) +* build: update webdriver-manager to support latest Chrome ([#33216](https://github.com/angular/angular/issues/33216)) ([a914859](https://github.com/angular/angular/commit/a914859)) +* build: use http caching on windows CI runs ([#33238](https://github.com/angular/angular/issues/33238)) ([#33254](https://github.com/angular/angular/issues/33254)) ([117ca7c](https://github.com/angular/angular/commit/117ca7c)) +* feat: add a flag in bootstrap to enable coalesce event change detection to improve performance ([#30533](https://github.com/angular/angular/issues/30533)) ([#33230](https://github.com/angular/angular/issues/33230)) ([082aed6](https://github.com/angular/angular/commit/082aed6)) + + +### BREAKING CHANGES + +* typescript 3.4 and 3.5 are no longer supported, please update to typescript 3.6 + + + + +# [9.0.0-next.11](https://github.com/angular/angular/compare/9.0.0-next.10...9.0.0-next.11) (2019-10-15) + + +### Bug Fixes + +* **compiler-cli:** produce diagnostic messages in expression of PrefixNot node. ([#33087](https://github.com/angular/angular/issues/33087)) ([2ddc851](https://github.com/angular/angular/commit/2ddc851)) +* **compiler-cli:** resolve type of exported *ngIf variable. ([#33016](https://github.com/angular/angular/issues/33016)) ([39587ad](https://github.com/angular/angular/commit/39587ad)) +* **ivy:** avoid DOM element assertions if procedural renderer is used ([#33156](https://github.com/angular/angular/issues/33156)) ([11e04b1](https://github.com/angular/angular/commit/11e04b1)) +* **ivy:** do not always accept `undefined` for directive inputs ([#33066](https://github.com/angular/angular/issues/33066)) ([50bf17a](https://github.com/angular/angular/commit/50bf17a)), closes [#32690](https://github.com/angular/angular/issues/32690) +* **ivy:** ensure sanitizer is not used when direct class application occurs ([#33154](https://github.com/angular/angular/issues/33154)) ([1cda80e](https://github.com/angular/angular/commit/1cda80e)) +* **ivy:** i18n - add XLIFF aliases for legacy message id support ([#33160](https://github.com/angular/angular/issues/33160)) ([ad72c90](https://github.com/angular/angular/commit/ad72c90)) +* **ivy:** i18n - strip meta blocks from untranslated messages ([#33097](https://github.com/angular/angular/issues/33097)) ([1845faa](https://github.com/angular/angular/commit/1845faa)) +* **ivy:** i18n - support lazy-load template string helpers ([#33097](https://github.com/angular/angular/issues/33097)) ([83425fa](https://github.com/angular/angular/commit/83425fa)) +* **ivy:** i18n - turn on legacy message-id support by default ([#33053](https://github.com/angular/angular/issues/33053)) ([f640a4a](https://github.com/angular/angular/commit/f640a4a)) +* **language-service:** Use index.d.ts for typings ([#33043](https://github.com/angular/angular/issues/33043)) ([728cd84](https://github.com/angular/angular/commit/728cd84)) +* google3 sync which requires type hints ([#33108](https://github.com/angular/angular/issues/33108)) ([0c69ec2](https://github.com/angular/angular/commit/0c69ec2)) +* **ngcc:** rename the executable from `ivy-ngcc` to `ngcc` ([#33140](https://github.com/angular/angular/issues/33140)) ([1a34fbc](https://github.com/angular/angular/commit/1a34fbc)) +* **service-worker:** continue serving api requests on cache failure ([#32996](https://github.com/angular/angular/issues/32996)) ([52483bf](https://github.com/angular/angular/commit/52483bf)), closes [#21412](https://github.com/angular/angular/issues/21412) + + +### Code Refactoring + +* **forms:** remove ngForm element selector ([#33058](https://github.com/angular/angular/issues/33058)) ([0b1daa9](https://github.com/angular/angular/commit/0b1daa9)) + + +### Features + +* **compiler:** record absolute span of template expressions in parser ([#31897](https://github.com/angular/angular/issues/31897)) ([b04488d](https://github.com/angular/angular/commit/b04488d)), closes [#31898](https://github.com/angular/angular/issues/31898) +* **core:** add postinstall ngcc migration ([#32999](https://github.com/angular/angular/issues/32999)) ([30d25f6](https://github.com/angular/angular/commit/30d25f6)) +* **ivy:** better error messages for unknown components ([#33064](https://github.com/angular/angular/issues/33064)) ([d8249d1](https://github.com/angular/angular/commit/d8249d1)) +* **ivy:** check regular attributes that correspond with directive inputs ([#33066](https://github.com/angular/angular/issues/33066)) ([cd7b199](https://github.com/angular/angular/commit/cd7b199)) +* **ivy:** disable strict null checks for input bindings ([#33066](https://github.com/angular/angular/issues/33066)) ([ece0b2d](https://github.com/angular/angular/commit/ece0b2d)) +* **ivy:** i18n - support source locale inlining ([#33101](https://github.com/angular/angular/issues/33101)) ([f433d66](https://github.com/angular/angular/commit/f433d66)) +* change tslib from direct dependency to peerDependency ([#32167](https://github.com/angular/angular/issues/32167)) ([e2d5bc2](https://github.com/angular/angular/commit/e2d5bc2)) +* **language-service:** directive info when looking up attribute's symbol ([#33127](https://github.com/angular/angular/issues/33127)) ([ce7f934](https://github.com/angular/angular/commit/ce7f934)) +* **language-service:** hover information for component NgModules ([#33118](https://github.com/angular/angular/issues/33118)) ([e409ed0](https://github.com/angular/angular/commit/e409ed0)), closes [#32565](https://github.com/angular/angular/issues/32565) +* **ngcc:** support fallback to a default configuration ([#33008](https://github.com/angular/angular/issues/33008)) ([9167624](https://github.com/angular/angular/commit/9167624)) +* **ngcc:** support version ranges in project/default configurations ([#33008](https://github.com/angular/angular/issues/33008)) ([90007e9](https://github.com/angular/angular/commit/90007e9)) + + +### Performance Improvements + +* **ivy:** guard host binding execution with a TNode flag ([#33102](https://github.com/angular/angular/issues/33102)) ([d4d0723](https://github.com/angular/angular/commit/d4d0723)) +* **ivy:** introduce micro-benchmark for directive instantiation ([#33082](https://github.com/angular/angular/issues/33082)) ([22d4efb](https://github.com/angular/angular/commit/22d4efb)) +* **ivy:** limit memory reads in getOrCreateNodeInjectorForNode ([#33102](https://github.com/angular/angular/issues/33102)) ([dcca80b](https://github.com/angular/angular/commit/dcca80b)) +* **ivy:** speed up bindings when no directives are present ([#32919](https://github.com/angular/angular/issues/32919)) ([b2decf0](https://github.com/angular/angular/commit/b2decf0)) +* **ivy:** stricter null checks in setInputsFromAttrs ([#33102](https://github.com/angular/angular/issues/33102)) ([b800b88](https://github.com/angular/angular/commit/b800b88)) +* **ivy:** use instanceof operator to check for NodeInjectorFactory instances ([#33082](https://github.com/angular/angular/issues/33082)) ([8d111da](https://github.com/angular/angular/commit/8d111da)) + + +### BREAKING CHANGES + +* We no longer directly have a direct depedency on `tslib`. Instead it is now listed a `peerDependency`. + +Users not using the CLI will need to manually install `tslib` via; +``` +yarn add tslib +``` +or +``` +npm install tslib --save +``` +* **forms:** * `` can no longer be used as a selector. Use `` instead. +* The `NgFormSelectorWarning` directive has been removed. +* `FormsModule.withConfig` has been removed. Use the `FormsModule` directly. + + + + +## [8.2.11](https://github.com/angular/angular/compare/8.2.10...8.2.11) (2019-10-15) + + +### Bug Fixes + +* **service-worker:** continue serving api requests on cache failure ([#33165](https://github.com/angular/angular/issues/33165)) ([a2716ac](https://github.com/angular/angular/commit/a2716ac)), closes [#32996](https://github.com/angular/angular/issues/32996) [#21412](https://github.com/angular/angular/issues/21412) + + + + +# [9.0.0-next.10](https://github.com/angular/angular/compare/9.0.0-next.9...9.0.0-next.10) (2019-10-09) + + +### Bug Fixes + +* **common:** expand type for "ngForOf" input to work with strict null checks ([#31371](https://github.com/angular/angular/issues/31371)) ([c1bb886](https://github.com/angular/angular/commit/c1bb886)), closes [#16373](https://github.com//github.com/angular/components/pull/16373) +* **core:** ngNoopZone should have the same signature with ngZone ([#32068](https://github.com/angular/angular/issues/32068)) ([3a53e2c](https://github.com/angular/angular/commit/3a53e2c)), closes [#32063](https://github.com/angular/angular/issues/32063) +* **core:** set migration schematic versions to valid semver versions ([#32991](https://github.com/angular/angular/issues/32991)) ([0119f46](https://github.com/angular/angular/commit/0119f46)) +* **core:** update migration descriptions with links to AIO documentation ([#32991](https://github.com/angular/angular/issues/32991)) ([f8eca84](https://github.com/angular/angular/commit/f8eca84)) +* **ivy:** avoid exposing `ng` with Closure Compiler enhanced optimizations ([#33010](https://github.com/angular/angular/issues/33010)) ([bad3434](https://github.com/angular/angular/commit/bad3434)) +* **ivy:** generate ng-reflect properties for i18n attributes ([#32989](https://github.com/angular/angular/issues/32989)) ([90fb5d9](https://github.com/angular/angular/commit/90fb5d9)) +* **ivy:** i18n - better translation warnings ([#32867](https://github.com/angular/angular/issues/32867)) ([97d5700](https://github.com/angular/angular/commit/97d5700)) +* **ivy:** i18n - do not render message ids unnecessarily ([#32867](https://github.com/angular/angular/issues/32867)) ([9188751](https://github.com/angular/angular/commit/9188751)) +* **ivy:** i18n - support colons in $localize metadata ([#32867](https://github.com/angular/angular/issues/32867)) ([d24ade9](https://github.com/angular/angular/commit/d24ade9)) +* **ivy:** i18n - throw an error if a translation contains an invalid placeholder ([#32867](https://github.com/angular/angular/issues/32867)) ([601f87c](https://github.com/angular/angular/commit/601f87c)) +* **ivy:** missing schematics field in localize package ([#33025](https://github.com/angular/angular/issues/33025)) ([d18289f](https://github.com/angular/angular/commit/d18289f)), closes [#32791](https://github.com/angular/angular/issues/32791) +* **ivy:** process nested animation metadata ([#32818](https://github.com/angular/angular/issues/32818)) ([c61e4d7](https://github.com/angular/angular/commit/c61e4d7)), closes [#32794](https://github.com/angular/angular/issues/32794) +* **ivy:** unable to bind style zero ([#32994](https://github.com/angular/angular/issues/32994)) ([3efb060](https://github.com/angular/angular/commit/3efb060)), closes [#32984](https://github.com/angular/angular/issues/32984) +* **language-service:** create StaticReflector once only ([#32543](https://github.com/angular/angular/issues/32543)) ([adb562b](https://github.com/angular/angular/commit/adb562b)) + + +### Code Refactoring + +* **core:** remove deprecated Renderer ([#33019](https://github.com/angular/angular/issues/33019)) ([2265cb5](https://github.com/angular/angular/commit/2265cb5)) + + +### Features + +* **core:** default to dynamic queries ([#32720](https://github.com/angular/angular/issues/32720)) ([7806596](https://github.com/angular/angular/commit/7806596)) +* **core:** make static query flag optional ([#32986](https://github.com/angular/angular/issues/32986)) ([900d005](https://github.com/angular/angular/commit/900d005)), closes [#32686](https://github.com/angular/angular/issues/32686) +* **forms:** formGroupName and formArrayName also accepts a number ([#32607](https://github.com/angular/angular/issues/32607)) ([fee28e2](https://github.com/angular/angular/commit/fee28e2)) +* **ivy:** i18n - implement compile-time inlining ([#32881](https://github.com/angular/angular/issues/32881)) ([2cdb3a0](https://github.com/angular/angular/commit/2cdb3a0)) +* **ivy:** i18n - render legacy message ids in `$localize` if requested ([#32937](https://github.com/angular/angular/issues/32937)) ([bcbf3e4](https://github.com/angular/angular/commit/bcbf3e4)) +* **language-service:** module definitions on directive hover ([#32763](https://github.com/angular/angular/issues/32763)) ([0d186dd](https://github.com/angular/angular/commit/0d186dd)), closes [#32565](https://github.com/angular/angular/issues/32565) +* **ngcc:** expose `--create-ivy-entry-points` option on ivy-ngcc ([#33049](https://github.com/angular/angular/issues/33049)) ([b2b917d](https://github.com/angular/angular/commit/b2b917d)), closes [/github.com/angular/angular/pull/32999#issuecomment-539937368](https://github.com//github.com/angular/angular/pull/32999/issues/issuecomment-539937368) + + +### Performance Improvements + +* **ivy:** add static attributes to the element_text_create benchmark ([#32997](https://github.com/angular/angular/issues/32997)) ([affae99](https://github.com/angular/angular/commit/affae99)) +* **ivy:** attempt rendering initial styling only if present ([#32979](https://github.com/angular/angular/issues/32979)) ([6004703](https://github.com/angular/angular/commit/6004703)) +* **ivy:** avoid memory allocation in the isAnimationProp check ([#32997](https://github.com/angular/angular/issues/32997)) ([9f0c549](https://github.com/angular/angular/commit/9f0c549)) +* **ivy:** increase number of created views in the element_text_create benchmark ([#32979](https://github.com/angular/angular/issues/32979)) ([8593d0d](https://github.com/angular/angular/commit/8593d0d)) +* **ivy:** limit TNode.inputs reads on first template pass ([#32979](https://github.com/angular/angular/issues/32979)) ([e6881b5](https://github.com/angular/angular/commit/e6881b5)) +* **ivy:** move attributes array into component def ([#32798](https://github.com/angular/angular/issues/32798)) ([d5b87d3](https://github.com/angular/angular/commit/d5b87d3)) +* **language-service:** improve Language service performance ([#32098](https://github.com/angular/angular/issues/32098)) ([65297cd](https://github.com/angular/angular/commit/65297cd)) + + +### BREAKING CHANGES + +* **core:** The deprecated type `Renderer` has been removed. Use `Renderer2` instead. +* **core:** The deprecated type `RenderComponentType` has been removed. Use `RendererType2` instead. +* **core:** The deprecated type `RootRenderer` has been removed. Use `RendererFactory2` instead. + + + + +## [8.2.10](https://github.com/angular/angular/compare/8.2.9...8.2.10) (2019-10-09) + +This release contains various API docs improvements. + + + + +# [9.0.0-next.9](https://github.com/angular/angular/compare/9.0.0-next.8...9.0.0-next.9) (2019-10-02) + + +### Bug Fixes + +* **ivy:** ensure class/style values are debuggable through `DebugElement` ([#32842](https://github.com/angular/angular/issues/32842)) ([c32b2ae](https://github.com/angular/angular/commit/c32b2ae)) +* **ivy:** ensure TestBed restores fields to the most original value ([#32823](https://github.com/angular/angular/issues/32823)) ([c8be987](https://github.com/angular/angular/commit/c8be987)) +* **ivy:** include `ngProjectAs` into attributes array ([#32784](https://github.com/angular/angular/issues/32784)) ([966c2a3](https://github.com/angular/angular/commit/966c2a3)) +* **ivy:** Only restore registered modules if user compiles modules with TestBed ([#32944](https://github.com/angular/angular/issues/32944)) ([63256b5](https://github.com/angular/angular/commit/63256b5)) +* **ivy:** R3TestBed should clean up registered modules after each test ([#32872](https://github.com/angular/angular/issues/32872)) ([475e36a](https://github.com/angular/angular/commit/475e36a)) +* **ivy:** refresh child components before executing ViewQuery function ([#32922](https://github.com/angular/angular/issues/32922)) ([72f3747](https://github.com/angular/angular/commit/72f3747)) +* **language-service:** add closing quote in invalid test template ([#32785](https://github.com/angular/angular/issues/32785)) ([01e4d44](https://github.com/angular/angular/commit/01e4d44)) +* **language-service:** Turn on strict mode for test project ([#32783](https://github.com/angular/angular/issues/32783)) ([28358b6](https://github.com/angular/angular/commit/28358b6)) +* **ngcc:** ensure private exports are added for `ModuleWithProviders` ([#32902](https://github.com/angular/angular/issues/32902)) ([002a97d](https://github.com/angular/angular/commit/002a97d)) +* **ngcc:** handle presence of both `ctorParameters` and `__decorate` ([#32901](https://github.com/angular/angular/issues/32901)) ([747f0cf](https://github.com/angular/angular/commit/747f0cf)) +* **ngcc:** make the build-marker error more clear ([#32712](https://github.com/angular/angular/issues/32712)) ([0ea4875](https://github.com/angular/angular/commit/0ea4875)), closes [/github.com/angular/angular/issues/31354#issuecomment-532080537](https://github.com//github.com/angular/angular/issues/31354/issues/issuecomment-532080537) +* **upgrade:** fix AngularJsUrlCodec to support Safari ([#32959](https://github.com/angular/angular/issues/32959)) ([39e8ceb](https://github.com/angular/angular/commit/39e8ceb)) + + +### Features + +* update rxjs peerDependencies minimum requirment to 6.5.3 ([#32812](https://github.com/angular/angular/issues/32812)) ([66658c4](https://github.com/angular/angular/commit/66658c4)) +* **ivy:** support ng-add in localize package ([#32791](https://github.com/angular/angular/issues/32791)) ([e41cbfb](https://github.com/angular/angular/commit/e41cbfb)) +* **language-service:** allow retreiving synchronized analyzed NgModules ([#32779](https://github.com/angular/angular/issues/32779)) ([98feee7](https://github.com/angular/angular/commit/98feee7)) +* **service-worker:** remove deprecated `versionedFiles` option ([#32862](https://github.com/angular/angular/issues/32862)) ([5d5c94d](https://github.com/angular/angular/commit/5d5c94d)) + + +### Performance Improvements + +* **ivy:** avoid repeat global state accesses in i18n instructions ([#32916](https://github.com/angular/angular/issues/32916)) ([ffc34b3](https://github.com/angular/angular/commit/ffc34b3)) + + +### BREAKING CHANGES + +* **service-worker:** Remove deprecated option `versionedFiles` from service worker asset group configuration in `ngsw-config.json` + +Before +```json +"assetGroups": [ + { + "name": "test", + "resources": { + "versionedFiles": [ + "/**/*.txt" + ] + } + } +] +``` + +After +```json +"assetGroups": [ + { + "name": "test", + "resources": { + "files": [ + "/**/*.txt" + ] + } + } +] +``` + + + + +## [8.2.9](https://github.com/angular/angular/compare/8.2.8...8.2.9) (2019-10-02) + + +### Bug Fixes + +* **upgrade:** fix AngularJsUrlCodec to support Safari ([#32959](https://github.com/angular/angular/issues/32959)) ([57457fb](https://github.com/angular/angular/commit/57457fb)) + + + + +# [9.0.0-next.8](https://github.com/angular/angular/compare/9.0.0-next.7...9.0.0-next.8) (2019-09-25) + + +### Bug Fixes + +* **ivy:** ensure `window.ng.getDebugNode` returns debug info for component elements ([#32780](https://github.com/angular/angular/issues/32780)) ([5651fa3](https://github.com/angular/angular/commit/5651fa3)) +* **ivy:** ensure multiple map-based bindings do not skip intermediate values ([#32774](https://github.com/angular/angular/issues/32774)) ([86fd571](https://github.com/angular/angular/commit/86fd571)) + + +### Features + +* **language-service:** expose determining the NgModule of a Directive ([#32710](https://github.com/angular/angular/issues/32710)) ([2846505](https://github.com/angular/angular/commit/2846505)), closes [#32565](https://github.com/angular/angular/issues/32565) + + +### Performance Improvements + +* **ivy:** remove extra SafeStyle detection code ([#32775](https://github.com/angular/angular/issues/32775)) ([52552b0](https://github.com/angular/angular/commit/52552b0)) + + + + +## [8.2.8](https://github.com/angular/angular/compare/8.2.7...8.2.8) (2019-09-25) + +This release contains various API docs improvements. + + + + +# [9.0.0-next.7](https://github.com/angular/angular/compare/9.0.0-next.6...9.0.0-next.7) (2019-09-18) + + +### Bug Fixes + +* **bazel:** ng_package(data) should support non-text files ([#32721](https://github.com/angular/angular/issues/32721)) ([df1c456](https://github.com/angular/angular/commit/df1c456)) +* **compiler-cli:** fix typo in diagnostic template info. ([#32684](https://github.com/angular/angular/issues/32684)) ([f6d6667](https://github.com/angular/angular/commit/f6d6667)), closes [#32662](https://github.com/angular/angular/issues/32662) +* **core:** initialize global ngDevMode without toplevel side effects ([#32079](https://github.com/angular/angular/issues/32079)) ([5f095a5](https://github.com/angular/angular/commit/5f095a5)), closes [#31595](https://github.com/angular/angular/issues/31595) +* **core:** make injector.get() return default value with InjectFlags.Self flag on ([#27739](https://github.com/angular/angular/issues/27739)) ([0477bfc](https://github.com/angular/angular/commit/0477bfc)), closes [#27729](https://github.com/angular/angular/issues/27729) +* **ivy:** avoid unnecessary i18n instructions generation for with structural directives ([#32623](https://github.com/angular/angular/issues/32623)) ([5328bb2](https://github.com/angular/angular/commit/5328bb2)) +* **ivy:** correct debug array names ([#32691](https://github.com/angular/angular/issues/32691)) ([52a6da0](https://github.com/angular/angular/commit/52a6da0)) +* **ivy:** DebugNode throws exceptions when querying some properties ([#32622](https://github.com/angular/angular/issues/32622)) ([bfb3995](https://github.com/angular/angular/commit/bfb3995)) +* **ivy:** ensure that `window.ng` utilities are published when NgModules are used ([#32725](https://github.com/angular/angular/issues/32725)) ([a0d04c6](https://github.com/angular/angular/commit/a0d04c6)) +* **ivy:** i18n - start generated placeholder name at `PH` ([#32493](https://github.com/angular/angular/issues/32493)) ([f1b1de9](https://github.com/angular/angular/commit/f1b1de9)) +* **ivy:** i18n - update the compiler to output `MessageId`s ([#32594](https://github.com/angular/angular/issues/32594)) ([b741a1c](https://github.com/angular/angular/commit/b741a1c)) +* **ivy:** i18n - use `MessageId` for matching translations ([#32594](https://github.com/angular/angular/issues/32594)) ([357aa4a](https://github.com/angular/angular/commit/357aa4a)) +* **language-service:** Lazily instantiate MetadataResolver ([#32631](https://github.com/angular/angular/issues/32631)) ([1771d6f](https://github.com/angular/angular/commit/1771d6f)) +* **language-service:** Use tsLSHost.fileExists() to resolve modules ([#32642](https://github.com/angular/angular/issues/32642)) ([bbb2798](https://github.com/angular/angular/commit/bbb2798)) +* **ngcc:** consistently use outer declaration for classes ([#32539](https://github.com/angular/angular/issues/32539)) ([373e133](https://github.com/angular/angular/commit/373e133)), closes [#32078](https://github.com/angular/angular/issues/32078) +* **ngcc:** correctly read static properties for aliased classes ([#32619](https://github.com/angular/angular/issues/32619)) ([c4e039a](https://github.com/angular/angular/commit/c4e039a)), closes [#32539](https://github.com/angular/angular/issues/32539) [#31791](https://github.com/angular/angular/issues/31791) +* **ngcc:** resolve imports in `.d.ts` files for UMD/CommonJS bundles ([#32619](https://github.com/angular/angular/issues/32619)) ([3c7da76](https://github.com/angular/angular/commit/3c7da76)), closes [#31791](https://github.com/angular/angular/issues/31791) +* **ngcc:** support UMD global factory in comma lists ([#32709](https://github.com/angular/angular/issues/32709)) ([e5a3de5](https://github.com/angular/angular/commit/e5a3de5)) + + +### Features + +* **bazel:** support ts_library targets as entry-points for ng_package ([#32610](https://github.com/angular/angular/issues/32610)) ([217db9b](https://github.com/angular/angular/commit/217db9b)) +* **core:** add dynamic queries schematic ([#32231](https://github.com/angular/angular/issues/32231)) ([f5982fd](https://github.com/angular/angular/commit/f5982fd)) +* **core:** Mark TestBed.get as deprecated ([#32406](https://github.com/angular/angular/issues/32406)) ([a85eccd](https://github.com/angular/angular/commit/a85eccd)), closes [#32200](https://github.com/angular/angular/issues/32200) [#26491](https://github.com/angular/angular/issues/26491) +* **ivy:** expose `window.ng.getDebugNode` helper ([#32727](https://github.com/angular/angular/issues/32727)) ([4726ac2](https://github.com/angular/angular/commit/4726ac2)) +* **ivy:** i18n - add syntax support for `$localize` metadata block ([#32594](https://github.com/angular/angular/issues/32594)) ([c7abb7d](https://github.com/angular/angular/commit/c7abb7d)) +* **ivy:** i18n - reorganize entry-points for better reuse ([#32488](https://github.com/angular/angular/issues/32488)) ([2bf5606](https://github.com/angular/angular/commit/2bf5606)) +* **language-service:** enable logging on TypeScriptHost ([#32645](https://github.com/angular/angular/issues/32645)) ([e82f56b](https://github.com/angular/angular/commit/e82f56b)) +* **language-service:** provide diagnostic for invalid templateUrls ([#32586](https://github.com/angular/angular/issues/32586)) ([adeee0f](https://github.com/angular/angular/commit/adeee0f)), closes [#32564](https://github.com/angular/angular/issues/32564) +* **language-service:** provide diagnostics for invalid styleUrls ([#32674](https://github.com/angular/angular/issues/32674)) ([4c168ed](https://github.com/angular/angular/commit/4c168ed)), closes [#32564](https://github.com/angular/angular/issues/32564) + + +### Performance Improvements + +* **ivy:** avoid megamorphic reads during property binding ([#32574](https://github.com/angular/angular/issues/32574)) ([fcdd068](https://github.com/angular/angular/commit/fcdd068)) +* **ivy:** avoid repeated lview reads in pipe instructions ([#32633](https://github.com/angular/angular/issues/32633)) ([73cb581](https://github.com/angular/angular/commit/73cb581)) +* **ivy:** avoid repeated LView reads in property instructions ([#32681](https://github.com/angular/angular/issues/32681)) ([e6ed4a2](https://github.com/angular/angular/commit/e6ed4a2)) +* **ivy:** avoid unnecessary DOM reads in styling instructions ([#32716](https://github.com/angular/angular/issues/32716)) ([05e1b3b](https://github.com/angular/angular/commit/05e1b3b)) +* **ivy:** binding update benchmark ([#32574](https://github.com/angular/angular/issues/32574)) ([ea378a9](https://github.com/angular/angular/commit/ea378a9)) +* **ivy:** convert all node-based benchmark to use a testing harness ([#32699](https://github.com/angular/angular/issues/32699)) ([1748aeb](https://github.com/angular/angular/commit/1748aeb)) +* **ivy:** guard listening to outputs with isDirectiveHost ([#32495](https://github.com/angular/angular/issues/32495)) ([527ce3b](https://github.com/angular/angular/commit/527ce3b)) +* **ivy:** initialise TNode inputs / outputs on the first creation pass ([#32608](https://github.com/angular/angular/issues/32608)) ([ad178c5](https://github.com/angular/angular/commit/ad178c5)) +* **ivy:** introduce benchmark for listeners registration ([#32495](https://github.com/angular/angular/issues/32495)) ([024765b](https://github.com/angular/angular/commit/024765b)) +* **ivy:** limit TNode.outputs reads ([#32495](https://github.com/angular/angular/issues/32495)) ([51292e2](https://github.com/angular/angular/commit/51292e2)) +* **ivy:** run the expandng rows benchmark with es2015 ([#32716](https://github.com/angular/angular/issues/32716)) ([3ace25f](https://github.com/angular/angular/commit/3ace25f)) +* **language-service:** keep analyzedModules cache when source files don't change ([#32562](https://github.com/angular/angular/issues/32562)) ([4f03323](https://github.com/angular/angular/commit/4f03323)) + + +### BREAKING CHANGES + +* **ivy:** Translations (loaded via the `loadTranslations()` function) must now use +`MessageId` for the translation key rather than the previous `SourceMessage` +string. +* **ivy:** To attach the `$localize` function to the global scope import from +`@angular/localize/init`. Previously it was `@angular/localize`. To access the `loadTranslations()` and `clearTranslations()` functions, +import from `@angular/localize`. Previously it was `@angular/localize/run_time`. + + +### DEPRECATIONS + +* **core:** TestBed.get function is marked as deprecated, use TestBed.inject instead. + + + + +## [8.2.7](https://github.com/angular/angular/compare/8.2.6...8.2.7) (2019-09-18) + + +### Bug Fixes + +* **bazel:** ng_package(data) should support non-text files ([#32721](https://github.com/angular/angular/issues/32721)) ([ba1ef6b](https://github.com/angular/angular/commit/ba1ef6b)) +* **compiler-cli:** fix typo in diagnostic template info. ([#32684](https://github.com/angular/angular/issues/32684)) ([947c076](https://github.com/angular/angular/commit/947c076)), closes [#32662](https://github.com/angular/angular/issues/32662) +* **language-service:** cache module resolution ([#32483](https://github.com/angular/angular/issues/32483)) ([1c5b157](https://github.com/angular/angular/commit/1c5b157)) + + + + +# [9.0.0-next.6](https://github.com/angular/angular/compare/9.0.0-next.5...9.0.0-next.6) (2019-09-11) + + +### Bug Fixes + +* **core:** improve the "missing `$localize`" error message ([#32491](https://github.com/angular/angular/issues/32491)) ([a9ff48e](https://github.com/angular/angular/commit/a9ff48e)) +* **ivy:** capture template source mapping details during preanalysis ([#32544](https://github.com/angular/angular/issues/32544)) ([a64eded](https://github.com/angular/angular/commit/a64eded)), closes [#32538](https://github.com/angular/angular/issues/32538) +* **ivy:** handle expressions in i18n attributes properly ([#32309](https://github.com/angular/angular/issues/32309)) ([f00d033](https://github.com/angular/angular/commit/f00d033)) +* **ivy:** i18n - do not generate jsdoc comments for `$localize` ([#32473](https://github.com/angular/angular/issues/32473)) ([a731119](https://github.com/angular/angular/commit/a731119)) +* **ivy:** maintain coalesced listeners order ([#32484](https://github.com/angular/angular/issues/32484)) ([098feec](https://github.com/angular/angular/commit/098feec)) +* **ivy:** match class and attribute value without case-sensitivity ([#32548](https://github.com/angular/angular/issues/32548)) ([ded5724](https://github.com/angular/angular/commit/ded5724)) +* **ivy:** node placed in incorrect order inside ngFor with ng-container ([#32324](https://github.com/angular/angular/issues/32324)) ([da42a76](https://github.com/angular/angular/commit/da42a76)) +* **ivy:** restore global state after running refreshView ([#32521](https://github.com/angular/angular/issues/32521)) ([a1beba4](https://github.com/angular/angular/commit/a1beba4)) +* **ivy:** template compiler should render correct $localize placeholder names ([#32509](https://github.com/angular/angular/issues/32509)) ([ea6a2e9](https://github.com/angular/angular/commit/ea6a2e9)) +* **ivy:** unable to bind to properties that start with class or style ([#32421](https://github.com/angular/angular/issues/32421)) ([62d92f8](https://github.com/angular/angular/commit/62d92f8)), closes [#32310](https://github.com/angular/angular/issues/32310) +* **ivy:** unable to override ComponentFactoryResolver provider in tests ([#32512](https://github.com/angular/angular/issues/32512)) ([2124588](https://github.com/angular/angular/commit/2124588)) +* **ivy:** warn instead of throwing for unknown properties ([#32463](https://github.com/angular/angular/issues/32463)) ([bc061b7](https://github.com/angular/angular/commit/bc061b7)) +* **language-service:** Return empty external files during project initialization ([#32519](https://github.com/angular/angular/issues/32519)) ([a65d3fa](https://github.com/angular/angular/commit/a65d3fa)) +* **language-service:** Use module resolution cache ([#32479](https://github.com/angular/angular/issues/32479)) ([6052b12](https://github.com/angular/angular/commit/6052b12)) +* **ngcc:** only back up the original `prepublishOnly` script and not the overwritten one ([#32427](https://github.com/angular/angular/issues/32427)) ([38359b1](https://github.com/angular/angular/commit/38359b1)) +* **service-worker:** keep serving clients on older versions if latest is invalidated ([#31865](https://github.com/angular/angular/issues/31865)) ([bda2b4e](https://github.com/angular/angular/commit/bda2b4e)) + + +### Code Refactoring + +* **bazel:** remove [@angular](https://github.com/angular)/bazel protractor rule now provided by [@bazel](https://github.com/bazel)/protractor ([#32485](https://github.com/angular/angular/issues/32485)) ([9448828](https://github.com/angular/angular/commit/9448828)) + + +### Features + +* **language-service:** add definitions for styleUrls ([#32464](https://github.com/angular/angular/issues/32464)) ([a391aeb](https://github.com/angular/angular/commit/a391aeb)) +* **language-service:** add script to rebuild, refresh Angular dist ([#32515](https://github.com/angular/angular/issues/32515)) ([1716b91](https://github.com/angular/angular/commit/1716b91)) +* **service-worker:** recover from `EXISTING_CLIENTS_ONLY` mode when there is a valid update ([#31865](https://github.com/angular/angular/issues/31865)) ([094538c](https://github.com/angular/angular/commit/094538c)), closes [#31109](https://github.com/angular/angular/issues/31109) + + +### Performance Improvements + +* **ivy:** check for animation synthetic props in dev mode only ([#32578](https://github.com/angular/angular/issues/32578)) ([7280710](https://github.com/angular/angular/commit/7280710)) +* **ivy:** introduce a node-based micro-benchmarks harness ([#32510](https://github.com/angular/angular/issues/32510)) ([2895edc](https://github.com/angular/angular/commit/2895edc)) +* **ivy:** replace select instruction with advance ([#32516](https://github.com/angular/angular/issues/32516)) ([664e001](https://github.com/angular/angular/commit/664e001)) +* **ivy:** run tree benchmark with bundles and ngDevMode off ([#32558](https://github.com/angular/angular/issues/32558)) ([c3a1ef2](https://github.com/angular/angular/commit/c3a1ef2)) +* **ngcc:** process tasks in parallel in async mode ([#32427](https://github.com/angular/angular/issues/32427)) ([e36e6c8](https://github.com/angular/angular/commit/e36e6c8)) + + +### BREAKING CHANGES + +* **bazel:** Angular bazel users using protractor_web_test_suite from @angular/bazel npm package should now switch to the @bazel/protractor npm package. + +This should impact very few users and the user's that are impacted have a very easy upgrade path to switch to fetching the protractor_web_test_suite rule via the @bazel/protractor npm package. + + + + +## [8.2.6](https://github.com/angular/angular/compare/8.2.5...8.2.6) (2019-09-11) + +This release contains various API docs improvements. + + + + +# [9.0.0-next.5](https://github.com/angular/angular/compare/9.0.0-next.4...9.0.0-next.5) (2019-09-04) + + +### Bug Fixes + +* **ivy:** add missing closure extern for \$localize ([#32460](https://github.com/angular/angular/issues/32460)) ([e8f9ba4](https://github.com/angular/angular/commit/e8f9ba4)) +* **ivy:** ensure binding ordering doesn't mess up when a `NO_CHANGE` value is encountered ([#32143](https://github.com/angular/angular/issues/32143)) ([7cc4225](https://github.com/angular/angular/commit/7cc4225)) +* **ivy:** i18n - handle translated text containing HTML comments ([#32475](https://github.com/angular/angular/issues/32475)) ([5d8eb74](https://github.com/angular/angular/commit/5d8eb74)) +* **ivy:** ngcc - improve the "ngcc version changed" error message ([#32396](https://github.com/angular/angular/issues/32396)) ([d5101df](https://github.com/angular/angular/commit/d5101df)) +* **ivy:** Prevent errors when querying for elements outside Angular context ([#32361](https://github.com/angular/angular/issues/32361)) ([260217a](https://github.com/angular/angular/commit/260217a)) +* **language-service:** Create DirectiveKind enum ([#32376](https://github.com/angular/angular/issues/32376)) ([852afb3](https://github.com/angular/angular/commit/852afb3)) +* **language-service:** Invalidate Reflector caches when program changes ([#32357](https://github.com/angular/angular/issues/32357)) ([97fc45f](https://github.com/angular/angular/commit/97fc45f)) +* update all files/directories owned by DevInfra to new DevInfra Framework team alias ([#32247](https://github.com/angular/angular/issues/32247)) ([3758978](https://github.com/angular/angular/commit/3758978)) +* **language-service:** re-add regressed templateUrl tests ([#32438](https://github.com/angular/angular/issues/32438)) ([1ed3531](https://github.com/angular/angular/commit/1ed3531)), closes [#32378](https://github.com/angular/angular/issues/32378) +* **language-service:** Use ts.CompletionEntry for completions ([#32375](https://github.com/angular/angular/issues/32375)) ([f6e88cd](https://github.com/angular/angular/commit/f6e88cd)) +* **ngcc:** handle compilation diagnostics ([#31996](https://github.com/angular/angular/issues/31996)) ([f7471ee](https://github.com/angular/angular/commit/f7471ee)), closes [#31977](https://github.com/angular/angular/issues/31977) +* **common:** HttpParams fromObject accepts ReadonlyArray ([#31072](https://github.com/angular/angular/issues/31072)) ([f5bec3f](https://github.com/angular/angular/commit/f5bec3f)), closes [#28452](https://github.com/angular/angular/issues/28452) + + +### Features + +* **bazel:** update to the latest `[@microsoft](https://github.com/microsoft)/api-extractor` ([#32185](https://github.com/angular/angular/issues/32185)) ([350ea47](https://github.com/angular/angular/commit/350ea47)) +* **core:** Adds DI support for `providedIn: 'platform'|'any'` ([#32154](https://github.com/angular/angular/issues/32154)) ([77c382c](https://github.com/angular/angular/commit/77c382c)) +* **core:** Introduce TestBed.inject to replace TestBed.get ([#32200](https://github.com/angular/angular/issues/32200)) ([3aba7eb](https://github.com/angular/angular/commit/3aba7eb)), closes [#26491](https://github.com/angular/angular/issues/26491) [#29905](https://github.com/angular/angular/issues/29905) +* **ivy:** implement `$localize()` global function ([#31609](https://github.com/angular/angular/issues/31609)) ([b21397b](https://github.com/angular/angular/commit/b21397b)) +* **language-service:** add definitions for templateUrl ([#32238](https://github.com/angular/angular/issues/32238)) ([46caf88](https://github.com/angular/angular/commit/46caf88)), closes [angular/vscode-ng-language-service#111](https://github.com/angular/vscode-ng-language-service/issues/111) + + +### Performance Improvements + +* **core:** Make `PlatformLocation` tree-shakable ([#32154](https://github.com/angular/angular/issues/32154)) ([1537791](https://github.com/angular/angular/commit/1537791)) +* **ivy:** add a micro benchmark for map-based style and class bindings ([#32401](https://github.com/angular/angular/issues/32401)) ([ba5e07e](https://github.com/angular/angular/commit/ba5e07e)) +* **ivy:** add a micro benchmark for style and class bindings ([#32401](https://github.com/angular/angular/issues/32401)) ([df8e675](https://github.com/angular/angular/commit/df8e675)) +* **ivy:** add element and text creation benchmark ([#32342](https://github.com/angular/angular/issues/32342)) ([85864ed](https://github.com/angular/angular/commit/85864ed)) +* **ivy:** guard directive-related operations with a TNode flag ([#32445](https://github.com/angular/angular/issues/32445)) ([641c5c1](https://github.com/angular/angular/commit/641c5c1)) +* **ivy:** properly initialise global state in the element_text_create benchmark ([#32397](https://github.com/angular/angular/issues/32397)) ([8dc3f36](https://github.com/angular/angular/commit/8dc3f36)) +* **ivy:** remove renderStringify calls for text nodes creation ([#32342](https://github.com/angular/angular/issues/32342)) ([a1e91b0](https://github.com/angular/angular/commit/a1e91b0)) +* **ivy:** remove repeated memory read / write in addComponentLogic ([#32339](https://github.com/angular/angular/issues/32339)) ([581b837](https://github.com/angular/angular/commit/581b837)) +* **ivy:** run registerPostOrderHooks in the first template pass only ([#32342](https://github.com/angular/angular/issues/32342)) ([fac066e](https://github.com/angular/angular/commit/fac066e)) + + +### Reverts + +* docs: create Issue and Pull Request markdown doc, explaining automatic locking policy ([#32405](https://github.com/angular/angular/issues/32405)) ([43619fc](https://github.com/angular/angular/commit/43619fc)) + + +### BREAKING CHANGES + +* **ivy:** This commit removes the public export of `hasBeenProcessed()`. + +This was exported to be availble to the CLI integration but was never +used. The change to the function signature is a breaking change in itself +so we remove the function altogether to simplify and lower the public +API surface going forward. +* **core:** Injector.get now accepts abstract classes to return +type-safe values. Previous implementation returned `any` through the +deprecated implementation. + + + + +## [8.2.5](https://github.com/angular/angular/compare/8.2.4...8.2.5) (2019-09-04) + +This release contains various API docs improvements. + + + +### Bug Fixes + +* **common:** HttpParams fromObject accepts ReadonlyArray ([#31072](https://github.com/angular/angular/issues/31072)) ([b3ea698](https://github.com/angular/angular/commit/b3ea698)), closes [#28452](https://github.com/angular/angular/issues/28452) + + + +# [9.0.0-next.4](https://github.com/angular/angular/compare/9.0.0-next.3...9.0.0-next.4) (2019-08-28) + + +### Bug Fixes + +* **ivy:** debug node names should match user declaration ([#32328](https://github.com/angular/angular/issues/32328)) ([14feb56](https://github.com/angular/angular/commit/14feb56)) +* **ivy:** ngtsc throws if "flatModuleOutFile" is set to null ([#32235](https://github.com/angular/angular/issues/32235)) ([4f7c971](https://github.com/angular/angular/commit/4f7c971)) +* **ivy:** reset binding index before executing a template in `refreshView` call ([#32201](https://github.com/angular/angular/issues/32201)) ([6b245a3](https://github.com/angular/angular/commit/6b245a3)) +* **ngcc:** do not analyze dependencies for non Angular entry-points ([#32303](https://github.com/angular/angular/issues/32303)) ([e563d77](https://github.com/angular/angular/commit/e563d77)), closes [#32302](https://github.com/angular/angular/issues/32302) + + +### Features + +* **core:** add undecorated classes with decorated fields schematic ([#32130](https://github.com/angular/angular/issues/32130)) ([904a201](https://github.com/angular/angular/commit/904a201)) +* **ivy:** use the schema registry to check DOM bindings ([#32171](https://github.com/angular/angular/issues/32171)) ([0677cf0](https://github.com/angular/angular/commit/0677cf0)) + + +### Performance Improvements + +* **ivy:** minimise writes to the lView[BINDING_INDEX] / binding root ([#32263](https://github.com/angular/angular/issues/32263)) ([e3422e0](https://github.com/angular/angular/commit/e3422e0)) +* **ivy:** store binding metadata in the ngDevMode only ([#32317](https://github.com/angular/angular/issues/32317)) ([0874bf4](https://github.com/angular/angular/commit/0874bf4)) + + + + + +## [8.2.4](https://github.com/angular/angular/compare/8.2.3...8.2.4) (2019-08-28) + +This release contains various API docs improvements. + + + + +# [9.0.0-next.3](https://github.com/angular/angular/compare/9.0.0-next.2...9.0.0-next.3) (2019-08-21) + + +### Bug Fixes + +* **bazel:** pin `[@microsoft](https://github.com/microsoft)/api-extractor` ([#32187](https://github.com/angular/angular/issues/32187)) ([5da5ca5](https://github.com/angular/angular/commit/5da5ca5)) +* **common:** update $locationShim to notify onChange listeners before emitting AngularJS events ([#32037](https://github.com/angular/angular/issues/32037)) ([5064dc7](https://github.com/angular/angular/commit/5064dc7)) +* **compiler:** return enableIvy true when using `readConfiguration` ([#32234](https://github.com/angular/angular/issues/32234)) ([424ab48](https://github.com/angular/angular/commit/424ab48)) +* **ivy:** get name directly from nativeNode ([#32198](https://github.com/angular/angular/issues/32198)) ([3dbc4ab](https://github.com/angular/angular/commit/3dbc4ab)) +* **ivy:** handle empty bindings in template type checker ([#31594](https://github.com/angular/angular/issues/31594)) ([0db1b5d](https://github.com/angular/angular/commit/0db1b5d)), closes [#30076](https://github.com/angular/angular/issues/30076) [#30929](https://github.com/angular/angular/issues/30929) +* **ivy:** in ngcc, handle inline exports in commonjs code ([#32129](https://github.com/angular/angular/issues/32129)) ([02bab8c](https://github.com/angular/angular/commit/02bab8c)) +* **ivy:** ngcc should only index .d.ts exports within the package ([#32129](https://github.com/angular/angular/issues/32129)) ([964d726](https://github.com/angular/angular/commit/964d726)) +* **ivy:** ngTemplateOutlet error when switching between null and template value ([#32160](https://github.com/angular/angular/issues/32160)) ([c2868de](https://github.com/angular/angular/commit/c2868de)), closes [#32060](https://github.com/angular/angular/issues/32060) +* **ivy:** run template type-checking for all components ([#31952](https://github.com/angular/angular/issues/31952)) ([bfc26bc](https://github.com/angular/angular/commit/bfc26bc)) +* **language-service:** Instantiate MetadataResolver once ([#32145](https://github.com/angular/angular/issues/32145)) ([6a0b1d5](https://github.com/angular/angular/commit/6a0b1d5)) +* **language-service:** Remove 'context' used for module resolution ([#32015](https://github.com/angular/angular/issues/32015)) ([a91ab15](https://github.com/angular/angular/commit/a91ab15)) +* **ngcc:** handle deep imports that already have an extension ([#32181](https://github.com/angular/angular/issues/32181)) ([4bbf16e](https://github.com/angular/angular/commit/4bbf16e)), closes [#32097](https://github.com/angular/angular/issues/32097) +* **ngcc:** ignore format properties that exist but are undefined ([#32205](https://github.com/angular/angular/issues/32205)) ([f8b995d](https://github.com/angular/angular/commit/f8b995d)), closes [#32052](https://github.com/angular/angular/issues/32052) [#32188](https://github.com/angular/angular/issues/32188) + + +### Features + +* **core:** add undecorated classes migration schematic ([#31650](https://github.com/angular/angular/issues/31650)) ([024c31d](https://github.com/angular/angular/commit/024c31d)) +* **forms:** formControlName also accepts a number ([#30606](https://github.com/angular/angular/issues/30606)) ([628b0c1](https://github.com/angular/angular/commit/628b0c1)) +* **compiler:** allow selector-less directives as base classes in View Engine ([#31379](https://github.com/angular/angular/issues/31379)) ([4055150](https://github.com/angular/angular/commit/4055150)) +* **ivy:** support selector-less directive as base classes in Ivy ([#32125](https://github.com/angular/angular/issues/32125)) ([cfed0c0](https://github.com/angular/angular/commit/cfed0c0)), closes [#31379](https://github.com/angular/angular/issues/31379) +* **ivy:** make the Ivy compiler the default for ngc ([#32219](https://github.com/angular/angular/issues/32219)) ([ec4381d](https://github.com/angular/angular/commit/ec4381d)) +* **ivy:** convert all ngtsc diagnostics to ts.Diagnostics ([#31952](https://github.com/angular/angular/issues/31952)) ([0287b23](https://github.com/angular/angular/commit/0287b23)) + + +### Performance Improvements + +* **core:** make sanitization tree-shakable in Ivy mode ([#31934](https://github.com/angular/angular/issues/31934)) ([2e4d17f](https://github.com/angular/angular/commit/2e4d17f)) +* **ivy:** auto-call select(0) for non-empty views only ([#32131](https://github.com/angular/angular/issues/32131)) ([4d549f6](https://github.com/angular/angular/commit/4d549f6)) +* **ivy:** avoid first template pass checks during view creation ([#32120](https://github.com/angular/angular/issues/32120)) ([4c3b791](https://github.com/angular/angular/commit/4c3b791)) +* **ivy:** avoid for-of loops at runtime ([#32157](https://github.com/angular/angular/issues/32157)) ([abb44f7](https://github.com/angular/angular/commit/abb44f7)) +* **ivy:** improve NaN checks in change detection ([#32212](https://github.com/angular/angular/issues/32212)) ([53bfa7c](https://github.com/angular/angular/commit/53bfa7c)) +* **ivy:** interpolation micro-benchmark ([#32104](https://github.com/angular/angular/issues/32104)) ([be665d8](https://github.com/angular/angular/commit/be665d8)) +* **ivy:** noop change detection micro-benchmark ([#32104](https://github.com/angular/angular/issues/32104)) ([c422c72](https://github.com/angular/angular/commit/c422c72)) +* don't create holey arrays ([#32155](https://github.com/angular/angular/issues/32155)) ([6477057](https://github.com/angular/angular/commit/6477057)) +* **ivy:** read selected index only when need in prop bindings ([#32212](https://github.com/angular/angular/issues/32212)) ([53f33c1](https://github.com/angular/angular/commit/53f33c1)) +* **ivy:** split hooks processing into init and check phases ([#32131](https://github.com/angular/angular/issues/32131)) ([1062960](https://github.com/angular/angular/commit/1062960)) +* **ivy:** split view processing into render (create) and refresh (update) pass ([#32020](https://github.com/angular/angular/issues/32020)) ([b9dfe66](https://github.com/angular/angular/commit/b9dfe66)) + + +### BREAKING CHANGES + +Angular now compiles with Ivy by default ([#32219](https://github.com/angular/angular/issues/32219)) ([ec4381d](https://github.com/angular/angular/commit/ec4381d)). + +If you aren't familiar with Ivy, read our [blog post about the Ivy preview](https://blog.angular.io/its-time-for-the-compatibility-opt-in-preview-of-ivy-38f3542a282f?gi=8bfeb44b05c) and see the list of changes [here](https://docs.google.com/document/d/1Dije0AsJ0PxL3NaeNPxpYDeapj30b_QC0xfeIvIIzgg/preview). + +* **ivy:** make Hammer support tree-shakable. Previously, in Ivy applications, Hammer providers were included by default. With this commit, apps that want Hammer support must import `HammerModule`in their root module. ([#32203](https://github.com/angular/angular/issues/32203)) ([de8ebbd](https://github.com/angular/angular/commit/de8ebbd)) + + + + +## [8.2.3](https://github.com/angular/angular/compare/8.2.2...8.2.3) (2019-08-21) + + +### Bug Fixes + +* **bazel:** pin `[@microsoft](https://github.com/microsoft)/api-extractor` ([#32187](https://github.com/angular/angular/issues/32187)) ([a7b9478](https://github.com/angular/angular/commit/a7b9478)) + + + + +# [9.0.0-next.2](https://github.com/angular/angular/compare/9.0.0-next.1...9.0.0-next.2) (2019-08-12) + + +### Bug Fixes + +* **bazel:** disable treeshaking when generating FESM and UMD bundles ([#32069](https://github.com/angular/angular/issues/32069)) ([4f37487](https://github.com/angular/angular/commit/4f37487)) +* **compiler:** do not remove whitespace wrapping i18n expansions ([#31962](https://github.com/angular/angular/issues/31962)) ([0ddf0c4](https://github.com/angular/angular/commit/0ddf0c4)) +* **ivy:** reuse compilation scope for incremental template changes. ([#31932](https://github.com/angular/angular/issues/31932)) ([eb5412d](https://github.com/angular/angular/commit/eb5412d)), closes [#31654](https://github.com/angular/angular/issues/31654) + + + +### Performance Improvements + +* **ivy:** don't read global state when interpolated values don't change ([#32093](https://github.com/angular/angular/issues/32093)) ([6eb9c2f](https://github.com/angular/angular/commit/6eb9c2f)) + + + + +## [8.2.2](https://github.com/angular/angular/compare/8.2.1...8.2.2) (2019-08-12) + + +### Bug Fixes + +* **bazel:** disable treeshaking when generating FESM and UMD bundles ([#32069](https://github.com/angular/angular/issues/32069)) ([3420d29](https://github.com/angular/angular/commit/3420d29)) + + + +# [9.0.0-next.1](https://github.com/angular/angular/compare/9.0.0-next.0...9.0.0-next.1) (2019-08-08) + + +### Bug Fixes + +* **language-service:** getSourceFile() should only be called on TS files ([#31920](https://github.com/angular/angular/issues/31920)) ([e8b8f6d](https://github.com/angular/angular/commit/e8b8f6d)) +* **language-service:** Make Definition and QuickInfo compatible with TS LS ([#31972](https://github.com/angular/angular/issues/31972)) ([a8e2ee1](https://github.com/angular/angular/commit/a8e2ee1)) +* **upgrade:** compile downgraded components synchronously (if possible) ([#31840](https://github.com/angular/angular/issues/31840)) ([c1ae612](https://github.com/angular/angular/commit/c1ae612)), closes [#27217](https://github.com/angular/angular/issues/27217) [#30330](https://github.com/angular/angular/issues/30330) + + + + +## [8.2.1](https://github.com/angular/angular/compare/8.2.0...8.2.1) (2019-08-08) + + +### Bug Fixes + +* **upgrade:** compile downgraded components synchronously (if possible) ([#31840](https://github.com/angular/angular/issues/31840)) ([04ebd59](https://github.com/angular/angular/commit/04ebd59)), closes [#27217](https://github.com/angular/angular/issues/27217) [#30330](https://github.com/angular/angular/issues/30330) + + + + +# [9.0.0-next.0](https://github.com/angular/angular/compare/8.2.0-next.2...9.0.0-next.0) (2019-07-31) + +* Ivy related improvements and fixes + + + +# [8.2.0](https://github.com/angular/angular/compare/8.2.0-rc.0...8.2.0) (2019-07-31) + + +### Features + +* **core:** TypeScript 3.5 support ([#31615](https://github.com/angular/angular/issues/31615)) ([6ece7db](https://github.com/angular/angular/commit/6ece7db)) +* **core:** add automatic migration from Renderer to Renderer2 ([#30936](https://github.com/angular/angular/issues/30936)) ([c095597](https://github.com/angular/angular/commit/c095597)) +* **bazel:** compile targets used for indexing by Kythe with Ivy ([#31786](https://github.com/angular/angular/issues/31786)) ([82055b2](https://github.com/angular/angular/commit/82055b2)) +* **upgrade:** support $element in upgraded component template/templateUrl functions ([#31637](https://github.com/angular/angular/issues/31637)) ([29e1c53](https://github.com/angular/angular/commit/29e1c53)) +* **bazel:** allow passing a custom bazel compiler host to ngc compile ([#31341](https://github.com/angular/angular/issues/31341)) ([a29dc96](https://github.com/angular/angular/commit/a29dc96)) +* **bazel:** allow passing and rewriting an old bazel host ([#31381](https://github.com/angular/angular/issues/31381)) ([11a208f](https://github.com/angular/angular/commit/11a208f)), closes [#31341](https://github.com/angular/angular/issues/31341) + + +### Performance Improvements + +* **compiler:** avoid copying from prototype while cloning an object ([#31638](https://github.com/angular/angular/issues/31638)) ([24ca582](https://github.com/angular/angular/commit/24ca582)), closes [#31627](https://github.com/angular/angular/issues/31627) + +### Bug Fixes + +* **core:** DebugElement.listeners not cleared on destroy ([#31820](https://github.com/angular/angular/issues/31820)) ([46b160e](https://github.com/angular/angular/commit/46b160e)) + * **bazel:** increase memory limit of ngc under bazel from 2 to 4 GB ([#31784](https://github.com/angular/angular/issues/31784)) ([5a8eb92](https://github.com/angular/angular/commit/5a8eb92)) +* **core:** allow Z variations of CSS transforms in sanitizer ([#29264](https://github.com/angular/angular/issues/29264)) ([78e7fdd](https://github.com/angular/angular/commit/78e7fdd)) +* **elements:** handle falsy initial value ([#31604](https://github.com/angular/angular/issues/31604)) ([7151eae](https://github.com/angular/angular/commit/7151eae)), closes [angular/angular#30834](https://github.com/angular/angular/issues/30834) +* **platform-browser:** debug element query predicates not compatible with strictFunctionTypes ([#30993](https://github.com/angular/angular/issues/30993)) ([10a1e19](https://github.com/angular/angular/commit/10a1e19)) +* use the correct WTF array to iterate over ([#31208](https://github.com/angular/angular/issues/31208)) ([9204de9](https://github.com/angular/angular/commit/9204de9)) +* **bazel:** pass custom bazel compiler host rather than rewriting one ([#31496](https://github.com/angular/angular/issues/31496)) ([0c61a35](https://github.com/angular/angular/commit/0c61a35)) +* **compiler-cli:** Return original sourceFile instead of redirected sourceFile from getSourceFile ([#26036](https://github.com/angular/angular/issues/26036)) ([3166cff](https://github.com/angular/angular/commit/3166cff)), closes [#22524](https://github.com/angular/angular/issues/22524) +* **language-service:** Eagarly initialize data members ([#31577](https://github.com/angular/angular/issues/31577)) ([0110de2](https://github.com/angular/angular/commit/0110de2)) +* **bazel:** revert location of xi18n outputs to bazel-genfiles ([#31410](https://github.com/angular/angular/issues/31410)) ([1d3e227](https://github.com/angular/angular/commit/1d3e227)) +* **compiler:** give ASTWithSource its own visit method ([#31347](https://github.com/angular/angular/issues/31347)) ([6aaca21](https://github.com/angular/angular/commit/6aaca21)) +* **core:** handle `undefined` meta in `injectArgs` ([#31333](https://github.com/angular/angular/issues/31333)) ([80ccd6c](https://github.com/angular/angular/commit/80ccd6c)), closes [CLI #14888](https://github.com/angular/angular-cli/issues/14888) +* **service-worker:** cache opaque responses in data groups with `freshness` strategy ([#30977](https://github.com/angular/angular/issues/30977)) ([d7be38f](https://github.com/angular/angular/commit/d7be38f)), closes [#30968](https://github.com/angular/angular/issues/30968) +* **service-worker:** cache opaque responses when requests exceeds timeout threshold ([#30977](https://github.com/angular/angular/issues/30977)) ([93abc35](https://github.com/angular/angular/commit/93abc35)) + + + + +## [8.1.3](https://github.com/angular/angular/compare/8.1.2...8.1.3) (2019-07-26) + + +### Bug Fixes + +* **elements:** handle falsy initial value ([#31604](https://github.com/angular/angular/issues/31604)) ([434b796](https://github.com/angular/angular/commit/434b796)), closes [angular/angular#30834](https://github.com/angular/angular/issues/30834) + + +### Performance Improvements + +* **compiler:** avoid copying from prototype while cloning an object ([#31638](https://github.com/angular/angular/issues/31638)) ([1f3daa0](https://github.com/angular/angular/commit/1f3daa0)), closes [#31627](https://github.com/angular/angular/issues/31627) + + + + + +## [8.1.2](https://github.com/angular/angular/compare/8.1.0...8.1.2) (2019-07-17) + + +### Bug Fixes + +* use the correct WTF array to iterate over ([#31208](https://github.com/angular/angular/issues/31208)) ([4aed480](https://github.com/angular/angular/commit/4aed480)) +* **compiler-cli:** Return original sourceFile instead of redirected sourceFile from getSourceFile ([#26036](https://github.com/angular/angular/issues/26036)) ([13dbb98](https://github.com/angular/angular/commit/13dbb98)), closes [#22524](https://github.com/angular/angular/issues/22524) +* **core:** export provider interfaces that are part of the public API types ([#31377](https://github.com/angular/angular/issues/31377)) ([bebf089](https://github.com/angular/angular/commit/bebf089)), closes [/github.com/angular/angular/pull/31377#discussion_r299254408](https://github.com//github.com/angular/angular/pull/31377/issues/discussion_r299254408) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L365-L366](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L365-L366) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L283-L284](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L283-L284) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts#L23](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts/issues/L23) + + + +## [8.1.1](https://github.com/angular/angular/compare/8.1.0...8.1.1) (2019-07-10) + + +### Bug Fixes + +* **core:** export provider interfaces that are part of the public API types ([#31377](https://github.com/angular/angular/issues/31377)) ([bebf089](https://github.com/angular/angular/commit/bebf089)), closes [/github.com/angular/angular/pull/31377#discussion_r299254408](https://github.com//github.com/angular/angular/pull/31377/issues/discussion_r299254408) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L365-L366](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L365-L366) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L283-L284](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L283-L284) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts#L23](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts/issues/L23) + + + + +# [8.1.0](https://github.com/angular/angular/compare/8.1.0-rc.0...8.1.0) (2019-07-02) + + +### Bug Fixes + +* **core:** handle `undefined` meta in `injectArgs` ([#31333](https://github.com/angular/angular/issues/31333)) ([80ccd6c](https://github.com/angular/angular/commit/80ccd6c)), closes [CLI #14888](https://github.com/angular/angular-cli/issues/14888) +* **service-worker:** cache opaque responses in data groups with `freshness` strategy ([#30977](https://github.com/angular/angular/issues/30977)) ([b0c3453](https://github.com/angular/angular/commit/b0c3453)), closes [#30968](https://github.com/angular/angular/issues/30968) +* **service-worker:** cache opaque responses when requests exceeds timeout threshold ([#30977](https://github.com/angular/angular/issues/30977)) ([a9038ef](https://github.com/angular/angular/commit/a9038ef)) + + + + +# [8.1.0-rc.0](https://github.com/angular/angular/compare/8.1.0-next.3...8.1.0-rc.0) (2019-06-26) + + +### Bug Fixes + +* **bazel:** exclude all angular schematics folders from metadata build ([#31237](https://github.com/angular/angular/issues/31237)) ([16717fa](https://github.com/angular/angular/commit/16717fa)), closes [#31235](https://github.com/angular/angular/issues/31235) +* **bazel:** remove unsupported Css pre-processors from ng new ([#31234](https://github.com/angular/angular/issues/31234)) ([e83667a](https://github.com/angular/angular/commit/e83667a)), closes [#31209](https://github.com/angular/angular/issues/31209) +* **bazel:** update ng new schema to match the current ng new schema of [@schematics](https://github.com/schematics)/angular ([#31234](https://github.com/angular/angular/issues/31234)) ([805fc86](https://github.com/angular/angular/commit/805fc86)), closes [#31233](https://github.com/angular/angular/issues/31233) +* **compiler:** fix Elements not making a new ParseSourceSpan ([#31190](https://github.com/angular/angular/issues/31190)) ([7035f22](https://github.com/angular/angular/commit/7035f22)) +* **compiler:** stringify `Object.create(null)` tokens ([#16848](https://github.com/angular/angular/issues/16848)) ([5e53956](https://github.com/angular/angular/commit/5e53956)) +* **service-worker:** registration failed on Safari ([#31140](https://github.com/angular/angular/issues/31140)) ([a5dd4ed](https://github.com/angular/angular/commit/a5dd4ed)), closes [#31061](https://github.com/angular/angular/issues/31061) + + +### Features + +* **upgrade:** provide unit test helpers for wiring up injectors ([#16848](https://github.com/angular/angular/issues/16848)) ([3fb78aa](https://github.com/angular/angular/commit/3fb78aa)) + + + + +## [8.0.3](https://github.com/angular/angular/compare/8.0.2...8.0.3) (2019-06-26) + + +### Bug Fixes + +* **bazel:** exclude all angular schematics folders from metadata build ([#31237](https://github.com/angular/angular/issues/31237)) ([6bad2ca](https://github.com/angular/angular/commit/6bad2ca)), closes [#31235](https://github.com/angular/angular/issues/31235) +* **bazel:** remove unsupported Css pre-processors from ng new ([#31234](https://github.com/angular/angular/issues/31234)) ([980bcaf](https://github.com/angular/angular/commit/980bcaf)), closes [#31209](https://github.com/angular/angular/issues/31209) +* **bazel:** update ng new schema to match the current ng new schema of [@schematics](https://github.com/schematics)/angular ([#31234](https://github.com/angular/angular/issues/31234)) ([48f7f65](https://github.com/angular/angular/commit/48f7f65)), closes [#31233](https://github.com/angular/angular/issues/31233) +* **service-worker:** registration failed on Safari ([#31140](https://github.com/angular/angular/issues/31140)) ([f470e69](https://github.com/angular/angular/commit/f470e69)), closes [#31061](https://github.com/angular/angular/issues/31061) + + + + +# [8.1.0-next.3](https://github.com/angular/angular/compare/8.1.0-next.2...8.1.0-next.3) (2019-06-19) + + +### Bug Fixes + +* **bazel:** builder workspace should use nodejs v10.16.0 ([#31088](https://github.com/angular/angular/issues/31088)) ([a1fc4de](https://github.com/angular/angular/commit/a1fc4de)) +* **core:** temporarily remove [@deprecated](https://github.com/deprecated) jsdoc tag for a TextBedStatic.get overload ([#30714](https://github.com/angular/angular/issues/30714)) ([6bc9c78](https://github.com/angular/angular/commit/6bc9c78)), closes [#30514](https://github.com/angular/angular/issues/30514) +* **language-service:** Remove 'any' in getQuickInfoAtPosition ([#31014](https://github.com/angular/angular/issues/31014)) ([a4601ec](https://github.com/angular/angular/commit/a4601ec)) + + + + +## [8.0.2](https://github.com/angular/angular/compare/8.0.1...8.0.2) (2019-06-19) + + +### Bug Fixes + +* **bazel:** builder workspace should use nodejs v10.16.0 ([#31088](https://github.com/angular/angular/issues/31088)) ([c198dc6](https://github.com/angular/angular/commit/c198dc6)) +* **core:** temporarily remove [@deprecated](https://github.com/deprecated) jsdoc tag for a TextBedStatic.get overload ([#30714](https://github.com/angular/angular/issues/30714)) ([0a7aebb](https://github.com/angular/angular/commit/0a7aebb)), closes [#30514](https://github.com/angular/angular/issues/30514) +* **language-service:** Remove 'any' in getQuickInfoAtPosition ([#31014](https://github.com/angular/angular/issues/31014)) ([7f21449](https://github.com/angular/angular/commit/7f21449)) + + + + +# [8.1.0-next.2](https://github.com/angular/angular/compare/8.1.0-next.1...8.1.0-next.2) (2019-06-13) + + +### Bug Fixes + +* **bazel:** do not modify tsconfig.json ([#30877](https://github.com/angular/angular/issues/30877)) ([b086676](https://github.com/angular/angular/commit/b086676)) +* **bazel:** exclude components schematics from build ([#30825](https://github.com/angular/angular/issues/30825)) ([05a43ca](https://github.com/angular/angular/commit/05a43ca)) +* **bazel:** Load global stylesheet in dev and prod ([#30879](https://github.com/angular/angular/issues/30879)) ([17bfedd](https://github.com/angular/angular/commit/17bfedd)) +* **common:** expose the `HttpUploadProgressEvent` interface as public API ([#30852](https://github.com/angular/angular/issues/30852)) ([5c18f23](https://github.com/angular/angular/commit/5c18f23)), closes [#30814](https://github.com/angular/angular/issues/30814) +* **service-worker:** avoid uncaught rejection warning when registration fails ([#30876](https://github.com/angular/angular/issues/30876)) ([81c2a94](https://github.com/angular/angular/commit/81c2a94)) + + + + +## [8.0.1](https://github.com/angular/angular/compare/8.0.0...8.0.1) (2019-06-13) + + +### Bug Fixes + +* **bazel:** do not modify tsconfig.json ([#30984](https://github.com/angular/angular/issues/30984)) ([49307f0](https://github.com/angular/angular/commit/49307f0)) +* **bazel:** Load global stylesheet in dev and prod ([#30879](https://github.com/angular/angular/issues/30879)) ([5a7bcd1](https://github.com/angular/angular/commit/5a7bcd1)) +* **common:** expose the `HttpUploadProgressEvent` interface as public API ([#30852](https://github.com/angular/angular/issues/30852)) ([4e8614b](https://github.com/angular/angular/commit/4e8614b)), closes [#30814](https://github.com/angular/angular/issues/30814) +* **core:** TypeScript related migrations should cater for BOM ([#30719](https://github.com/angular/angular/issues/30719)) ([26e3615](https://github.com/angular/angular/commit/26e3615)), closes [/github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts#L72](https://github.com//github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts/issues/L72) [#30713](https://github.com/angular/angular/issues/30713) +* **service-worker:** avoid uncaught rejection warning when registration fails ([#30876](https://github.com/angular/angular/issues/30876)) ([08c38a1](https://github.com/angular/angular/commit/08c38a1)) + + + # [8.1.0-next.1](https://github.com/angular/angular/compare/8.1.0-beta.0...8.1.0-next.1) (2019-06-05) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c3d9fd3eab..a98906c74e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,9 +55,9 @@ We want to fix all the issues as soon as possible, but before fixing a bug we ne A minimal reproduction allows us to quickly confirm a bug (or point out a coding problem) as well as confirm that we are fixing the right problem. -We will be insisting on a minimal reproduction scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience users often find coding problems themselves while preparing a minimal reproduction. We understand that sometimes it might be hard to extract essential bits of code from a larger code-base but we really need to isolate the problem before we can fix it. +We will be insisting on a minimal reproduction scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience, users often find coding problems themselves while preparing a minimal reproduction. We understand that sometimes it might be hard to extract essential bits of code from a larger codebase but we really need to isolate the problem before we can fix it. -Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that doesn't have enough info to be reproduced. +Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you, we are going to close an issue that doesn't have enough info to be reproduced. You can file new issues by selecting from our [new issue templates](https://github.com/angular/angular/issues/new/choose) and filling out the issue template. @@ -168,7 +168,7 @@ format that includes a **type**, a **scope** and a **subject**: The **header** is mandatory and the **scope** of the header is optional. -Any line of the commit message cannot be longer 100 characters! This allows the message to be easier +Any line of the commit message cannot be longer than 100 characters! This allows the message to be easier to read on GitHub as well as in various git tools. The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any. @@ -201,7 +201,7 @@ Must be one of the following: * **test**: Adding missing tests or correcting existing tests ### Scope -The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages. +The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages). The following is the list of supported scopes: @@ -222,6 +222,7 @@ The following is the list of supported scopes: * **router** * **service-worker** * **upgrade** +* **zone.js** There are currently a few exceptions to the "use package name" rule: @@ -231,6 +232,8 @@ There are currently a few exceptions to the "use package name" rule: * **changelog**: used for updating the release notes in CHANGELOG.md * **docs-infra**: used for docs-app (angular.io) related changes within the /aio directory of the repo +* **ivy**: used for changes to the [Ivy renderer](https://github.com/angular/angular/issues/21706). +* **ngcc**: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md) * none/empty string: useful for `style`, `test` and `refactor` changes that are done across all packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a specific package (e.g. `docs: fix typo in tutorial`). @@ -259,8 +262,8 @@ A detailed explanation can be found in this [document][commit-message-format]. Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code changes to be accepted, the CLA must be signed. It's a quick process, we promise! -* For individuals we have a [simple click-through form][individual-cla]. -* For corporations we'll need you to +* For individuals, we have a [simple click-through form][individual-cla]. +* For corporations, we'll need you to [print, sign and one of scan+email, fax or mail the form][corporate-cla].
@@ -276,7 +279,6 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
- [angular-group]: https://groups.google.com/forum/#!forum/angular [coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md [commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit# diff --git a/README.md b/README.md index 0ad87d18a4..dac553362a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ # Angular -Angular is a development platform for building mobile and desktop web applications using Typescript/JavaScript and other languages. +Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. ## Quickstart @@ -14,7 +14,7 @@ Angular is a development platform for building mobile and desktop web applicatio ## Changelog -[Learn about the latest improvements][changelog]. +[Learn about the latest improvements][changelog]. ## Want to help? diff --git a/WORKSPACE b/WORKSPACE index 912617f7d3..94db91ed99 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -1,30 +1,23 @@ -workspace(name = "angular") +workspace( + name = "angular", + managed_directories = {"@npm": ["node_modules"]}, +) load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -# Uncomment for local bazel rules development -#local_repository( -# name = "build_bazel_rules_nodejs", -# path = "../rules_nodejs", -#) -#local_repository( -# name = "npm_bazel_typescript", -# path = "../rules_typescript", -#) - # Fetch rules_nodejs so we can install our npm dependencies http_archive( name = "build_bazel_rules_nodejs", - sha256 = "395b7568f20822c13fc5abc65b1eced637446389181fda3a108fdd6ff2cac1e9", - urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.29.2/rules_nodejs-0.29.2.tar.gz"], + sha256 = "16fc00ab0d1e538e88f084272316c0693a2e9007d64f45529b82f6230aedb073", + urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.42.2/rules_nodejs-0.42.2.tar.gz"], ) # Check the bazel version and download npm dependencies -load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "check_rules_nodejs_version", "node_repositories", "yarn_install") +load("@build_bazel_rules_nodejs//:index.bzl", "check_bazel_version", "check_rules_nodejs_version", "node_repositories", "yarn_install") -# Bazel version must be at least v0.21.0 because: -# - 0.21.0 Using --incompatible_strict_action_env flag fixes cache when running `yarn bazel` -# (see https://github.com/angular/angular/issues/27514#issuecomment-451438271) +# Bazel version must be at least the following version because: +# - 0.26.0 managed_directories feature added which is required for nodejs rules 0.30.0 +# - 0.27.0 has a fix for managed_directories after `rm -rf node_modules` check_bazel_version( message = """ You no longer need to install Bazel on your machine. @@ -33,44 +26,28 @@ Try running `yarn bazel` instead. (If you did run that, check that you've got a fresh `yarn install`) """, - minimum_bazel_version = "0.21.0", + minimum_bazel_version = "1.1.0", ) -# The NodeJS rules version must be at least v0.15.3 because: -# - 0.15.2 Re-introduced the prod_only attribute on yarn_install -# - 0.15.3 Includes a fix for the `jasmine_node_test` rule ignoring target tags -# - 0.16.8 Supports npm installed bazel workspaces -# - 0.26.0 Fix for data files in yarn_install and npm_install -# - 0.27.12 Adds NodeModuleSources provider for transtive npm deps support -check_rules_nodejs_version("0.27.12") +check_rules_nodejs_version(minimum_version_string = "0.42.1") # Setup the Node.js toolchain node_repositories( - node_version = "10.9.0", + node_repositories = { + "10.16.0-darwin_amd64": ("node-v10.16.0-darwin-x64.tar.gz", "node-v10.16.0-darwin-x64", "6c009df1b724026d84ae9a838c5b382662e30f6c5563a0995532f2bece39fa9c"), + "10.16.0-linux_amd64": ("node-v10.16.0-linux-x64.tar.xz", "node-v10.16.0-linux-x64", "1827f5b99084740234de0c506f4dd2202a696ed60f76059696747c34339b9d48"), + "10.16.0-windows_amd64": ("node-v10.16.0-win-x64.zip", "node-v10.16.0-win-x64", "aa22cb357f0fb54ccbc06b19b60e37eefea5d7dd9940912675d3ed988bf9a059"), + }, + node_version = "10.16.0", package_json = ["//:package.json"], - preserve_symlinks = True, - # yarn 1.13.0 under Bazel has a regression on Windows that causes build errors on rebuilds: - # ``` - # ERROR: Source forest creation failed: C:/.../fyuc5c3n/execroot/angular/external (Directory not empty) - # ``` - # See https://github.com/angular/angular/pull/29431 for more information. - # It possible that versions of yarn past 1.13.0 do not have this issue, however, before - # advancing this version we need to test manually on Windows that the above error does not - # happen as the issue is not caught by CI. - yarn_version = "1.12.1", + # Label needs to explicitly specify the current workspace name because otherwise Bazel does + # not provide all needed data (like "workspace_root") to the repository context. + vendored_yarn = "@angular//:third_party/github.com/yarnpkg/yarn/releases/download/v1.21.1", ) yarn_install( name = "npm", - data = [ - "//:tools/npm/@angular_bazel/index.js", - "//:tools/npm/@angular_bazel/package.json", - "//:tools/postinstall-patches.js", - "//:tools/yarn/check-yarn.js", - ], package_json = "//:package.json", - # Don't install devDependencies, they are large and not used under Bazel - prod_only = True, yarn_lock = "//:yarn.lock", ) @@ -84,19 +61,22 @@ load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies") rules_angular_dev_dependencies() -# Load karma dependencies -load("@npm_bazel_karma//:package.bzl", "rules_karma_dependencies") +# Load protractor dependencies +load("@npm_bazel_protractor//:package.bzl", "npm_bazel_protractor_dependencies") -rules_karma_dependencies() +npm_bazel_protractor_dependencies() + +# Load karma dependencies +load("@npm_bazel_karma//:package.bzl", "npm_bazel_karma_dependencies") + +npm_bazel_karma_dependencies() # Setup the rules_webtesting toolchain load("@io_bazel_rules_webtesting//web:repositories.bzl", "web_test_repositories") web_test_repositories() -# Temporary work-around for https://github.com/angular/angular/issues/28681 -# TODO(gregmagolan): go back to @io_bazel_rules_webtesting browser_repositories -load("//:browser_repositories.bzl", "browser_repositories") +load("//tools/browsers:browser_repositories.bzl", "browser_repositories") browser_repositories() @@ -120,17 +100,20 @@ load("@bazel_toolchains//rules:rbe_repo.bzl", "rbe_autoconfig") rbe_autoconfig( name = "rbe_ubuntu1604_angular", - # The sha256 of marketplace.gcr.io/google/rbe-ubuntu16-04 container that is - # used by rbe_autoconfig() to pair toolchain configs in the @bazel_toolchains repo. - base_container_digest = "sha256:677c1317f14c6fd5eba2fd8ec645bfdc5119f64b3e5e944e13c89e0525cc8ad1", + # Need to specify a base container digest in order to ensure that we can use the checked-in + # platform configurations for the "ubuntu16_04" image. Otherwise the autoconfig rule would + # need to pull the image and run it in order determine the toolchain configuration. See: + # https://github.com/bazelbuild/bazel-toolchains/blob/1.1.2/configs/ubuntu16_04_clang/versions.bzl + base_container_digest = "sha256:1ab40405810effefa0b2f45824d6d608634ccddbf06366760c341ef6fbead011", # Note that if you change the `digest`, you might also need to update the # `base_container_digest` to make sure marketplace.gcr.io/google/rbe-ubuntu16-04-webtest: # and marketplace.gcr.io/google/rbe-ubuntu16-04: have - # the same Clang and JDK installed. - # Clang is needed because of the dependency on @com_google_protobuf. - # Java is needed for the Bazel's test executor Java tool. - digest = "sha256:74a8e9dca4781d5f277a7bd8e7ea7ed0f5906c79c9cd996205b6d32f090c62f3", + # the same Clang and JDK installed. Clang is needed because of the dependency on + # @com_google_protobuf. Java is needed for the Bazel's test executor Java tool. + digest = "sha256:0b8fa87db4b8e5366717a7164342a029d1348d2feea7ecc4b18c780bc2507059", env = clang_env(), registry = "marketplace.gcr.io", + # We can't use the default "ubuntu16_04" RBE image provided by the autoconfig because we need + # a specific Linux kernel that comes with "libx11" in order to run headless browser tests. repository = "google/rbe-ubuntu16-04-webtest", ) diff --git a/aio/README.md b/aio/README.md index 3a8a75235a..8cb7af568d 100644 --- a/aio/README.md +++ b/aio/README.md @@ -14,10 +14,12 @@ Here are the most important tasks you might need to use: * `yarn` - install all the dependencies. * `yarn setup` - install all the dependencies, boilerplate, stackblitz, zips and run dgeni on the docs. -* `yarn setup-local` - same as `setup`, but use the locally built Angular packages for aio and docs examples boilerplate. +* `yarn setup-local` - same as `setup`, but build the Angular packages from the source code and use these locally built versions (instead of the ones fetched from npm) for aio and docs examples boilerplate. * `yarn build` - create a production build of the application (after installing dependencies, boilerplate, etc). * `yarn build-local` - same as `build`, but use `setup-local` instead of `setup`. +* `yarn build-local-with-viewengine` - same as `build-local`, but in addition also turns on `ViewEngine` mode in aio. + (Note: Docs examples run in `ViewEngine` mode by default. To turn on `ivy` mode in examples, see `yarn boilerplate:add` below.) * `yarn start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary. * `yarn serve-and-sync` - run both the `docs-watch` and `start` in the same console. @@ -31,16 +33,29 @@ Here are the most important tasks you might need to use: * `yarn docs-lint` - check that the doc gen code follows our style rules. * `yarn docs-test` - run the unit tests for the doc generation code. -* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally. Add the option `--local` to use your local version of Angular contained in the "dist" folder. +* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally. +* `yarn boilerplate:add:ivy` - same as `boilerplate:add` but also turns on `ivy` mode. + * `yarn boilerplate:remove` - remove all the boilerplate code that was added via `yarn boilerplate:add`. * `yarn generate-stackblitz` - generate the stackblitz files that are used by the `live-example` tags in the docs. * `yarn generate-zips` - generate the zip files from the examples. Zip available via the `live-example` tags in the docs. -* `yarn example-e2e` - run all e2e tests for examples - - `yarn example-e2e --setup` - force webdriver update & other setup, then run tests - - `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 +* `yarn example-e2e` - run all e2e tests for examples. Available options: + - `--setup`: generate boilerplate, force webdriver update & other setup, then run tests. + - `--local`: run e2e tests with the local version of Angular contained in the "dist" folder. + _Requires `--setup` in order to take effect._ + - `--ivy`: run e2e tests in `ivy` mode. + - `--filter=foo`: limit e2e tests to those containing the word "foo". +> **Note for Windows users** +> +> Setting up the examples involves creating some [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link) (see [here](./tools/examples/README.md#symlinked-node_modules) for details). On Windows, this requires to either have [Developer Mode enabled](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10) (supported on Windows 10 or newer) or run the setup commands as administrator. +> +> The affected commands are: +> - `yarn setup` / `yarn setup-*` +> - `yarn build` / `yarn build-*` +> - `yarn boilerplate:add` +> - `yarn example-e2e --setup` ## Using ServiceWorker locally @@ -89,7 +104,7 @@ You also want to see those changes displayed properly in the doc viewer with a quick, edit/view cycle time. For this purpose, use the `yarn docs-watch` task, which watches for changes to source files and only -re-processes the the files necessary to generate the docs that are related to the file that has changed. +re-processes the files necessary to generate the docs that are related to the file that has changed. Since this task takes shortcuts, it is much faster (often less than 1 second) but it won't produce full fidelity content. For example, links to other docs and code examples may not render correctly. This is most particularly noticed in links to other docs and in the embedded examples, which may not always render diff --git a/aio/aio-builds-setup/dockerbuild/scripts-js/package.json b/aio/aio-builds-setup/dockerbuild/scripts-js/package.json index 64f0c0ccf5..7599c1a84e 100644 --- a/aio/aio-builds-setup/dockerbuild/scripts-js/package.json +++ b/aio/aio-builds-setup/dockerbuild/scripts-js/package.json @@ -34,7 +34,7 @@ "shelljs": "^0.8.2", "source-map-support": "^0.5.9", "tar-stream": "^1.6.1", - "tslib": "^1.9.3" + "tslib": "^1.10.0" }, "devDependencies": { "@types/body-parser": "^1.17.0", diff --git a/aio/aio-builds-setup/dockerbuild/scripts-js/yarn.lock b/aio/aio-builds-setup/dockerbuild/scripts-js/yarn.lock index f5702a8228..7b82bbe49a 100644 --- a/aio/aio-builds-setup/dockerbuild/scripts-js/yarn.lock +++ b/aio/aio-builds-setup/dockerbuild/scripts-js/yarn.lock @@ -2444,7 +2444,12 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.3: +tslib@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== + +tslib@^1.8.0, tslib@^1.8.1: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" diff --git a/aio/angular.json b/aio/angular.json index ec11a66792..6b02c8293a 100644 --- a/aio/angular.json +++ b/aio/angular.json @@ -5,7 +5,8 @@ "packageManager": "yarn", "warnings": { "typescriptMismatch": false - } + }, + "analytics": false }, "newProjectRoot": "projects", "projects": { @@ -60,7 +61,13 @@ "styles": [ "src/styles.scss" ], - "scripts": [] + "scripts": [], + "budgets": [ + { + "type": "anyComponentStyle", + "maximumWarning": "6kb" + } + ] }, "configurations": { "fast": { @@ -185,4 +192,4 @@ } }, "defaultProject": "site" -} +} \ No newline at end of file diff --git a/aio/browserslist b/aio/browserslist index 2ffbe86742..929b6eee65 100644 --- a/aio/browserslist +++ b/aio/browserslist @@ -6,8 +6,7 @@ # For additional information see: https://developers.google.com/search/docs/guides/rendering > 0.5% -last 2 versions +last 2 major versions Firefox ESR not dead -IE 9-11 # For IE 9-11 support. -Chrome 41 # For Googlebot support. +IE 11 diff --git a/aio/content/cli/index.md b/aio/content/cli/index.md index 332fbe2a80..e3d0d500cf 100644 --- a/aio/content/cli/index.md +++ b/aio/content/cli/index.md @@ -19,7 +19,7 @@ Install the CLI using the `npm` package manager: 使用 `npm` 包管理器来安装 CLI: - + npm install -g @angular/cli @@ -40,7 +40,7 @@ Enter the following to list commands or options for a given command (such as [ge 命令行中还提供了联机帮助。 输入下列命令列出命令或指定命令(如 [generate](cli/generate))选项的简短说明。 - + ng help ng generate --help @@ -49,7 +49,7 @@ To create, build, and serve a new, basic Angular project on a development server 要想创建、构建或在开发服务器上运行一个新的、基本的 Angular 项目,请到这个新工作区的上级目录中运行下列命令: - + ng new my-first-project cd my-first-project ng serve @@ -61,6 +61,18 @@ When you use the [ng serve](cli/serve) command to build an app and serve it loca 在浏览器中,打开 查看运行效果。 当你使用 [ng serve](cli/serve) 命令来构建应用并在本地启动开发服务器时,服务器会自动重新构建此应用,并在修改源码时重新加载此页面。 +
+ +when you run `ng new my-first-project` a new folder, named `my-first-project`, will be created in the current working directory. since you want to be able to create files inside that folder, make sure you have sufficient rights in the current working directory before running the command. + +当你运行 `ng new my-first-project` 时,将在当前工作目录中创建一个名为 `my-first-project` 的新文件夹。由于你希望在该文件夹中创建文件,因此在运行命令之前,请确保你在当前工作目录中具有足够的权限。 + +If the current working directory is not the right place for your project, you can change to a more appropriate directory by running `cd ` first. + +如果当前工作目录不适合放你的项目,可以先运行 `cd ` 来切换到更合适的目录。 + +
+ ## Workspaces and project files ## 工作区与项目文件 @@ -134,8 +146,8 @@ Command syntax is shown as follows: * Option names are prefixed with a double dash (--). Option aliases are prefixed with a single dash (-). Arguments are not prefixed. - For example: - + For example: + ng build my-app -c production @@ -197,6 +209,6 @@ Schematic options are supplied to the command in the same format as immediate co ### 使用 Bazel 进行构建 -Optionally, you can configure the Angular CLI to use [Bazel](https://docs.bazel.build) as the build tool. For more information, see [Building with Bazel](guide/bazel). +Optionally, you can configure the Angular CLI to use [Bazel](https://docs.bazel.build) as the build tool. For more information, see [Building with Bazel](guide/bazel). 你还可以把 Angular CLI 配置为把 [Bazel](https://docs.bazel.build) 作为构建工具。欲知详情,参见[用 Bazel 进行构建](guide/bazel)。 \ No newline at end of file diff --git a/aio/content/examples/accessibility/e2e/src/app.e2e-spec.ts b/aio/content/examples/accessibility/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000000..1df4834f8c --- /dev/null +++ b/aio/content/examples/accessibility/e2e/src/app.e2e-spec.ts @@ -0,0 +1,21 @@ +'use strict'; // necessary for es6 output in node + +import { browser, element, by } from 'protractor'; + +describe('Accessibility example e2e tests', () => { + + beforeEach(() => { + browser.get(''); + }); + + it('should display Accessibility Example', function () { + expect(element(by.css('h1')).getText()).toEqual('Accessibility Example'); + }); + + it('should take a number and change progressbar width', function () { + element(by.css('input')).sendKeys('16'); + expect(element(by.css('input')).getAttribute('value')).toEqual('016'); + expect(element(by.css('app-example-progressbar div')).getCssValue('width')).toBe('48px'); + }); + +}); diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customer-list/customer-list.component.css b/aio/content/examples/accessibility/example-config.json similarity index 100% rename from aio/content/examples/lazy-loading-ngmodules/src/app/customers/customer-list/customer-list.component.css rename to aio/content/examples/accessibility/example-config.json diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/orders/order-list/order-list.component.css b/aio/content/examples/accessibility/src/app/app.component.css old mode 100644 new mode 100755 similarity index 100% rename from aio/content/examples/lazy-loading-ngmodules/src/app/orders/order-list/order-list.component.css rename to aio/content/examples/accessibility/src/app/app.component.css diff --git a/aio/content/examples/accessibility/src/app/app.component.html b/aio/content/examples/accessibility/src/app/app.component.html new file mode 100755 index 0000000000..4869298570 --- /dev/null +++ b/aio/content/examples/accessibility/src/app/app.component.html @@ -0,0 +1,13 @@ +

Accessibility Example

+ + + + + + + + diff --git a/aio/content/examples/accessibility/src/app/app.component.ts b/aio/content/examples/accessibility/src/app/app.component.ts new file mode 100755 index 0000000000..dd635acc9c --- /dev/null +++ b/aio/content/examples/accessibility/src/app/app.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: [ './app.component.css' ] +}) +export class AppComponent { + progress = 0; +} diff --git a/aio/content/examples/accessibility/src/app/app.module.ts b/aio/content/examples/accessibility/src/app/app.module.ts new file mode 100755 index 0000000000..bce527d559 --- /dev/null +++ b/aio/content/examples/accessibility/src/app/app.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { AppComponent } from './app.component'; +import { ExampleProgressbarComponent } from './progress-bar.component'; + +@NgModule({ + imports: [ BrowserModule ], + declarations: [ AppComponent, ExampleProgressbarComponent ], + bootstrap: [ AppComponent ] +}) +export class AppModule { } diff --git a/aio/content/examples/accessibility/src/app/progress-bar.component.css b/aio/content/examples/accessibility/src/app/progress-bar.component.css new file mode 100755 index 0000000000..976ef61655 --- /dev/null +++ b/aio/content/examples/accessibility/src/app/progress-bar.component.css @@ -0,0 +1,12 @@ + :host { + display: block; + width: 300px; + height: 25px; + border: 1px solid black; + margin-top: 16px; + } + + .bar { + background: blue; + height: 100%; + } \ No newline at end of file diff --git a/aio/content/examples/accessibility/src/app/progress-bar.component.ts b/aio/content/examples/accessibility/src/app/progress-bar.component.ts new file mode 100755 index 0000000000..fe1f5d8c73 --- /dev/null +++ b/aio/content/examples/accessibility/src/app/progress-bar.component.ts @@ -0,0 +1,28 @@ +// #docregion progressbar-component +import { Component, Input } from '@angular/core'; + +/** + * Example progressbar component. + */ +@Component({ + selector: 'app-example-progressbar', + template: `
`, + styleUrls: ['./progress-bar.component.css'], + host: { + // Sets the role for this component to "progressbar" + role: 'progressbar', + + // Sets the minimum and maximum values for the progressbar role. + 'aria-valuemin': '0', + 'aria-valuemax': '100', + + // Binding that updates the current value of the progressbar. + '[attr.aria-valuenow]': 'value', + } +}) +export class ExampleProgressbarComponent { + /** Current value of the progressbar. */ + @Input() value = 0; +} + +// #enddocregion progressbar-component diff --git a/aio/content/examples/accessibility/src/index.html b/aio/content/examples/accessibility/src/index.html new file mode 100644 index 0000000000..8c4042ea2d --- /dev/null +++ b/aio/content/examples/accessibility/src/index.html @@ -0,0 +1,14 @@ + + + + + Accessibility Example + + + + + + + Loading... + + diff --git a/aio/content/examples/accessibility/src/main.ts b/aio/content/examples/accessibility/src/main.ts new file mode 100644 index 0000000000..a9ca1caf8c --- /dev/null +++ b/aio/content/examples/accessibility/src/main.ts @@ -0,0 +1,11 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/aio/content/examples/accessibility/stackblitz.json b/aio/content/examples/accessibility/stackblitz.json new file mode 100644 index 0000000000..f3ee46960b --- /dev/null +++ b/aio/content/examples/accessibility/stackblitz.json @@ -0,0 +1,10 @@ +{ + "description": "Accessibility", + "files": [ + "!**/*.d.ts", + "!**/*.js", + "!**/*.[1,2].*" + ], + "file": "src/app/app.component.ts", + "tags": ["Accessibility"] +} diff --git a/aio/content/examples/animations/src/app/hero.ts b/aio/content/examples/animations/src/app/hero.ts index e3eac516da..a61b497759 100644 --- a/aio/content/examples/animations/src/app/hero.ts +++ b/aio/content/examples/animations/src/app/hero.ts @@ -1,4 +1,4 @@ -export class Hero { +export interface Hero { id: number; name: string; } diff --git a/aio/content/examples/animations/src/app/open-close.component.3.ts b/aio/content/examples/animations/src/app/open-close.component.3.ts index ddd6f09f2b..64ca362f36 100644 --- a/aio/content/examples/animations/src/app/open-close.component.3.ts +++ b/aio/content/examples/animations/src/app/open-close.component.3.ts @@ -36,9 +36,6 @@ import { transAnimation } from './animations'; }) ]) ]) -// #docregion runtime - ], -// #enddocregion runtime // #enddocregion reusable templateUrl: 'open-close.component.html', styleUrls: ['open-close.component.css'] diff --git a/aio/content/examples/architecture/e2e/src/app.e2e-spec.ts b/aio/content/examples/architecture/e2e/src/app.e2e-spec.ts index 6dbc6952b8..d6e9316e8e 100644 --- a/aio/content/examples/architecture/e2e/src/app.e2e-spec.ts +++ b/aio/content/examples/architecture/e2e/src/app.e2e-spec.ts @@ -4,7 +4,7 @@ import { protractor, browser, element, by, ElementFinder } from 'protractor'; const nameSuffix = 'X'; -class Hero { +interface Hero { id: number; name: string; } diff --git a/aio/content/examples/attribute-binding/e2e/src/app.e2e-spec.ts b/aio/content/examples/attribute-binding/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000000..c02fa87e1b --- /dev/null +++ b/aio/content/examples/attribute-binding/e2e/src/app.e2e-spec.ts @@ -0,0 +1,47 @@ +'use strict'; // necessary for es6 output in node + +import { browser, element, by } from 'protractor'; + +describe('Attribute binding example', function () { + + beforeEach(function () { + browser.get(''); + }); + + it('should display Property Binding with Angular', function () { + expect(element(by.css('h1')).getText()).toEqual('Attribute, class, and style bindings'); + }); + + it('should display a table', function() { + expect(element.all(by.css('table')).isPresent()).toBe(true); + }); + + it('should display an Aria button', function () { + expect(element.all(by.css('button')).get(0).getText()).toBe('Go for it with Aria'); + }); + + it('should display a blue background on div', function () { + expect(element.all(by.css('div')).get(1).getCssValue('background-color')).toEqual('rgba(25, 118, 210, 1)'); + }); + + it('should display a blue div with a red border', function () { + expect(element.all(by.css('div')).get(4).getCssValue('border')).toEqual('2px solid rgb(212, 30, 46)'); + }); + + it('should display a div with replaced classes', function () { + expect(element.all(by.css('div')).get(5).getAttribute('class')).toEqual('new-class'); + }); + + it('should display four buttons', function() { + let redButton = element.all(by.css('button')).get(1); + let saveButton = element.all(by.css('button')).get(2); + let bigButton = element.all(by.css('button')).get(3); + let smallButton = element.all(by.css('button')).get(4); + + expect(redButton.getCssValue('color')).toEqual('rgba(255, 0, 0, 1)'); + expect(saveButton.getCssValue('background-color')).toEqual('rgba(0, 255, 255, 1)'); + expect(bigButton.getText()).toBe('Big'); + expect(smallButton.getText()).toBe('Small'); + }); + +}); diff --git a/aio/content/examples/attribute-binding/example-config.json b/aio/content/examples/attribute-binding/example-config.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/attribute-binding/src/app/app.component.css b/aio/content/examples/attribute-binding/src/app/app.component.css new file mode 100644 index 0000000000..f26e6c8569 --- /dev/null +++ b/aio/content/examples/attribute-binding/src/app/app.component.css @@ -0,0 +1,22 @@ +.special { + background-color: #1976d2; + color: #ffffff; +} + +.item { + font-weight: bold; +} +.clearance { + border: 2px solid #d41e2e; + +} +.item-clearance { + font-style: italic; + +} + +.new-class { + background-color: #ed1b2f; + font-style: italic; + color: #fff; +} diff --git a/aio/content/examples/attribute-binding/src/app/app.component.html b/aio/content/examples/attribute-binding/src/app/app.component.html new file mode 100644 index 0000000000..7a2fb3311f --- /dev/null +++ b/aio/content/examples/attribute-binding/src/app/app.component.html @@ -0,0 +1,65 @@ + +

Attribute, class, and style bindings

+

Attribute binding

+ + + + + + + + + + + + +
One-Two
Three-Four
FiveSix
+ + +
+ + + + +
+ +
+ +

Class binding

+ + +

toggle the "special" class on/off with a property:

+
The class binding is special.
+ +

binding to class.special overrides the class attribute:

+
This one is not so special.
+ +

Using the bind- syntax:

+
This class binding is special too.
+ + + +

Add a class:

+
Add another class
+ + + +

Overwrite all existing classes with a new class:

+
Reset all classes at once
+ + +
+ +

Style binding

+ + + + + + + + + + diff --git a/aio/content/examples/attribute-binding/src/app/app.component.spec.ts b/aio/content/examples/attribute-binding/src/app/app.component.spec.ts new file mode 100644 index 0000000000..bcbdf36b3e --- /dev/null +++ b/aio/content/examples/attribute-binding/src/app/app.component.spec.ts @@ -0,0 +1,27 @@ +import { TestBed, async } from '@angular/core/testing'; +import { AppComponent } from './app.component'; +describe('AppComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ + AppComponent + ], + }).compileComponents(); + })); + it('should create the app', async(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app).toBeTruthy(); + })); + it(`should have as title 'app'`, async(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app.title).toEqual('app'); + })); + it('should render title in a h1 tag', async(() => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.debugElement.nativeElement; + expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!'); + })); +}); diff --git a/aio/content/examples/attribute-binding/src/app/app.component.ts b/aio/content/examples/attribute-binding/src/app/app.component.ts new file mode 100644 index 0000000000..f79b22c817 --- /dev/null +++ b/aio/content/examples/attribute-binding/src/app/app.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'] +}) +export class AppComponent { + actionName = 'Go for it'; + isSpecial = true; + itemClearance = true; + resetClasses = 'new-class'; + canSave = true; + +} diff --git a/aio/content/examples/attribute-binding/src/app/app.module.ts b/aio/content/examples/attribute-binding/src/app/app.module.ts new file mode 100644 index 0000000000..926975afe8 --- /dev/null +++ b/aio/content/examples/attribute-binding/src/app/app.module.ts @@ -0,0 +1,18 @@ +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; + + +import { AppComponent } from './app.component'; + + +@NgModule({ + declarations: [ + AppComponent + ], + imports: [ + BrowserModule + ], + providers: [], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/aio/content/examples/attribute-binding/src/index.html b/aio/content/examples/attribute-binding/src/index.html new file mode 100644 index 0000000000..0cfaba9b75 --- /dev/null +++ b/aio/content/examples/attribute-binding/src/index.html @@ -0,0 +1,14 @@ + + + + + AttributeBinding + + + + + + + + + diff --git a/aio/content/examples/attribute-binding/src/main.ts b/aio/content/examples/attribute-binding/src/main.ts new file mode 100644 index 0000000000..91ec6da5f0 --- /dev/null +++ b/aio/content/examples/attribute-binding/src/main.ts @@ -0,0 +1,12 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.log(err)); diff --git a/aio/content/examples/attribute-binding/stackblitz.json b/aio/content/examples/attribute-binding/stackblitz.json new file mode 100644 index 0000000000..1a0178b68a --- /dev/null +++ b/aio/content/examples/attribute-binding/stackblitz.json @@ -0,0 +1,10 @@ +{ + "description": "Attribute Binding", + "files": [ + "!**/*.d.ts", + "!**/*.js", + "!**/*.[1,2].*" + ], + "file": "src/app/app.component.ts", + "tags": ["Attribute Binding"] +} diff --git a/aio/content/examples/attribute-directives/e2e/src/app.e2e-spec.ts b/aio/content/examples/attribute-directives/e2e/src/app.e2e-spec.ts index 00ef4e33c6..019469c338 100644 --- a/aio/content/examples/attribute-directives/e2e/src/app.e2e-spec.ts +++ b/aio/content/examples/attribute-directives/e2e/src/app.e2e-spec.ts @@ -25,8 +25,8 @@ describe('Attribute directives', () => { greenRb.click(); browser.actions().mouseMove(highlightedEle).perform(); - // Wait for up to 2s for the background color to be updated, + // Wait for up to 4s for the background color to be updated, // to account for slow environments (e.g. CI). - browser.wait(() => highlightedEle.getCssValue('background-color').then(c => c === lightGreen), 2000); + browser.wait(() => highlightedEle.getCssValue('background-color').then(c => c === lightGreen), 4000); }); }); diff --git a/aio/content/examples/binding-syntax/e2e/src/app.e2e-spec.ts b/aio/content/examples/binding-syntax/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000000..c9bc11e472 --- /dev/null +++ b/aio/content/examples/binding-syntax/e2e/src/app.e2e-spec.ts @@ -0,0 +1,76 @@ +import { browser, element, by } from 'protractor'; +import { logging } from 'selenium-webdriver'; + +describe('Binding syntax e2e tests', () => { + + beforeEach(function () { + browser.get(''); + }); + + + // helper function used to test what's logged to the console + async function logChecker(button, contents) { + const logs = await browser.manage().logs().get(logging.Type.BROWSER); + const message = logs.filter(({ message }) => message.indexOf(contents) !== -1 ? true : false); + expect(message.length).toBeGreaterThan(0); + } + + + it('should display Binding syntax', function () { + expect(element(by.css('h1')).getText()).toEqual('Binding syntax'); + }); + + it('should display Save button', function () { + expect(element.all(by.css('button')).get(0).getText()).toBe('Save'); + }); + + it('should display HTML attributes and DOM properties', function () { + expect(element.all(by.css('h2')).get(1).getText()).toBe('HTML attributes and DOM properties'); + }); + + it('should display 1. Use the inspector...', function () { + expect(element.all(by.css('p')).get(0).getText()).toContain('1. Use the inspector'); + }); + + it('should display Disabled property vs. attribute', function () { + expect(element.all(by.css('h3')).get(0).getText()).toBe('Disabled property vs. attribute'); + }); + + + it('should log a message including Sarah', async () => { + let attributeButton = element.all(by.css('button')).get(1); + await attributeButton.click(); + const contents = 'Sarah'; + logChecker(attributeButton, contents); + }); + + it('should log a message including Sarah for DOM property', async () => { + let DOMPropertyButton = element.all(by.css('button')).get(2); + await DOMPropertyButton.click(); + const contents = 'Sarah'; + logChecker(DOMPropertyButton, contents); + }); + + it('should log a message including Sally for DOM property', async () => { + let DOMPropertyButton = element.all(by.css('button')).get(2); + let input = element(by.css('input')); + input.sendKeys('Sally'); + await DOMPropertyButton.click(); + const contents = 'Sally'; + logChecker(DOMPropertyButton, contents); + }); + + it('should log a message that Test Button works', async () => { + let testButton = element.all(by.css('button')).get(3); + await testButton.click(); + const contents = 'Test'; + logChecker(testButton, contents); + }); + + it('should toggle Test Button disabled', async () => { + let toggleButton = element.all(by.css('button')).get(4); + await toggleButton.click(); + const contents = 'true'; + logChecker(toggleButton, contents); + }); +}); diff --git a/aio/content/examples/binding-syntax/example-config.json b/aio/content/examples/binding-syntax/example-config.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/binding-syntax/src/app/app.component.css b/aio/content/examples/binding-syntax/src/app/app.component.css new file mode 100644 index 0000000000..30428daac5 --- /dev/null +++ b/aio/content/examples/binding-syntax/src/app/app.component.css @@ -0,0 +1,3 @@ +div { + padding: .25rem 0; +} diff --git a/aio/content/examples/binding-syntax/src/app/app.component.html b/aio/content/examples/binding-syntax/src/app/app.component.html new file mode 100644 index 0000000000..0260bd75a5 --- /dev/null +++ b/aio/content/examples/binding-syntax/src/app/app.component.html @@ -0,0 +1,45 @@ + +
+

Binding syntax

+
+ +
+

Button disabled state bound to isUnchanged property

+ + + + +
+ +
+ +
+

HTML attributes and DOM properties

+

1. Use the inspector to see the HTML attribute and DOM property values. Click the buttons to log values to the console.

+ + +
+ Won't change. +
+ +
+ Changeable. Angular works with these. +
+ +

2. Change the name in the input and click the buttons again.

+
+ +
+ +
+

Disabled property vs. attribute

+

Use the inspector to see the Test Button work and its disabled property toggle.

+
+ +
+
+ +
+ +
diff --git a/aio/content/examples/binding-syntax/src/app/app.component.spec.ts b/aio/content/examples/binding-syntax/src/app/app.component.spec.ts new file mode 100644 index 0000000000..bcbdf36b3e --- /dev/null +++ b/aio/content/examples/binding-syntax/src/app/app.component.spec.ts @@ -0,0 +1,27 @@ +import { TestBed, async } from '@angular/core/testing'; +import { AppComponent } from './app.component'; +describe('AppComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ + AppComponent + ], + }).compileComponents(); + })); + it('should create the app', async(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app).toBeTruthy(); + })); + it(`should have as title 'app'`, async(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app.title).toEqual('app'); + })); + it('should render title in a h1 tag', async(() => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.debugElement.nativeElement; + expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!'); + })); +}); diff --git a/aio/content/examples/binding-syntax/src/app/app.component.ts b/aio/content/examples/binding-syntax/src/app/app.component.ts new file mode 100644 index 0000000000..bed9bd2a75 --- /dev/null +++ b/aio/content/examples/binding-syntax/src/app/app.component.ts @@ -0,0 +1,33 @@ +import { Component, ViewChild, ElementRef } from '@angular/core'; + + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'] +}) +export class AppComponent { + + @ViewChild('bindingInput') bindingInput: ElementRef; + + isUnchanged = true; + + getHTMLAttributeValue(): any { + console.warn('HTML attribute value: ' + this.bindingInput.nativeElement.getAttribute('value')); + } + + getDOMPropertyValue(): any { + console.warn('DOM property value: ' + this.bindingInput.nativeElement.value); + } + + working(): any { + console.warn('Test Button works!'); + } + + toggleDisabled(): any { + + let testButton = document.getElementById('testButton'); + testButton.disabled = !testButton.disabled; + console.warn(testButton.disabled); + } +} diff --git a/aio/content/examples/binding-syntax/src/app/app.module.ts b/aio/content/examples/binding-syntax/src/app/app.module.ts new file mode 100644 index 0000000000..926975afe8 --- /dev/null +++ b/aio/content/examples/binding-syntax/src/app/app.module.ts @@ -0,0 +1,18 @@ +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; + + +import { AppComponent } from './app.component'; + + +@NgModule({ + declarations: [ + AppComponent + ], + imports: [ + BrowserModule + ], + providers: [], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/aio/content/examples/binding-syntax/src/index.html b/aio/content/examples/binding-syntax/src/index.html new file mode 100644 index 0000000000..fe53d5a822 --- /dev/null +++ b/aio/content/examples/binding-syntax/src/index.html @@ -0,0 +1,14 @@ + + + + + + Angular binding syntax example + + + + + Loading... + + + diff --git a/aio/content/examples/binding-syntax/src/main.ts b/aio/content/examples/binding-syntax/src/main.ts new file mode 100644 index 0000000000..0740658908 --- /dev/null +++ b/aio/content/examples/binding-syntax/src/main.ts @@ -0,0 +1,12 @@ +// #docregion +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/aio/content/examples/binding-syntax/stackblitz.json b/aio/content/examples/binding-syntax/stackblitz.json new file mode 100644 index 0000000000..49fb8fc01a --- /dev/null +++ b/aio/content/examples/binding-syntax/stackblitz.json @@ -0,0 +1,10 @@ +{ + "description": "Binding Syntax", + "files": [ + "!**/*.d.ts", + "!**/*.js", + "!**/*.[1,2].*" + ], + "file": "src/app/app.component.ts", + "tags": ["Binding Syntax"] +} diff --git a/aio/content/examples/built-in-directives/e2e/src/app.e2e-spec.ts b/aio/content/examples/built-in-directives/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000000..261afac3d4 --- /dev/null +++ b/aio/content/examples/built-in-directives/e2e/src/app.e2e-spec.ts @@ -0,0 +1,78 @@ +'use strict'; + +import { browser, element, by } from 'protractor'; + +describe('Built-in Directives', function () { + + beforeAll(function () { + browser.get(''); + }); + + it('should have title Built-in Directives', function () { + let title = element.all(by.css('h1')).get(0); + expect(title.getText()).toEqual('Built-in Directives'); + }); + + it('should change first Teapot header', async () => { + let firstLabel = element.all(by.css('p')).get(0); + let firstInput = element.all(by.css('input')).get(0); + + expect(firstLabel.getText()).toEqual('Current item name: Teapot'); + firstInput.sendKeys('abc'); + expect(firstLabel.getText()).toEqual('Current item name: Teapotabc'); + }); + + + it('should modify sentence when modified checkbox checked', function () { + let modifiedChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(1); + let modifiedSentence = element.all(by.css('div')).get(1); + + modifiedChkbxLabel.click(); + expect(modifiedSentence.getText()).toContain('modified'); + }); + + it('should modify sentence when normal checkbox checked', function () { + let normalChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(4); + let normalSentence = element.all(by.css('div')).get(7); + + normalChkbxLabel.click(); + expect(normalSentence.getText()).toContain('normal weight and, extra large'); + }); + + it('should toggle app-item-detail', function () { + let toggleButton = element.all(by.css('button')).get(3); + let toggledDiv = element.all(by.css('app-item-detail')).get(0); + + toggleButton.click(); + expect(toggledDiv.isDisplayed()).toBe(true); + }); + + it('should hide app-item-detail', function () { + let hiddenMessage = element.all(by.css('p')).get(11); + let hiddenDiv = element.all(by.css('app-item-detail')).get(2); + + expect(hiddenMessage.getText()).toContain('in the DOM'); + expect(hiddenDiv.isDisplayed()).toBe(true); + }); + + it('should have 10 lists each containing the string Teapot', function () { + let listDiv = element.all(by.cssContainingText('.box', 'Teapot')); + expect(listDiv.count()).toBe(10); + }); + + it('should switch case', function () { + let tvRadioButton = element.all(by.css('input[type="radio"]')).get(3); + let tvDiv = element(by.css('app-lost-item')); + + let fishbowlRadioButton = element.all(by.css('input[type="radio"]')).get(4); + let fishbowlDiv = element(by.css('app-unknown-item')); + + tvRadioButton.click(); + expect(tvDiv.getText()).toContain('Television'); + fishbowlRadioButton.click(); + expect(fishbowlDiv.getText()).toContain('mysterious'); + }); + + +}); + diff --git a/aio/content/examples/built-in-directives/example-config.json b/aio/content/examples/built-in-directives/example-config.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/built-in-directives/src/app/app.component.css b/aio/content/examples/built-in-directives/src/app/app.component.css new file mode 100644 index 0000000000..201fe682c4 --- /dev/null +++ b/aio/content/examples/built-in-directives/src/app/app.component.css @@ -0,0 +1,75 @@ + +button { + font-size: 100%; + margin: 0 2px; +} + +div[ng-reflect-ng-switch], app-unknown-item { + margin: .5rem 0; + display: block; +} + +#noTrackByCnt, +#withTrackByCnt { + color: darkred; + max-width: 450px; + margin: 4px; +} + +img { + height: 100px; +} + +.box { + border: 1px solid black; + padding: 6px; + max-width: 450px; +} + +.child-div { + margin-left: 1em; + font-weight: normal; +} + +.context { + margin-left: 1em; +} + +.hidden { + display: none; +} + +.parent-div { + margin-top: 1em; + font-weight: bold; +} + +.course { + font-weight: bold; + font-size: x-large; +} + +.helpful { + color: red; +} + +.saveable { + color: limegreen; +} + +.study, +.modified { + font-family: "Brush Script MT"; + font-size: 2rem; +} + +.toe { + margin-left: 1em; + font-style: italic; +} + + +.to-toc { + margin-top: 10px; + display: block; +} diff --git a/aio/content/examples/built-in-directives/src/app/app.component.html b/aio/content/examples/built-in-directives/src/app/app.component.html new file mode 100644 index 0000000000..17b3fed9a4 --- /dev/null +++ b/aio/content/examples/built-in-directives/src/app/app.component.html @@ -0,0 +1,253 @@ +

Built-in Directives

+ +

Built-in attribute directives

+ +

NgModel (two-way) Binding

+ +

NgModel examples

+

Current item name: {{currentItem.name}}

+

+ + + + + +

+ +

+ + + + +

+ +

+ + +

+ +

+ + + + +

+ +

+ +

+
+ +

NgClass Binding

+ +

currentClasses is {{currentClasses | json}}

+ +
This div is initially saveable, unchanged, and special.
+ +
    +
  • + + +
  • +
  • + +
  • +
  • + +
  • +
+ + +
+ This div should be {{ canSave ? "": "not"}} saveable, + {{ isUnchanged ? "unchanged" : "modified" }} and + {{ isSpecial ? "": "not"}} special after clicking "Refresh".
+

+ + +
This div is special
+ +
Helpful study course
+
Study course
+ + + +

NgStyle Binding

+ +
+ This div is x-large or smaller. +
+ + + +

[ngStyle] binding to currentStyles - CSS property names

+

currentStyles is {{currentStyles | json}}

+ + +
+ This div is initially italic, normal weight, and extra large (24px). +
+ + + + +
+ | + | + + +

+
+ This div should be {{ canSave ? "italic": "plain"}}, + {{ isUnchanged ? "normal weight" : "bold" }} and, + {{ isSpecial ? "extra large": "normal size"}} after clicking "Refresh".
+ +
+

Built-in structural directives

+

NgIf Binding

+
+

If isActive is true, app-item-detail will render:

+ + + + + +
+

If currentCustomer isn't null, say hello to Laura:

+ +
Hello, {{currentCustomer.name}}
+ +

nullCustomer is null by default. NgIf guards against null. Give it a value to show it:

+ +
Hello, {{nullCustomer}}
+ + + + +

NgIf binding with template (no *)

+ +Add {{currentItem.name}} with template +
+ +

Show/hide vs. NgIf

+ + +
Show with class
+
Hide with class
+ +

ItemDetail is in the DOM but hidden

+ + +
Show with style
+
Hide with style
+ + + +
+

NgFor Binding

+ +
+ +
{{item.name}}
+ +
+ +

*ngFor with ItemDetailComponent element

+
+ + + +
+ + +

*ngFor with index

+

with semi-colon separator

+
+ +
{{i + 1}} - {{item.name}}
+ +
+ +

with comma separator

+
+
{{i + 1}} - {{item.name}}
+
+ +

*ngFor trackBy

+ + + + +

without trackBy

+
+
({{item.id}}) {{item.name}}
+ +
+ Item DOM elements change #{{itemsNoTrackByCount}} without trackBy +
+
+ +

with trackBy

+
+
({{item.id}}) {{item.name}}
+ +
+ Item DOM elements change #{{itemsWithTrackByCount}} with trackBy +
+
+ +


+ +

with trackBy and semi-colon separator

+
+ +
+ ({{item.id}}) {{item.name}} +
+ +
+ +

with trackBy and comma separator

+
+
({{item.id}}) {{item.name}}
+
+ +

with trackBy and space separator

+
+
({{item.id}}) {{item.name}}
+
+ +

with generic trackById function

+
+
({{item.id}}) {{item.name}}
+
+ +

NgSwitch Binding

+ +

Pick your favorite item

+
+ +
+ + +
+ + + + + + +
Are you as bright as {{currentItem.name}}?
+ + + +
+ + diff --git a/aio/content/examples/built-in-directives/src/app/app.component.ts b/aio/content/examples/built-in-directives/src/app/app.component.ts new file mode 100644 index 0000000000..36b75f60b7 --- /dev/null +++ b/aio/content/examples/built-in-directives/src/app/app.component.ts @@ -0,0 +1,115 @@ +import { Component, OnInit } from '@angular/core'; +import { Item } from './item'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'] +}) +export class AppComponent implements OnInit { + + canSave = true; + isSpecial = true; + isUnchanged = true; + + isActive = true; + nullCustomer = null; + currentCustomer = { + name: 'Laura' + }; + + item: Item; // defined to demonstrate template context precedence + items: Item[]; + + currentItem: Item; + + + // trackBy change counting + itemsNoTrackByCount = 0; + itemsWithTrackByCount = 0; + itemsWithTrackByCountReset = 0; + itemIdIncrement = 1; + + ngOnInit() { + this.resetItems(); + this.setCurrentClasses(); + this.setCurrentStyles(); + this.itemsNoTrackByCount = 0; + } + + setUppercaseName(name: string) { + this.currentItem.name = name.toUpperCase(); + } + +// #docregion setClasses + currentClasses: {}; + setCurrentClasses() { + // CSS classes: added/removed per current state of component properties + this.currentClasses = { + 'saveable': this.canSave, + 'modified': !this.isUnchanged, + 'special': this.isSpecial + }; + } + // #enddocregion setClasses + + // #docregion setStyles + currentStyles: {}; + setCurrentStyles() { + // CSS styles: set per current state of component properties + this.currentStyles = { + 'font-style': this.canSave ? 'italic' : 'normal', + 'font-weight': !this.isUnchanged ? 'bold' : 'normal', + 'font-size': this.isSpecial ? '24px' : '12px' + }; + } + // #enddocregion setStyles + + isActiveToggle() { + this.isActive = !this.isActive; + } + + giveNullCustomerValue() { + !(this.nullCustomer = null) ? (this.nullCustomer = 'Kelly') : (this.nullCustomer = null); + } + + resetNullItem() { + this.nullCustomer = null; + } + + resetItems() { + this.items = Item.items.map(item => item.clone()); + this.currentItem = this.items[0]; + this.item = this.currentItem; + } + + resetList() { + this.resetItems() + this.itemsWithTrackByCountReset = 0; + this.itemsNoTrackByCount = ++this.itemsNoTrackByCount; + } + + changeIds() { + + this.items.forEach(i => i.id += 1 * this.itemIdIncrement); + this.itemsWithTrackByCountReset = -1; + this.itemsNoTrackByCount = ++this.itemsNoTrackByCount; + this.itemsWithTrackByCount = ++this.itemsWithTrackByCount; + } + + clearTrackByCounts() { + this.resetItems(); + this.itemsNoTrackByCount = 0; + this.itemsWithTrackByCount = 0; + this.itemIdIncrement = 1; + } +// #docregion trackByItems + trackByItems(index: number, item: Item): number { return item.id; } +// #enddocregion trackByItems + + trackById(index: number, item: any): number { return item['id']; } + +} + + + diff --git a/aio/content/examples/built-in-directives/src/app/app.module.ts b/aio/content/examples/built-in-directives/src/app/app.module.ts new file mode 100644 index 0000000000..2aa14debe3 --- /dev/null +++ b/aio/content/examples/built-in-directives/src/app/app.module.ts @@ -0,0 +1,34 @@ +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; +// #docregion import-forms-module +import { FormsModule } from '@angular/forms'; // <--- JavaScript import from Angular +// #enddocregion import-forms-module + + +import { AppComponent } from './app.component'; +import { ItemDetailComponent } from './item-detail/item-detail.component'; +import { ItemSwitchComponents } from './item-switch.component'; + + +// #docregion import-forms-module +@NgModule({ + // #enddocregion import-forms-module + declarations: [ + AppComponent, + ItemDetailComponent, + ItemSwitchComponents + ], + // #docregion import-forms-module + + imports: [ + BrowserModule, + FormsModule // <--- import into the NgModule + ], + // #enddocregion import-forms-module + providers: [], + bootstrap: [AppComponent] + // #docregion import-forms-module +}) +export class AppModule { } +// #enddocregion import-forms-module + diff --git a/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.css b/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.html b/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.html new file mode 100644 index 0000000000..3586d503af --- /dev/null +++ b/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.html @@ -0,0 +1,3 @@ +
+ {{item?.name}} +
diff --git a/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.spec.ts b/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.spec.ts new file mode 100644 index 0000000000..7559cb65f6 --- /dev/null +++ b/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ItemDetailComponent } from './item-detail.component'; + +describe('ItemDetailComponent', () => { + let component: ItemDetailComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ItemDetailComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ItemDetailComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.ts b/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.ts new file mode 100644 index 0000000000..a2f4379aa6 --- /dev/null +++ b/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.ts @@ -0,0 +1,17 @@ +import { Component, Input } from '@angular/core'; + +import { Item } from '../item'; + +@Component({ + selector: 'app-item-detail', + templateUrl: './item-detail.component.html', + styleUrls: ['./item-detail.component.css'] +}) +export class ItemDetailComponent { + + + @Input() item: Item; + + constructor() { } + +} diff --git a/aio/content/examples/built-in-directives/src/app/item-switch.component.ts b/aio/content/examples/built-in-directives/src/app/item-switch.component.ts new file mode 100644 index 0000000000..b40d5c9af5 --- /dev/null +++ b/aio/content/examples/built-in-directives/src/app/item-switch.component.ts @@ -0,0 +1,50 @@ +import { Component, Input } from '@angular/core'; +import { Item } from './item'; + +@Component({ + selector: 'app-stout-item', + template: `I'm a little {{item.name}}, short and stout!` +}) +export class StoutItemComponent { + @Input() item: Item; +} + +@Component({ + selector: 'app-best-item', + template: `This is the brightest {{item.name}} in town.` +}) +export class BestItemComponent { + @Input() item: Item; +} + +@Component({ + selector: 'app-device-item', + template: `Which is the slimmest {{item.name}}?` +}) +export class DeviceItemComponent { + @Input() item: Item; +} + +@Component({ + selector: 'app-lost-item', + template: `Has anyone seen my {{item.name}}?` +}) +export class LostItemComponent { + @Input() item: Item; +} + +@Component({ + selector: 'app-unknown-item', + template: `{{message}}` +}) +export class UnknownItemComponent { + @Input() item: Item; + get message() { + return this.item && this.item.name ? + `${this.item.name} is strange and mysterious.` : + 'A mystery wrapped in a fishbowl.'; + } +} + +export const ItemSwitchComponents = + [ StoutItemComponent, BestItemComponent, DeviceItemComponent, LostItemComponent, UnknownItemComponent ]; diff --git a/aio/content/examples/built-in-directives/src/app/item.ts b/aio/content/examples/built-in-directives/src/app/item.ts new file mode 100644 index 0000000000..c5bffa1a20 --- /dev/null +++ b/aio/content/examples/built-in-directives/src/app/item.ts @@ -0,0 +1,30 @@ +export class Item { + static nextId = 0; + + static items: Item[] = [ + new Item( + null, + 'Teapot', + 'stout' + ), + new Item(1, 'Lamp', 'bright'), + new Item(2, 'Phone', 'slim' ), + new Item(3, 'Television', 'vintage' ), + new Item(4, 'Fishbowl') + ]; + + + constructor( + public id?: number, + public name?: string, + public feature?: string, + public url?: string, + public rate = 100, + ) { + this.id = id ? id : Item.nextId++; + } + + clone(): Item { + return Object.assign(new Item(), this); + } +} diff --git a/aio/content/examples/built-in-directives/src/index.html b/aio/content/examples/built-in-directives/src/index.html new file mode 100644 index 0000000000..c501fb93bf --- /dev/null +++ b/aio/content/examples/built-in-directives/src/index.html @@ -0,0 +1,14 @@ + + + + + BuiltInDirectives + + + + + + + + + diff --git a/aio/content/examples/built-in-directives/src/main.ts b/aio/content/examples/built-in-directives/src/main.ts new file mode 100644 index 0000000000..91ec6da5f0 --- /dev/null +++ b/aio/content/examples/built-in-directives/src/main.ts @@ -0,0 +1,12 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.log(err)); diff --git a/aio/content/examples/built-in-directives/stackblitz.json b/aio/content/examples/built-in-directives/stackblitz.json new file mode 100644 index 0000000000..6824495335 --- /dev/null +++ b/aio/content/examples/built-in-directives/stackblitz.json @@ -0,0 +1,10 @@ +{ + "description": "Built-in Directives", + "files": [ + "!**/*.d.ts", + "!**/*.js", + "!**/*.[1,2].*" + ], + "file": "src/app/app.component.ts", + "tags": ["Built-in Directives"] +} diff --git a/aio/content/examples/component-interaction/src/app/countdown-parent.component.ts b/aio/content/examples/component-interaction/src/app/countdown-parent.component.ts index 57f7230d89..9f4e5bd4df 100644 --- a/aio/content/examples/component-interaction/src/app/countdown-parent.component.ts +++ b/aio/content/examples/component-interaction/src/app/countdown-parent.component.ts @@ -39,7 +39,7 @@ export class CountdownLocalVarParentComponent { } }) export class CountdownViewChildParentComponent implements AfterViewInit { - @ViewChild(CountdownTimerComponent, {static: false}) + @ViewChild(CountdownTimerComponent) private timerComponent: CountdownTimerComponent; seconds() { return 0; } diff --git a/aio/content/examples/component-interaction/src/app/hero.ts b/aio/content/examples/component-interaction/src/app/hero.ts index 3e80ad51c2..676f2e23b4 100644 --- a/aio/content/examples/component-interaction/src/app/hero.ts +++ b/aio/content/examples/component-interaction/src/app/hero.ts @@ -1,4 +1,4 @@ -export class Hero { +export interface Hero { name: string; } diff --git a/aio/content/examples/dependency-injection/src/app/heroes/hero.ts b/aio/content/examples/dependency-injection/src/app/heroes/hero.ts index 5c49328241..1128cf6be2 100644 --- a/aio/content/examples/dependency-injection/src/app/heroes/hero.ts +++ b/aio/content/examples/dependency-injection/src/app/heroes/hero.ts @@ -1,6 +1,6 @@ // #docregion -export class Hero { +export interface Hero { id: number; name: string; - isSecret = false; + isSecret: boolean; } diff --git a/aio/content/examples/docs-style-guide/src/app/hero.ts b/aio/content/examples/docs-style-guide/src/app/hero.ts index e1fc2f4fa9..e76ad2b900 100644 --- a/aio/content/examples/docs-style-guide/src/app/hero.ts +++ b/aio/content/examples/docs-style-guide/src/app/hero.ts @@ -1,4 +1,4 @@ -export class Hero { +export interface Hero { id: number; name: string; } diff --git a/aio/content/examples/dynamic-component-loader/src/app/ad-banner.component.ts b/aio/content/examples/dynamic-component-loader/src/app/ad-banner.component.ts index a802371a30..faf03803d7 100644 --- a/aio/content/examples/dynamic-component-loader/src/app/ad-banner.component.ts +++ b/aio/content/examples/dynamic-component-loader/src/app/ad-banner.component.ts @@ -36,14 +36,14 @@ export class AdBannerComponent implements OnInit, OnDestroy { loadComponent() { this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length; - let adItem = this.ads[this.currentAdIndex]; + const adItem = this.ads[this.currentAdIndex]; - let componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component); + const componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component); - let viewContainerRef = this.adHost.viewContainerRef; + const viewContainerRef = this.adHost.viewContainerRef; viewContainerRef.clear(); - let componentRef = viewContainerRef.createComponent(componentFactory); + const componentRef = viewContainerRef.createComponent(componentFactory); (componentRef.instance).data = adItem.data; } diff --git a/aio/content/examples/dynamic-form/src/app/app.component.ts b/aio/content/examples/dynamic-form/src/app/app.component.ts index 51d154cc78..d8e9dd7e29 100644 --- a/aio/content/examples/dynamic-form/src/app/app.component.ts +++ b/aio/content/examples/dynamic-form/src/app/app.component.ts @@ -2,21 +2,23 @@ import { Component } from '@angular/core'; import { QuestionService } from './question.service'; +import { QuestionBase } from './question-base'; +import { Observable } from 'rxjs'; @Component({ selector: 'app-root', template: `

Job Application for Heroes

- +
`, providers: [QuestionService] }) export class AppComponent { - questions: any[]; + questions$: Observable[]>; constructor(service: QuestionService) { - this.questions = service.getQuestions(); + this.questions$ = service.getQuestions(); } } diff --git a/aio/content/examples/dynamic-form/src/app/dynamic-form-question.component.html b/aio/content/examples/dynamic-form/src/app/dynamic-form-question.component.html index 9f1b8cd4a6..e9ae3c8446 100644 --- a/aio/content/examples/dynamic-form/src/app/dynamic-form-question.component.html +++ b/aio/content/examples/dynamic-form/src/app/dynamic-form-question.component.html @@ -11,7 +11,7 @@ -
+
{{question.label}} is required
diff --git a/aio/content/examples/dynamic-form/src/app/dynamic-form-question.component.ts b/aio/content/examples/dynamic-form/src/app/dynamic-form-question.component.ts index 9a4c25829f..988e4fb39c 100644 --- a/aio/content/examples/dynamic-form/src/app/dynamic-form-question.component.ts +++ b/aio/content/examples/dynamic-form/src/app/dynamic-form-question.component.ts @@ -9,7 +9,7 @@ import { QuestionBase } from './question-base'; templateUrl: './dynamic-form-question.component.html' }) export class DynamicFormQuestionComponent { - @Input() question: QuestionBase; + @Input() question: QuestionBase; @Input() form: FormGroup; get isValid() { return this.form.controls[this.question.key].valid; } } diff --git a/aio/content/examples/dynamic-form/src/app/dynamic-form.component.ts b/aio/content/examples/dynamic-form/src/app/dynamic-form.component.ts index 4167b4617f..cca09063e3 100644 --- a/aio/content/examples/dynamic-form/src/app/dynamic-form.component.ts +++ b/aio/content/examples/dynamic-form/src/app/dynamic-form.component.ts @@ -12,7 +12,7 @@ import { QuestionControlService } from './question-control.service'; }) export class DynamicFormComponent implements OnInit { - @Input() questions: QuestionBase[] = []; + @Input() questions: QuestionBase[] = []; form: FormGroup; payLoad = ''; @@ -23,6 +23,6 @@ export class DynamicFormComponent implements OnInit { } onSubmit() { - this.payLoad = JSON.stringify(this.form.value); + this.payLoad = JSON.stringify(this.form.getRawValue()); } } diff --git a/aio/content/examples/dynamic-form/src/app/question-base.ts b/aio/content/examples/dynamic-form/src/app/question-base.ts index 8249a38bee..8edc0dcfdc 100644 --- a/aio/content/examples/dynamic-form/src/app/question-base.ts +++ b/aio/content/examples/dynamic-form/src/app/question-base.ts @@ -6,6 +6,8 @@ export class QuestionBase { required: boolean; order: number; controlType: string; + type: string; + options: {key: string, value: string}[]; constructor(options: { value?: T, @@ -13,7 +15,8 @@ export class QuestionBase { label?: string, required?: boolean, order?: number, - controlType?: string + controlType?: string, + type?: string } = {}) { this.value = options.value; this.key = options.key || ''; @@ -21,5 +24,6 @@ export class QuestionBase { this.required = !!options.required; this.order = options.order === undefined ? 1 : options.order; this.controlType = options.controlType || ''; + this.type = options.type || ''; } } diff --git a/aio/content/examples/dynamic-form/src/app/question-control.service.ts b/aio/content/examples/dynamic-form/src/app/question-control.service.ts index 1378ba8490..1ca0727055 100644 --- a/aio/content/examples/dynamic-form/src/app/question-control.service.ts +++ b/aio/content/examples/dynamic-form/src/app/question-control.service.ts @@ -8,7 +8,7 @@ import { QuestionBase } from './question-base'; export class QuestionControlService { constructor() { } - toFormGroup(questions: QuestionBase[] ) { + toFormGroup(questions: QuestionBase[] ) { let group: any = {}; questions.forEach(question => { diff --git a/aio/content/examples/dynamic-form/src/app/question.service.ts b/aio/content/examples/dynamic-form/src/app/question.service.ts index a1d9499c68..7f80dd78c1 100644 --- a/aio/content/examples/dynamic-form/src/app/question.service.ts +++ b/aio/content/examples/dynamic-form/src/app/question.service.ts @@ -4,15 +4,15 @@ import { Injectable } from '@angular/core'; import { DropdownQuestion } from './question-dropdown'; import { QuestionBase } from './question-base'; import { TextboxQuestion } from './question-textbox'; +import { of } from 'rxjs'; @Injectable() export class QuestionService { // TODO: get from a remote source of question metadata - // TODO: make asynchronous getQuestions() { - let questions: QuestionBase[] = [ + let questions: QuestionBase[] = [ new DropdownQuestion({ key: 'brave', @@ -42,6 +42,6 @@ export class QuestionService { }) ]; - return questions.sort((a, b) => a.order - b.order); + return of(questions.sort((a, b) => a.order - b.order)); } } diff --git a/aio/content/examples/event-binding/src/app/app.component.ts b/aio/content/examples/event-binding/src/app/app.component.ts index 69a76d6669..e8e7882d89 100644 --- a/aio/content/examples/event-binding/src/app/app.component.ts +++ b/aio/content/examples/event-binding/src/app/app.component.ts @@ -18,7 +18,7 @@ export class AppComponent { } deleteItem(item: Item) { - alert(`Delete the ${item}.`); + alert(`Delete the ${item.name}.`); } onClickMe(event?: KeyboardEvent) { diff --git a/aio/content/examples/form-validation/src/app/shared/alter-ego.directive.ts b/aio/content/examples/form-validation/src/app/shared/alter-ego.directive.ts index f8230e3195..bf08aa6bd3 100644 --- a/aio/content/examples/form-validation/src/app/shared/alter-ego.directive.ts +++ b/aio/content/examples/form-validation/src/app/shared/alter-ego.directive.ts @@ -7,7 +7,7 @@ import { } from '@angular/forms'; import { catchError, map } from 'rxjs/operators'; import { HeroesService } from './heroes.service'; -import { Observable } from 'rxjs'; +import { Observable, of } from 'rxjs'; // #docregion async-validator @Injectable({ providedIn: 'root' }) @@ -19,7 +19,7 @@ export class UniqueAlterEgoValidator implements AsyncValidator { ): Promise | Observable { return this.heroesService.isAlterEgoTaken(ctrl.value).pipe( map(isTaken => (isTaken ? { uniqueAlterEgo: true } : null)), - catchError(() => null) + catchError(() => of(null)) ); } } diff --git a/aio/content/examples/getting-started/src/app/app.module.ts b/aio/content/examples/getting-started/src/app/app.module.ts index fd49de191f..36a43eefc2 100644 --- a/aio/content/examples/getting-started/src/app/app.module.ts +++ b/aio/content/examples/getting-started/src/app/app.module.ts @@ -1,8 +1,8 @@ // #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'; +// #docregion http-client-module-import import { HttpClientModule } from '@angular/common/http'; // #enddocregion http-client-module-import import { ReactiveFormsModule } from '@angular/forms'; @@ -12,7 +12,6 @@ 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'; diff --git a/aio/content/examples/getting-started/src/app/cart/cart.component.3.ts b/aio/content/examples/getting-started/src/app/cart/cart.component.3.ts index 9f7847ab0a..fc44540f4d 100644 --- a/aio/content/examples/getting-started/src/app/cart/cart.component.3.ts +++ b/aio/content/examples/getting-started/src/app/cart/cart.component.3.ts @@ -1,6 +1,6 @@ // #docplaster // #docregion imports -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { CartService } from '../cart.service'; // #enddocregion imports @@ -10,12 +10,14 @@ import { CartService } from '../cart.service'; styleUrls: ['./cart.component.css'] }) // #docregion props-services, submit -export class CartComponent { +export class CartComponent implements OnInit { items; constructor( private cartService: CartService - ) { + ) { } + + ngOnInit() { this.items = this.cartService.getItems(); } } diff --git a/aio/content/examples/getting-started/src/app/cart/cart.component.html b/aio/content/examples/getting-started/src/app/cart/cart.component.html index 060e9d8823..b2b825c694 100644 --- a/aio/content/examples/getting-started/src/app/cart/cart.component.html +++ b/aio/content/examples/getting-started/src/app/cart/cart.component.html @@ -16,16 +16,20 @@
- - + +
- - + +
- + diff --git a/aio/content/examples/getting-started/src/app/cart/cart.component.ts b/aio/content/examples/getting-started/src/app/cart/cart.component.ts index cf7f31a4f4..09165b0324 100644 --- a/aio/content/examples/getting-started/src/app/cart/cart.component.ts +++ b/aio/content/examples/getting-started/src/app/cart/cart.component.ts @@ -1,6 +1,6 @@ // #docplaster // #docregion imports -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { FormBuilder } from '@angular/forms'; import { CartService } from '../cart.service'; @@ -12,7 +12,7 @@ import { CartService } from '../cart.service'; styleUrls: ['./cart.component.css'] }) // #docregion props-services, submit, inject-form-builder, checkout-form, checkout-form-group -export class CartComponent { +export class CartComponent implements OnInit { items; // #enddocregion inject-form-builder checkoutForm; @@ -24,14 +24,16 @@ export class CartComponent { private formBuilder: FormBuilder, ) { // #enddocregion inject-form-builder - this.items = this.cartService.getItems(); - this.checkoutForm = this.formBuilder.group({ name: '', address: '' }); // #docregion inject-form-builder } + + ngOnInit() { + this.items = this.cartService.getItems(); + } // #enddocregion inject-form-builder, checkout-form-group // #enddocregion props-services diff --git a/aio/content/examples/getting-started/src/app/shipping/shipping.component.ts b/aio/content/examples/getting-started/src/app/shipping/shipping.component.ts index 6a04bcb55e..95a58b6f1b 100644 --- a/aio/content/examples/getting-started/src/app/shipping/shipping.component.ts +++ b/aio/content/examples/getting-started/src/app/shipping/shipping.component.ts @@ -1,6 +1,6 @@ // #docplaster // #docregion imports -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { CartService } from '../cart.service'; // #enddocregion @@ -11,7 +11,7 @@ import { CartService } from '../cart.service'; styleUrls: ['./shipping.component.css'] }) // #docregion props, ctor -export class ShippingComponent { +export class ShippingComponent implements OnInit { shippingCosts; // #enddocregion props @@ -19,10 +19,12 @@ export class ShippingComponent { constructor( private cartService: CartService ) { -// #enddocregion inject-cart-service - this.shippingCosts = this.cartService.getShippingPrices(); -// #docregion inject-cart-service } // #enddocregion inject-cart-service + + ngOnInit() { + this.shippingCosts = this.cartService.getShippingPrices(); + } + // #docregion props } diff --git a/aio/content/examples/getting-started/tsconfig.0.json b/aio/content/examples/getting-started/tsconfig.0.json new file mode 100644 index 0000000000..58d3db1566 --- /dev/null +++ b/aio/content/examples/getting-started/tsconfig.0.json @@ -0,0 +1,29 @@ +// This tsconfig is used in the TypeScript +// configuration guide (../guide/typescript-configuration.md) +// to display the latest default configuration +// Note: Update with every major release to the latest default +// #docregion +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "sourceMap": true, + "declaration": false, + "module": "esnext", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "importHelpers": true, + "target": "es2015", + "typeRoots": [ + "node_modules/@types" + ], +// #docregion lib + "lib": [ + "es2018", + "dom" + ] +// #enddocregion lib + } +} diff --git a/aio/content/examples/hierarchical-dependency-injection/src/app/hero.ts b/aio/content/examples/hierarchical-dependency-injection/src/app/hero.ts index 4ad6ccd8eb..9f05cb6cff 100644 --- a/aio/content/examples/hierarchical-dependency-injection/src/app/hero.ts +++ b/aio/content/examples/hierarchical-dependency-injection/src/app/hero.ts @@ -1,6 +1,6 @@ // #docregion -export class Hero { +export interface Hero { id: number; name: string; tid: string; // tax id diff --git a/aio/content/examples/http/specs.stackblitz.json b/aio/content/examples/http/specs.stackblitz.json index 1442c98f3a..68c0874f18 100644 --- a/aio/content/examples/http/specs.stackblitz.json +++ b/aio/content/examples/http/specs.stackblitz.json @@ -1,6 +1,7 @@ { "description": "Http Guide Testing", "files":[ + "src/app/heroes/hero.ts", "src/app/heroes/heroes.service.ts", "src/app/heroes/heroes.service.spec.ts", diff --git a/aio/content/examples/http/src/app/app.component.html b/aio/content/examples/http/src/app/app.component.html index e5d5dec909..21acf52793 100644 --- a/aio/content/examples/http/src/app/app.component.html +++ b/aio/content/examples/http/src/app/app.component.html @@ -1,6 +1,6 @@

HTTP Sample

- + diff --git a/aio/content/examples/http/src/app/heroes/heroes.component.ts b/aio/content/examples/http/src/app/heroes/heroes.component.ts index d44f80e9ff..7b7547aec8 100644 --- a/aio/content/examples/http/src/app/heroes/heroes.component.ts +++ b/aio/content/examples/http/src/app/heroes/heroes.component.ts @@ -6,14 +6,14 @@ import { HeroesService } from './heroes.service'; @Component({ selector: 'app-heroes', templateUrl: './heroes.component.html', - providers: [ HeroesService ], + providers: [HeroesService], styleUrls: ['./heroes.component.css'] }) export class HeroesComponent implements OnInit { heroes: Hero[]; editHero: Hero; // the hero currently being edited - constructor(private heroesService: HeroesService) { } + constructor(private heroesService: HeroesService) {} ngOnInit() { this.getHeroes(); @@ -21,18 +21,21 @@ export class HeroesComponent implements OnInit { getHeroes(): void { this.heroesService.getHeroes() - .subscribe(heroes => this.heroes = heroes); + .subscribe(heroes => (this.heroes = heroes)); } add(name: string): void { this.editHero = undefined; name = name.trim(); - if (!name) { return; } + if (!name) { + return; + } // The server will generate the id for this new hero const newHero: Hero = { name } as Hero; // #docregion add-hero-subscribe - this.heroesService.addHero(newHero) + this.heroesService + .addHero(newHero) .subscribe(hero => this.heroes.push(hero)); // #enddocregion add-hero-subscribe } @@ -40,7 +43,9 @@ export class HeroesComponent implements OnInit { delete(hero: Hero): void { this.heroes = this.heroes.filter(h => h !== hero); // #docregion delete-hero-subscribe - this.heroesService.deleteHero(hero.id).subscribe(); + this.heroesService + .deleteHero(hero.id) + .subscribe(); // #enddocregion delete-hero-subscribe /* // #docregion delete-hero-no-subscribe @@ -50,26 +55,30 @@ export class HeroesComponent implements OnInit { */ } - edit(hero) { + edit(hero: Hero) { this.editHero = hero; } search(searchTerm: string) { this.editHero = undefined; if (searchTerm) { - this.heroesService.searchHeroes(searchTerm) - .subscribe(heroes => this.heroes = heroes); + this.heroesService + .searchHeroes(searchTerm) + .subscribe(heroes => (this.heroes = heroes)); } } update() { if (this.editHero) { - this.heroesService.updateHero(this.editHero) + this.heroesService + .updateHero(this.editHero) .subscribe(hero => { - // replace the hero in the heroes list with update from server - const ix = hero ? this.heroes.findIndex(h => h.id === hero.id) : -1; - if (ix > -1) { this.heroes[ix] = hero; } - }); + // replace the hero in the heroes list with update from server + const ix = hero ? this.heroes.findIndex(h => h.id === hero.id) : -1; + if (ix > -1) { + this.heroes[ix] = hero; + } + }); this.editHero = undefined; } } diff --git a/aio/content/examples/http/src/app/package-search/package-search.service.ts b/aio/content/examples/http/src/app/package-search/package-search.service.ts index b026e03e06..a1ef8cc26b 100644 --- a/aio/content/examples/http/src/app/package-search/package-search.service.ts +++ b/aio/content/examples/http/src/app/package-search/package-search.service.ts @@ -48,7 +48,7 @@ export class PackageSearchService { // TODO: Add error handling return this.http.get(searchUrl, options).pipe( map((data: any) => { - return data.results.map(entry => ({ + return data.results.map((entry: any) => ({ name: entry.name[0], version: entry.version[0], description: entry.description[0] diff --git a/aio/content/examples/http/src/main.ts b/aio/content/examples/http/src/main.ts index 6b6532d428..0740658908 100644 --- a/aio/content/examples/http/src/main.ts +++ b/aio/content/examples/http/src/main.ts @@ -1,5 +1,12 @@ // #docregion +import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/aio/content/examples/http/src/testing/http-client.spec.ts b/aio/content/examples/http/src/testing/http-client.spec.ts index e98bc7562e..f13c15a18b 100644 --- a/aio/content/examples/http/src/testing/http-client.spec.ts +++ b/aio/content/examples/http/src/testing/http-client.spec.ts @@ -67,6 +67,7 @@ describe('HttpClient testing', () => { httpTestingController.verify(); }); // #enddocregion get-test + it('can test HttpClient.get with matching header', () => { const testData: Data = {name: 'Test Data'}; diff --git a/aio/content/examples/http/stackblitz.json b/aio/content/examples/http/stackblitz.json index 6ef625c1a0..5d24738b29 100644 --- a/aio/content/examples/http/stackblitz.json +++ b/aio/content/examples/http/stackblitz.json @@ -5,7 +5,8 @@ "!**/*.js", "!src/testing/*.*", - "!src/index-specs.html" + "!src/index-specs.html", + "!src/main-specs.ts" ], "tags": ["http"] } diff --git a/aio/content/examples/i18n/doc-files/app.locale_data.ts b/aio/content/examples/i18n/doc-files/app.locale_data.ts index 05c83be034..6e77ea039f 100644 --- a/aio/content/examples/i18n/doc-files/app.locale_data.ts +++ b/aio/content/examples/i18n/doc-files/app.locale_data.ts @@ -2,6 +2,6 @@ import { registerLocaleData } from '@angular/common'; import localeFr from '@angular/common/locales/fr'; -// the second parameter 'fr' is optional -registerLocaleData(localeFr, 'fr'); +// the second parameter 'fr-FR' is optional +registerLocaleData(localeFr, 'fr-FR'); // #enddocregion import-locale diff --git a/aio/content/examples/i18n/doc-files/main.2.ts b/aio/content/examples/i18n/doc-files/main.2.ts index 0b68bc10fe..5807e7b40f 100644 --- a/aio/content/examples/i18n/doc-files/main.2.ts +++ b/aio/content/examples/i18n/doc-files/main.2.ts @@ -12,7 +12,7 @@ if (environment.production) { // use the require method provided by webpack declare const require; // we use the webpack raw-loader to return the content as a string -const translations = require(`raw-loader!./locale/messages.fr.xlf`); +const translations = require('raw-loader!./locale/messages.fr.xlf').default; platformBrowserDynamic().bootstrapModule(AppModule, { providers: [ diff --git a/aio/content/examples/i18n/src/app/app.component.ts b/aio/content/examples/i18n/src/app/app.component.ts index d8e79acf50..147246e912 100644 --- a/aio/content/examples/i18n/src/app/app.component.ts +++ b/aio/content/examples/i18n/src/app/app.component.ts @@ -10,7 +10,6 @@ export class AppComponent { gender = 'female'; fly = true; logo = 'https://angular.io/assets/images/logos/angular/angular.png'; - heroes: string[] = ['Magneta', 'Celeritas', 'Dynama']; inc(i: number) { this.minutes = Math.min(5, Math.max(0, this.minutes + i)); } diff --git a/aio/content/examples/inputs-outputs/e2e/src/app.e2e-spec.ts b/aio/content/examples/inputs-outputs/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000000..d62786fff5 --- /dev/null +++ b/aio/content/examples/inputs-outputs/e2e/src/app.e2e-spec.ts @@ -0,0 +1,70 @@ +'use strict'; + +import { browser, element, by } from 'protractor'; +import { logging } from 'selenium-webdriver'; + +describe('Inputs and Outputs', function () { + + + beforeEach(() => { + browser.get(''); + }); + + + // helper function used to test what's logged to the console + async function logChecker(button, contents) { + const logs = await browser + .manage() + .logs() + .get(logging.Type.BROWSER); + const message = logs.filter(({ message }) => + message.indexOf(contents) !== -1 ? true : false + ); + console.log(message); + expect(message.length).toBeGreaterThan(0); + } + + it('should have title Inputs and Outputs', function () { + let title = element.all(by.css('h1')).get(0); + expect(title.getText()).toEqual('Inputs and Outputs'); + }); + + it('should add 123 to the parent list', async () => { + let addToParentButton = element.all(by.css('button')).get(0); + let addToListInput = element.all(by.css('input')).get(0); + let addedItem = element.all(by.css('li')).get(4); + await addToListInput.sendKeys('123'); + await addToParentButton.click(); + expect(addedItem.getText()).toEqual('123'); + }); + + it('should delete item', async () => { + let deleteButton = element.all(by.css('button')).get(1); + const contents = 'Child'; + await deleteButton.click(); + await logChecker(deleteButton, contents); + }); + + it('should log buy the item', async () => { + let buyButton = element.all(by.css('button')).get(2); + const contents = 'Child'; + await buyButton.click(); + await logChecker(buyButton, contents); + }); + + it('should save item for later', async () => { + let saveButton = element.all(by.css('button')).get(3); + const contents = 'Child'; + await saveButton.click(); + await logChecker(saveButton, contents); + }); + + it('should add item to wishlist', async () => { + let addToParentButton = element.all(by.css('button')).get(4); + let addedItem = element.all(by.css('li')).get(6); + await addToParentButton.click(); + expect(addedItem.getText()).toEqual('Television'); + }); + +}); + diff --git a/aio/content/examples/inputs-outputs/example-config.json b/aio/content/examples/inputs-outputs/example-config.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/inputs-outputs/src/app/aliasing/aliasing.component.css b/aio/content/examples/inputs-outputs/src/app/aliasing/aliasing.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/inputs-outputs/src/app/aliasing/aliasing.component.html b/aio/content/examples/inputs-outputs/src/app/aliasing/aliasing.component.html new file mode 100644 index 0000000000..ae7da190a3 --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/aliasing/aliasing.component.html @@ -0,0 +1,7 @@ +

Save for later item: {{input1}}

+ + + +

Item for wishlist: {{input2}}

+ + diff --git a/aio/content/examples/inputs-outputs/src/app/aliasing/aliasing.component.spec.ts b/aio/content/examples/inputs-outputs/src/app/aliasing/aliasing.component.spec.ts new file mode 100644 index 0000000000..8f93c989bc --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/aliasing/aliasing.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AliasingComponent } from './aliasing.component'; + +describe('AliasingComponent', () => { + let component: AliasingComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AliasingComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AliasingComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/aio/content/examples/inputs-outputs/src/app/aliasing/aliasing.component.ts b/aio/content/examples/inputs-outputs/src/app/aliasing/aliasing.component.ts new file mode 100644 index 0000000000..8eed8bddbd --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/aliasing/aliasing.component.ts @@ -0,0 +1,46 @@ +/* tslint:disable:use-input-property-decorator */ +/* tslint:disable:use-output-property-decorator */ + +/* tslint:disable:no-input-rename */ + + +import { Component, EventEmitter, Input, Output } from '@angular/core'; + +@Component({ + selector: 'app-aliasing', + templateUrl: './aliasing.component.html', + styleUrls: ['./aliasing.component.css'], + // #docregion alias + // tslint:disable: no-inputs-metadata-property no-outputs-metadata-property + inputs: ['input1: saveForLaterItem'], // propertyName:alias + outputs: ['outputEvent1: saveForLaterEvent'] + // tslint:disable: no-inputs-metadata-property no-outputs-metadata-property + // #enddocregion alias + +}) +export class AliasingComponent { + + input1: string; + outputEvent1: EventEmitter = new EventEmitter(); + + // #docregion alias-input-output + @Input('wishListItem') input2: string; // @Input(alias) + @Output('wishEvent') outputEvent2 = new EventEmitter(); // @Output(alias) propertyName = ... + // #enddocregion alias-input-output + + + saveIt() { + console.warn('Child says: emiting outputEvent1 with', this.input1); + this.outputEvent1.emit(this.input1); + } + + wishForIt() { + console.warn('Child says: emiting outputEvent2', this.input2); + this.outputEvent2.emit(this.input2); + } + + +} +/* tslint:enable:use-input-property-decorator */ +/* tslint:enable:use-output-property-decorator */ + diff --git a/aio/content/examples/inputs-outputs/src/app/app.component.css b/aio/content/examples/inputs-outputs/src/app/app.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/inputs-outputs/src/app/app.component.html b/aio/content/examples/inputs-outputs/src/app/app.component.html new file mode 100644 index 0000000000..d4a67c3170 --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/app.component.html @@ -0,0 +1,45 @@ +

Inputs and Outputs

+ + + + +
+ + + + +

Parent component receiving value via @Output()

+ +
    +
  • {{item}}
  • +
+ +
+ +

Input and Output together

+

Open the console to see the EventEmitter at work when you click Delete.

+ + + + + +
+ +

Input and Output in the component class metadata

+

Open the console to see the EventEmitter at work when you click Buy.

+ + + + +
+ +

Aliasing Inputs and Outputs

+

See aliasing.component.ts for aliases and the console for the EventEmitter console logs.

+ + + +

Wishlist:

+
    +
  • {{wish}}
  • +
+ diff --git a/aio/content/examples/inputs-outputs/src/app/app.component.spec.ts b/aio/content/examples/inputs-outputs/src/app/app.component.spec.ts new file mode 100644 index 0000000000..bcbdf36b3e --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/app.component.spec.ts @@ -0,0 +1,27 @@ +import { TestBed, async } from '@angular/core/testing'; +import { AppComponent } from './app.component'; +describe('AppComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ + AppComponent + ], + }).compileComponents(); + })); + it('should create the app', async(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app).toBeTruthy(); + })); + it(`should have as title 'app'`, async(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app.title).toEqual('app'); + })); + it('should render title in a h1 tag', async(() => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.debugElement.nativeElement; + expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!'); + })); +}); diff --git a/aio/content/examples/inputs-outputs/src/app/app.component.ts b/aio/content/examples/inputs-outputs/src/app/app.component.ts new file mode 100644 index 0000000000..515cbbd595 --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/app.component.ts @@ -0,0 +1,55 @@ + +// #docplaster + +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'] +}) + +// #docregion parent-property +// #docregion add-new-item +export class AppComponent { +// #enddocregion add-new-item + currentItem = 'Television'; + // #enddocregion parent-property + + lastChanceItem = 'Beanbag'; +// #docregion add-new-item + items = ['item1', 'item2', 'item3', 'item4']; +// #enddocregion add-new-item + wishlist = ['Drone', 'Computer']; + + // #docregion add-new-item + + addItem(newItem: string) { + this.items.push(newItem); + } + // #enddocregion add-new-item + + + crossOffItem(item: string) { + console.warn(`Parent says: crossing off ${item}.`); + } + + buyClearanceItem(item) { + console.warn(`Parent says: buying ${item}.`); + } + + saveForLater(item) { + console.warn(`Parent says: saving ${item} for later.`); + } + + addToWishList(wish: string) { + console.warn(`Parent says: adding ${this.currentItem} to your wishlist.`); + this.wishlist.push(wish); + console.warn(this.wishlist); + } +// #docregion add-new-item +// #docregion parent-property +} +// #enddocregion add-new-item +// #enddocregion parent-property + diff --git a/aio/content/examples/inputs-outputs/src/app/app.module.ts b/aio/content/examples/inputs-outputs/src/app/app.module.ts new file mode 100644 index 0000000000..b5cc72fdcd --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/app.module.ts @@ -0,0 +1,28 @@ +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; + + +import { AppComponent } from './app.component'; +import { ItemDetailComponent } from './item-detail/item-detail.component'; +import { ItemOutputComponent } from './item-output/item-output.component'; +import { InputOutputComponent } from './input-output/input-output.component'; +import { InTheMetadataComponent } from './in-the-metadata/in-the-metadata.component'; +import { AliasingComponent } from './aliasing/aliasing.component'; + + +@NgModule({ + declarations: [ + AppComponent, + ItemDetailComponent, + ItemOutputComponent, + InputOutputComponent, + InTheMetadataComponent, + AliasingComponent + ], + imports: [ + BrowserModule + ], + providers: [], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/aio/content/examples/inputs-outputs/src/app/in-the-metadata/in-the-metadata.component.css b/aio/content/examples/inputs-outputs/src/app/in-the-metadata/in-the-metadata.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/inputs-outputs/src/app/in-the-metadata/in-the-metadata.component.html b/aio/content/examples/inputs-outputs/src/app/in-the-metadata/in-the-metadata.component.html new file mode 100644 index 0000000000..960e4f16e5 --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/in-the-metadata/in-the-metadata.component.html @@ -0,0 +1,3 @@ +

Latest clearance item: {{clearanceItem}}

+ + diff --git a/aio/content/examples/inputs-outputs/src/app/in-the-metadata/in-the-metadata.component.spec.ts b/aio/content/examples/inputs-outputs/src/app/in-the-metadata/in-the-metadata.component.spec.ts new file mode 100644 index 0000000000..eaa33528a9 --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/in-the-metadata/in-the-metadata.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InTheMetadataComponent } from './in-the-metadata.component'; + +describe('InTheMetadataComponent', () => { + let component: InTheMetadataComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ InTheMetadataComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(InTheMetadataComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/aio/content/examples/inputs-outputs/src/app/in-the-metadata/in-the-metadata.component.ts b/aio/content/examples/inputs-outputs/src/app/in-the-metadata/in-the-metadata.component.ts new file mode 100644 index 0000000000..465add0eca --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/in-the-metadata/in-the-metadata.component.ts @@ -0,0 +1,32 @@ +/* tslint:disable:use-input-property-decorator */ +/* tslint:disable:use-output-property-decorator */ + +import { Component, EventEmitter, Input, Output } from '@angular/core'; + +@Component({ + selector: 'app-in-the-metadata', + templateUrl: './in-the-metadata.component.html', + styleUrls: ['./in-the-metadata.component.css'], + // #docregion metadata + // tslint:disable: no-inputs-metadata-property no-outputs-metadata-property + inputs: ['clearanceItem'], + outputs: ['buyEvent'] + // tslint:enable: no-inputs-metadata-property no-outputs-metadata-property + // #enddocregion metadata + +}) +export class InTheMetadataComponent { + + + buyEvent = new EventEmitter(); + clearanceItem: string; + + buyIt() { + console.warn('Child says: emiting buyEvent with', this.clearanceItem); + this.buyEvent.emit(this.clearanceItem); + } + +} + +/* tslint:enable:use-input-property-decorator */ +/* tslint:enable:use-output-property-decorator */ diff --git a/aio/content/examples/inputs-outputs/src/app/input-output/input-output.component.css b/aio/content/examples/inputs-outputs/src/app/input-output/input-output.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/inputs-outputs/src/app/input-output/input-output.component.html b/aio/content/examples/inputs-outputs/src/app/input-output/input-output.component.html new file mode 100644 index 0000000000..c6a1e1dc1e --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/input-output/input-output.component.html @@ -0,0 +1,2 @@ +Item: {{item}} + diff --git a/aio/content/examples/inputs-outputs/src/app/input-output/input-output.component.spec.ts b/aio/content/examples/inputs-outputs/src/app/input-output/input-output.component.spec.ts new file mode 100644 index 0000000000..7e49af8ac4 --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/input-output/input-output.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InputOutputComponent } from './input-output.component'; + +describe('InputOutputComponent', () => { + let component: InputOutputComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ InputOutputComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(InputOutputComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/aio/content/examples/inputs-outputs/src/app/input-output/input-output.component.ts b/aio/content/examples/inputs-outputs/src/app/input-output/input-output.component.ts new file mode 100644 index 0000000000..f328ab8614 --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/input-output/input-output.component.ts @@ -0,0 +1,25 @@ +import { Component, Input, Output, EventEmitter } from '@angular/core'; + +@Component({ + selector: 'app-input-output', + templateUrl: './input-output.component.html', + styleUrls: ['./input-output.component.css'] +}) +export class InputOutputComponent { +// #docregion input-output + @Input() item: string; +// #docregion output + @Output() deleteRequest = new EventEmitter(); +// #enddocregion output +// #enddocregion input-output + + lineThrough = ''; + + // #docregion delete-method + delete() { + console.warn('Child says: emiting item deleteRequest with', this.item); + this.deleteRequest.emit(this.item); + this.lineThrough = this.lineThrough ? '' : 'line-through'; + } + // #enddocregion delete-method +} diff --git a/aio/content/examples/inputs-outputs/src/app/item-detail/item-detail.component.css b/aio/content/examples/inputs-outputs/src/app/item-detail/item-detail.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/inputs-outputs/src/app/item-detail/item-detail.component.html b/aio/content/examples/inputs-outputs/src/app/item-detail/item-detail.component.html new file mode 100644 index 0000000000..cd38989ce0 --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/item-detail/item-detail.component.html @@ -0,0 +1,8 @@ +

Child component with @Input()

+ + +

+ Today's item: {{item}} +

+ + diff --git a/aio/content/examples/inputs-outputs/src/app/item-detail/item-detail.component.spec.ts b/aio/content/examples/inputs-outputs/src/app/item-detail/item-detail.component.spec.ts new file mode 100644 index 0000000000..7559cb65f6 --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/item-detail/item-detail.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ItemDetailComponent } from './item-detail.component'; + +describe('ItemDetailComponent', () => { + let component: ItemDetailComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ItemDetailComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ItemDetailComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/aio/content/examples/inputs-outputs/src/app/item-detail/item-detail.component.ts b/aio/content/examples/inputs-outputs/src/app/item-detail/item-detail.component.ts new file mode 100644 index 0000000000..32f1b5fb59 --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/item-detail/item-detail.component.ts @@ -0,0 +1,16 @@ +// #docplaster +// #docregion use-input +import { Component, Input } from '@angular/core'; // First, import Input +// #enddocregion use-input + +@Component({ + selector: 'app-item-detail', + templateUrl: './item-detail.component.html', + styleUrls: ['./item-detail.component.css'] +}) + +// #docregion use-input +export class ItemDetailComponent { + @Input() item: string; // decorate the property with @Input() +} +// #enddocregion use-input diff --git a/aio/content/examples/inputs-outputs/src/app/item-output/item-output.component.css b/aio/content/examples/inputs-outputs/src/app/item-output/item-output.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/inputs-outputs/src/app/item-output/item-output.component.html b/aio/content/examples/inputs-outputs/src/app/item-output/item-output.component.html new file mode 100644 index 0000000000..c6baef5bfb --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/item-output/item-output.component.html @@ -0,0 +1,6 @@ +

Child component with @Output()

+ + + + + diff --git a/aio/content/examples/inputs-outputs/src/app/item-output/item-output.component.spec.ts b/aio/content/examples/inputs-outputs/src/app/item-output/item-output.component.spec.ts new file mode 100644 index 0000000000..c307491352 --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/item-output/item-output.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ItemOutputComponent } from './item-output.component'; + +describe('ItemOutputComponent', () => { + let component: ItemOutputComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ItemOutputComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ItemOutputComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/aio/content/examples/inputs-outputs/src/app/item-output/item-output.component.ts b/aio/content/examples/inputs-outputs/src/app/item-output/item-output.component.ts new file mode 100644 index 0000000000..68bbc6e584 --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/app/item-output/item-output.component.ts @@ -0,0 +1,22 @@ +// #docregion imports +import { Component, Output, EventEmitter } from '@angular/core'; +// #enddocregion imports + +@Component({ + selector: 'app-item-output', + templateUrl: './item-output.component.html', + styleUrls: ['./item-output.component.css'] +}) + +// #docregion item-output-class +export class ItemOutputComponent { +// #docregion item-output + + @Output() newItemEvent = new EventEmitter(); + +// #enddocregion item-output + addNewItem(value: string) { + this.newItemEvent.emit(value); + } +} +// #enddocregion item-output-class diff --git a/aio/content/examples/inputs-outputs/src/index.html b/aio/content/examples/inputs-outputs/src/index.html new file mode 100644 index 0000000000..6565652186 --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/index.html @@ -0,0 +1,14 @@ + + + + + Inputs and Outputs + + + + + + + + + diff --git a/aio/content/examples/inputs-outputs/src/main.ts b/aio/content/examples/inputs-outputs/src/main.ts new file mode 100644 index 0000000000..91ec6da5f0 --- /dev/null +++ b/aio/content/examples/inputs-outputs/src/main.ts @@ -0,0 +1,12 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.log(err)); diff --git a/aio/content/examples/inputs-outputs/stackblitz.json b/aio/content/examples/inputs-outputs/stackblitz.json new file mode 100644 index 0000000000..f52293403f --- /dev/null +++ b/aio/content/examples/inputs-outputs/stackblitz.json @@ -0,0 +1,10 @@ +{ + "description": "Inputs and Outputs", + "files": [ + "!**/*.d.ts", + "!**/*.js", + "!**/*.[1,2].*" + ], + "file": "src/app/app.component.ts", + "tags": ["Inputs and Outputs"] +} diff --git a/aio/content/examples/lazy-loading-ngmodules/e2e/src/app.e2e-spec.ts b/aio/content/examples/lazy-loading-ngmodules/e2e/src/app.e2e-spec.ts index c064e540e8..c6ff7f79cf 100644 --- a/aio/content/examples/lazy-loading-ngmodules/e2e/src/app.e2e-spec.ts +++ b/aio/content/examples/lazy-loading-ngmodules/e2e/src/app.e2e-spec.ts @@ -18,26 +18,26 @@ describe('providers App', () => { expect(page.getTitleText()).toEqual('Lazy loading feature modules'); }); - describe('Customers list', function() { + describe('Customers', function() { beforeEach(function() { customersButton.click(); }); - it('should show customers list when the button is clicked', function() { - let customersMessage = element(by.css('app-customer-list > p')); - expect(customersMessage.getText()).toBe('customer-list works!'); + it('should show customers when the button is clicked', function() { + let customersMessage = element(by.css('app-customers > p')); + expect(customersMessage.getText()).toBe('customers works!'); }); }); - describe('Orders list', function() { + describe('Orders', function() { beforeEach(function() { ordersButton.click(); }); - it('should show orders list when the button is clicked', function() { - let ordersMessage = element(by.css('app-order-list > p')); - expect(ordersMessage.getText()).toBe('order-list works!'); + it('should show orders when the button is clicked', function() { + let ordersMessage = element(by.css('app-orders > p')); + expect(ordersMessage.getText()).toBe('orders works!'); }); }); diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/app-routing.module.ts b/aio/content/examples/lazy-loading-ngmodules/src/app/app-routing.module.ts index 401aecbb1c..e8a873cfc9 100644 --- a/aio/content/examples/lazy-loading-ngmodules/src/app/app-routing.module.ts +++ b/aio/content/examples/lazy-loading-ngmodules/src/app/app-routing.module.ts @@ -4,23 +4,26 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; -// #docregion const-routes +// #docregion const-routes, routes-customers, routes-customers-orders const routes: Routes = [ { path: 'customers', - loadChildren: () => import('./customers/customers.module').then(mod => mod.CustomersModule) + loadChildren: () => import('./customers/customers.module').then(m => m.CustomersModule) + // #enddocregion routes-customers }, { path: 'orders', - loadChildren: () => import('./orders/orders.module').then(mod => mod.OrdersModule) + loadChildren: () => import('./orders/orders.module').then(m => m.OrdersModule) + // #enddocregion routes-customers-orders }, { path: '', redirectTo: '', pathMatch: 'full' + // #docregion routes-customers, routes-customers-orders } ]; -// #enddocregion const-routes +// #enddocregion const-routes, routes-customers, routes-customers-orders @NgModule({ imports: [ diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/app.component.spec.ts b/aio/content/examples/lazy-loading-ngmodules/src/app/app.component.spec.ts index 41967875b6..f1121210b4 100644 --- a/aio/content/examples/lazy-loading-ngmodules/src/app/app.component.spec.ts +++ b/aio/content/examples/lazy-loading-ngmodules/src/app/app.component.spec.ts @@ -21,16 +21,16 @@ describe('AppComponent', () => { expect(app).toBeTruthy(); })); - it(`should have as title 'app works!'`, async(() => { + it(`should have as title 'customer-app'`, async(() => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.debugElement.componentInstance; - expect(app.title).toEqual('app works!'); + expect(app.title).toEqual('customer-app'); })); it('should render title in a h1 tag', async(() => { const fixture = TestBed.createComponent(AppComponent); fixture.detectChanges(); const compiled = fixture.debugElement.nativeElement; - expect(compiled.querySelector('h1').textContent).toContain('app works!'); + expect(compiled.querySelector('h1').textContent).toContain('customer-app'); })); }); diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customer-list/customer-list.component.html b/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customer-list/customer-list.component.html deleted file mode 100644 index 125b263925..0000000000 --- a/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customer-list/customer-list.component.html +++ /dev/null @@ -1,3 +0,0 @@ -

- customer-list works! -

diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customer-list/customer-list.component.ts b/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customer-list/customer-list.component.ts deleted file mode 100644 index e3b118ff80..0000000000 --- a/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customer-list/customer-list.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'app-customer-list', - templateUrl: './customer-list.component.html', - styleUrls: ['./customer-list.component.css'] -}) -export class CustomerListComponent implements OnInit { - - constructor() { } - - ngOnInit() { - } - -} diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers-routing.module.ts b/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers-routing.module.ts index 2c7e16b4f4..21e9b46be9 100644 --- a/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers-routing.module.ts +++ b/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers-routing.module.ts @@ -3,13 +3,13 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; -import { CustomerListComponent } from './customer-list/customer-list.component'; +import { CustomersComponent } from './customers.component'; const routes: Routes = [ { path: '', - component: CustomerListComponent + component: CustomersComponent } ]; diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers.component.css b/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers.component.html b/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers.component.html new file mode 100644 index 0000000000..2094219d29 --- /dev/null +++ b/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers.component.html @@ -0,0 +1,3 @@ +

+ customers works! +

diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customer-list/customer-list.component.spec.ts b/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers.component.spec.ts similarity index 59% rename from aio/content/examples/lazy-loading-ngmodules/src/app/customers/customer-list/customer-list.component.spec.ts rename to aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers.component.spec.ts index c34e342ba0..1543c2d317 100644 --- a/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customer-list/customer-list.component.spec.ts +++ b/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers.component.spec.ts @@ -1,20 +1,20 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { CustomerListComponent } from './customer-list.component'; +import { CustomersComponent } from './customers.component'; describe('CustomerListComponent', () => { - let component: CustomerListComponent; - let fixture: ComponentFixture; + let component: CustomersComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ CustomerListComponent ] + declarations: [ CustomersComponent ] }) .compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(CustomerListComponent); + fixture = TestBed.createComponent(CustomersComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers.component.ts b/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers.component.ts new file mode 100644 index 0000000000..00e6c8639f --- /dev/null +++ b/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-customers', + templateUrl: './customers.component.html', + styleUrls: ['./customers.component.css'] +}) +export class CustomersComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers.module.ts b/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers.module.ts index db6909da9b..83e841e50b 100644 --- a/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers.module.ts +++ b/aio/content/examples/lazy-loading-ngmodules/src/app/customers/customers.module.ts @@ -3,14 +3,14 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { CustomersRoutingModule } from './customers-routing.module'; -import { CustomerListComponent } from './customer-list/customer-list.component'; +import { CustomersComponent } from './customers.component'; @NgModule({ imports: [ CommonModule, CustomersRoutingModule ], - declarations: [CustomerListComponent] + declarations: [CustomersComponent] }) export class CustomersModule { } // #enddocregion customers-module diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/orders/order-list/order-list.component.html b/aio/content/examples/lazy-loading-ngmodules/src/app/orders/order-list/order-list.component.html deleted file mode 100644 index ec99b36fea..0000000000 --- a/aio/content/examples/lazy-loading-ngmodules/src/app/orders/order-list/order-list.component.html +++ /dev/null @@ -1,3 +0,0 @@ -

- order-list works! -

diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/orders/order-list/order-list.component.ts b/aio/content/examples/lazy-loading-ngmodules/src/app/orders/order-list/order-list.component.ts deleted file mode 100644 index 33b31ce8cc..0000000000 --- a/aio/content/examples/lazy-loading-ngmodules/src/app/orders/order-list/order-list.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'app-order-list', - templateUrl: './order-list.component.html', - styleUrls: ['./order-list.component.css'] -}) -export class OrderListComponent implements OnInit { - - constructor() { } - - ngOnInit() { - } - -} diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders-routing.module.ts b/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders-routing.module.ts index 4ebb23615f..8bf2520341 100644 --- a/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders-routing.module.ts +++ b/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders-routing.module.ts @@ -4,12 +4,12 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; // #docregion orders-routing-module-detail -import { OrderListComponent } from './order-list/order-list.component'; +import { OrdersComponent } from './orders.component'; const routes: Routes = [ { path: '', - component: OrderListComponent + component: OrdersComponent } ]; // #enddocregion orders-routing-module-detail diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders.component.css b/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders.component.html b/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders.component.html new file mode 100644 index 0000000000..1f5843d4a3 --- /dev/null +++ b/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders.component.html @@ -0,0 +1,3 @@ +

+ orders works! +

diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/orders/order-list/order-list.component.spec.ts b/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders.component.spec.ts similarity index 61% rename from aio/content/examples/lazy-loading-ngmodules/src/app/orders/order-list/order-list.component.spec.ts rename to aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders.component.spec.ts index 2688bcf420..bc78306cb0 100644 --- a/aio/content/examples/lazy-loading-ngmodules/src/app/orders/order-list/order-list.component.spec.ts +++ b/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders.component.spec.ts @@ -1,20 +1,20 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { OrderListComponent } from './order-list.component'; +import { OrdersComponent } from './orders.component'; describe('OrderListComponent', () => { - let component: OrderListComponent; - let fixture: ComponentFixture; + let component: OrdersComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ OrderListComponent ] + declarations: [ OrdersComponent ] }) .compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(OrderListComponent); + fixture = TestBed.createComponent(OrdersComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders.component.ts b/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders.component.ts new file mode 100644 index 0000000000..62051ee88e --- /dev/null +++ b/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-orders', + templateUrl: './orders.component.html', + styleUrls: ['./orders.component.css'] +}) +export class OrdersComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders.module.ts b/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders.module.ts index a349d46898..0fbe55c108 100644 --- a/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders.module.ts +++ b/aio/content/examples/lazy-loading-ngmodules/src/app/orders/orders.module.ts @@ -2,13 +2,13 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { OrdersRoutingModule } from './orders-routing.module'; -import { OrderListComponent } from './order-list/order-list.component'; +import { OrdersComponent } from './orders.component'; @NgModule({ imports: [ CommonModule, OrdersRoutingModule ], - declarations: [OrderListComponent] + declarations: [OrdersComponent] }) export class OrdersModule { } diff --git a/aio/content/examples/lifecycle-hooks/src/app/after-content.component.ts b/aio/content/examples/lifecycle-hooks/src/app/after-content.component.ts index 858ea12c59..36d2cff20f 100644 --- a/aio/content/examples/lifecycle-hooks/src/app/after-content.component.ts +++ b/aio/content/examples/lifecycle-hooks/src/app/after-content.component.ts @@ -34,7 +34,7 @@ export class AfterContentComponent implements AfterContentChecked, AfterContentI comment = ''; // Query for a CONTENT child of type `ChildComponent` - @ContentChild(ChildComponent, {static: false}) contentChild: ChildComponent; + @ContentChild(ChildComponent) contentChild: ChildComponent; // #enddocregion hooks constructor(private logger: LoggerService) { diff --git a/aio/content/examples/lifecycle-hooks/src/app/after-view.component.ts b/aio/content/examples/lifecycle-hooks/src/app/after-view.component.ts index 59c472b37a..fd09962406 100644 --- a/aio/content/examples/lifecycle-hooks/src/app/after-view.component.ts +++ b/aio/content/examples/lifecycle-hooks/src/app/after-view.component.ts @@ -35,7 +35,7 @@ export class AfterViewComponent implements AfterViewChecked, AfterViewInit { private prevHero = ''; // Query for a VIEW child of type `ChildViewComponent` - @ViewChild(ChildViewComponent, {static: false}) viewChild: ChildViewComponent; + @ViewChild(ChildViewComponent) viewChild: ChildViewComponent; // #enddocregion hooks constructor(private logger: LoggerService) { diff --git a/aio/content/examples/lifecycle-hooks/src/app/do-check.component.ts b/aio/content/examples/lifecycle-hooks/src/app/do-check.component.ts index 098ee941d2..4b8a088b9a 100644 --- a/aio/content/examples/lifecycle-hooks/src/app/do-check.component.ts +++ b/aio/content/examples/lifecycle-hooks/src/app/do-check.component.ts @@ -81,7 +81,7 @@ export class DoCheckParentComponent { hero: Hero; power: string; title = 'DoCheck'; - @ViewChild(DoCheckComponent, {static: false}) childView: DoCheckComponent; + @ViewChild(DoCheckComponent) childView: DoCheckComponent; constructor() { this.reset(); } diff --git a/aio/content/examples/lifecycle-hooks/src/app/on-changes.component.ts b/aio/content/examples/lifecycle-hooks/src/app/on-changes.component.ts index 09f3169cc2..7b9cda05ef 100644 --- a/aio/content/examples/lifecycle-hooks/src/app/on-changes.component.ts +++ b/aio/content/examples/lifecycle-hooks/src/app/on-changes.component.ts @@ -55,7 +55,7 @@ export class OnChangesParentComponent { hero: Hero; power: string; title = 'OnChanges'; - @ViewChild(OnChangesComponent, {static: false}) childView: OnChangesComponent; + @ViewChild(OnChangesComponent) childView: OnChangesComponent; constructor() { this.reset(); diff --git a/aio/content/examples/ngcontainer/src/app/hero.ts b/aio/content/examples/ngcontainer/src/app/hero.ts index 8619853380..5eafdef334 100644 --- a/aio/content/examples/ngcontainer/src/app/hero.ts +++ b/aio/content/examples/ngcontainer/src/app/hero.ts @@ -1,5 +1,5 @@ // #docregion -export class Hero { +export interface Hero { id: number; name: string; emotion?: string; diff --git a/aio/content/examples/ngmodules/src/app/app-routing.module.ts b/aio/content/examples/ngmodules/src/app/app-routing.module.ts index 3ae0d3d346..a6336eadce 100644 --- a/aio/content/examples/ngmodules/src/app/app-routing.module.ts +++ b/aio/content/examples/ngmodules/src/app/app-routing.module.ts @@ -3,8 +3,8 @@ import { Routes, RouterModule } from '@angular/router'; export const routes: Routes = [ { path: '', redirectTo: 'contact', pathMatch: 'full'}, - { path: 'items', loadChildren: () => import('./items/items.module').then(mod => mod.ItemsModule) }, - { path: 'customers', loadChildren: () => import('./customers/customers.module').then(mod => mod.CustomersModule) } + { path: 'items', loadChildren: () => import('./items/items.module').then(m => m.ItemsModule) }, + { path: 'customers', loadChildren: () => import('./customers/customers.module').then(m => m.CustomersModule) } ]; @NgModule({ diff --git a/aio/content/examples/ngmodules/src/app/app.module.1.ts b/aio/content/examples/ngmodules/src/app/app.module.1.ts new file mode 100644 index 0000000000..f7c3597eea --- /dev/null +++ b/aio/content/examples/ngmodules/src/app/app.module.1.ts @@ -0,0 +1,14 @@ +// imports +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; + +import { AppComponent } from './app.component'; + +// @NgModule decorator with its metadata +@NgModule({ + declarations: [AppComponent], + imports: [BrowserModule], + providers: [], + bootstrap: [AppComponent] +}) +export class AppModule {} diff --git a/aio/content/examples/observables-in-angular/e2e/src/app.e2e-spec.ts b/aio/content/examples/observables-in-angular/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000000..83740c7123 --- /dev/null +++ b/aio/content/examples/observables-in-angular/e2e/src/app.e2e-spec.ts @@ -0,0 +1,9 @@ +/* + * This example project is special in that it is not a cli app. To run tests appropriate for this + * project, the test command is overwritten in `aio/content/examples/observables-in-angular/example-config.json`. + * + * This is an empty placeholder file to ensure that `aio/tools/examples/run-example-e2e.js` runs + * tests for this project. + * + * TODO: Fix our infrastructure/tooling, so that this hack is not necessary. + */ diff --git a/aio/content/examples/observables-in-angular/example-config.json b/aio/content/examples/observables-in-angular/example-config.json index e69de29bb2..548e66ce80 100644 --- a/aio/content/examples/observables-in-angular/example-config.json +++ b/aio/content/examples/observables-in-angular/example-config.json @@ -0,0 +1,8 @@ +{ + "e2e": [ + { + "cmd": "yarn", + "args": [ "tsc", "--project", "./" ] + } + ] +} diff --git a/aio/content/examples/observables-in-angular/src/main.ts b/aio/content/examples/observables-in-angular/src/main.ts index f010819b4d..16788a2f0e 100644 --- a/aio/content/examples/observables-in-angular/src/main.ts +++ b/aio/content/examples/observables-in-angular/src/main.ts @@ -39,9 +39,9 @@ export class ZippyComponent { Time: {{ time | async }}
` }) export class AsyncObservablePipeComponent { - time = new Observable(observer => - setInterval(() => observer.next(new Date().toString()), 1000) - ); + time = new Observable(observer => { + setInterval(() => observer.next(new Date().toString()), 1000); + }); } // #enddocregion pipe diff --git a/aio/content/examples/observables/e2e/src/app.e2e-spec.ts b/aio/content/examples/observables/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000000..ac89f882d0 --- /dev/null +++ b/aio/content/examples/observables/e2e/src/app.e2e-spec.ts @@ -0,0 +1,9 @@ +/* + * This example project is special in that it is not a cli app. To run tests appropriate for this + * project, the test command is overwritten in `aio/content/examples/observables/example-config.json`. + * + * This is an empty placeholder file to ensure that `aio/tools/examples/run-example-e2e.js` runs + * tests for this project. + * + * TODO: Fix our infrastructure/tooling, so that this hack is not necessary. + */ diff --git a/aio/content/examples/observables/example-config.json b/aio/content/examples/observables/example-config.json index e69de29bb2..548e66ce80 100644 --- a/aio/content/examples/observables/example-config.json +++ b/aio/content/examples/observables/example-config.json @@ -0,0 +1,8 @@ +{ + "e2e": [ + { + "cmd": "yarn", + "args": [ "tsc", "--project", "./" ] + } + ] +} diff --git a/aio/content/examples/observables/src/geolocation.ts b/aio/content/examples/observables/src/geolocation.ts index 7210a51e1d..841fea556e 100644 --- a/aio/content/examples/observables/src/geolocation.ts +++ b/aio/content/examples/observables/src/geolocation.ts @@ -5,28 +5,39 @@ import { Observable } from 'rxjs'; // Create an Observable that will start listening to geolocation updates // when a consumer subscribes. const locations = new Observable((observer) => { - // Get the next and error callbacks. These will be passed in when - // the consumer subscribes. - const {next, error} = observer; - let watchId; + let watchId: number; // Simple geolocation API check provides values to publish if ('geolocation' in navigator) { - watchId = navigator.geolocation.watchPosition(next, error); + watchId = navigator.geolocation.watchPosition((position: Position) => { + observer.next(position); + }, (error: PositionError) => { + observer.error(error); + }); } else { - error('Geolocation not available'); + observer.error('Geolocation not available'); } // When the consumer unsubscribes, clean up data ready for next subscription. - return {unsubscribe() { navigator.geolocation.clearWatch(watchId); }}; + return { + unsubscribe() { + navigator.geolocation.clearWatch(watchId); + } + }; }); // Call subscribe() to start listening for updates. const locationsSubscription = locations.subscribe({ - next(position) { console.log('Current Position: ', position); }, - error(msg) { console.log('Error Getting Location: ', msg); } + next(position) { + console.log('Current Position: ', position); + }, + error(msg) { + console.log('Error Getting Location: ', msg); + } }); // Stop listening for location after 10 seconds -setTimeout(() => { locationsSubscription.unsubscribe(); }, 10000); +setTimeout(() => { + locationsSubscription.unsubscribe(); +}, 10000); // #enddocregion diff --git a/aio/content/examples/practical-observable-usage/e2e/src/app.e2e-spec.ts b/aio/content/examples/practical-observable-usage/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000000..af10979040 --- /dev/null +++ b/aio/content/examples/practical-observable-usage/e2e/src/app.e2e-spec.ts @@ -0,0 +1,9 @@ +/* + * This example project is special in that it is not a cli app. To run tests appropriate for this + * project, the test command is overwritten in `aio/content/examples/practical-observable-usage/example-config.json`. + * + * This is an empty placeholder file to ensure that `aio/tools/examples/run-example-e2e.js` runs + * tests for this project. + * + * TODO: Fix our infrastructure/tooling, so that this hack is not necessary. + */ diff --git a/aio/content/examples/practical-observable-usage/example-config.json b/aio/content/examples/practical-observable-usage/example-config.json index e69de29bb2..548e66ce80 100644 --- a/aio/content/examples/practical-observable-usage/example-config.json +++ b/aio/content/examples/practical-observable-usage/example-config.json @@ -0,0 +1,8 @@ +{ + "e2e": [ + { + "cmd": "yarn", + "args": [ "tsc", "--project", "./" ] + } + ] +} diff --git a/aio/content/examples/practical-observable-usage/src/typeahead.ts b/aio/content/examples/practical-observable-usage/src/typeahead.ts index 4bde2c66d0..153ab7f23e 100644 --- a/aio/content/examples/practical-observable-usage/src/typeahead.ts +++ b/aio/content/examples/practical-observable-usage/src/typeahead.ts @@ -1,12 +1,12 @@ - import { fromEvent } from 'rxjs'; import { ajax } from 'rxjs/ajax'; -import { map, filter, debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators'; + const searchBox = document.getElementById('search-box'); const typeahead = fromEvent(searchBox, 'input').pipe( - map((e: KeyboardEvent) => e.target.value), + map((e: KeyboardEvent) => (e.target as HTMLInputElement).value), filter(text => text.length > 2), debounceTime(10), distinctUntilChanged(), diff --git a/aio/content/examples/property-binding/e2e/src/app.e2e-spec.ts b/aio/content/examples/property-binding/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000000..07b98491c1 --- /dev/null +++ b/aio/content/examples/property-binding/e2e/src/app.e2e-spec.ts @@ -0,0 +1,54 @@ +import { browser, element, by } from 'protractor'; + + +describe('Property binding e2e tests', () => { + + beforeEach(function () { + browser.get(''); + }); + + it('should display Property Binding with Angular', function () { + expect(element(by.css('h1')).getText()).toEqual('Property Binding with Angular'); + }); + + it('should display four phone pictures', function() { + expect(element.all(by.css('img')).isPresent()).toBe(true); + expect(element.all(by.css('img')).count()).toBe(4); + + }); + + it('should display Disabled button', function () { + expect(element.all(by.css('button')).get(0).getText()).toBe(`Disabled Button`); + }); + + it('should display Binding to a property of a directive', function () { + expect(element.all(by.css('h2')).get(4).getText()).toBe(`Binding to a property of a directive`); + }); + + it('should display Your item is: lamp', function () { + expect(element.all(by.css('p')).get(0).getText()).toContain(`blue`); + }); + it('should display Your item is: lamp', function () { + expect(element.all(by.css('p')).get(1).getText()).toContain(`Your item is: lamp`); + }); + + it('should display Your item is: parentItem', function () { + expect(element.all(by.css('p')).get(2).getText()).toBe(`Your item is: parentItem`); + }); + + it('should display a ul', function () { + expect(element.all(by.css('ul')).get(0).getText()).toContain(`tv`); + }); + + it('should display a ul containing phone', function () { + expect(element.all(by.css('ul')).get(1).getText()).toBe(`21 phone`); + }); + + it('should display one-time initialized string', function () { + expect(element.all(by.css('p')).get(3).getText()).toContain(`one-time initialized`); + }); + + it('should display Malicious content', function () { + expect(element.all(by.css('h2')).get(8).getText()).toBe(`Malicious content`); + }); +}); diff --git a/aio/content/examples/property-binding/example-config.json b/aio/content/examples/property-binding/example-config.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/property-binding/src/app/app.component.css b/aio/content/examples/property-binding/src/app/app.component.css new file mode 100644 index 0000000000..91bae844fd --- /dev/null +++ b/aio/content/examples/property-binding/src/app/app.component.css @@ -0,0 +1,9 @@ +div { + margin: 1rem auto; + width: 90% +} +.special { + background-color: #1976d2; + color: #fff; + padding: 1rem; +} diff --git a/aio/content/examples/property-binding/src/app/app.component.html b/aio/content/examples/property-binding/src/app/app.component.html new file mode 100644 index 0000000000..e6ca6e5b0a --- /dev/null +++ b/aio/content/examples/property-binding/src/app/app.component.html @@ -0,0 +1,84 @@ + + +
+

Property Binding with Angular

+

Binding the src property of an image:

+ + + +

Using bind- syntax:

+ + + +
+ +

Binding to the colSpan property

+ + + + + + +
Column 1Column 2
Span 2 columns
+ + +
+

Button disabled state bound to isUnchanged property:

+ + + + +
+ +

Binding to a property of a directive

+ +

[ngClass] binding to the classes property making this blue

+ +
+ +

Model property of a custom component:

+ + + + + + + +

Pass objects:

+ + + + +
+

Initialized string:

+ + + + +
+ +

Property binding and interpolation

+ +

is the interpolated image.

+

is the property bound image.

+ +

"{{interpolationTitle}}" is the interpolated title.

+

"" is the property bound title.

+ + +
+ +

Malicious content

+ + +

"{{evilTitle}}" is the interpolated evil title.

+ + + + +

"" is the property bound evil title.

+ +
diff --git a/aio/content/examples/property-binding/src/app/app.component.spec.ts b/aio/content/examples/property-binding/src/app/app.component.spec.ts new file mode 100644 index 0000000000..bcbdf36b3e --- /dev/null +++ b/aio/content/examples/property-binding/src/app/app.component.spec.ts @@ -0,0 +1,27 @@ +import { TestBed, async } from '@angular/core/testing'; +import { AppComponent } from './app.component'; +describe('AppComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ + AppComponent + ], + }).compileComponents(); + })); + it('should create the app', async(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app).toBeTruthy(); + })); + it(`should have as title 'app'`, async(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app.title).toEqual('app'); + })); + it('should render title in a h1 tag', async(() => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.debugElement.nativeElement; + expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!'); + })); +}); diff --git a/aio/content/examples/property-binding/src/app/app.component.ts b/aio/content/examples/property-binding/src/app/app.component.ts new file mode 100644 index 0000000000..c8dd3b5fe4 --- /dev/null +++ b/aio/content/examples/property-binding/src/app/app.component.ts @@ -0,0 +1,30 @@ +import { Component } from '@angular/core'; + + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'] +}) +export class AppComponent { + itemImageUrl = '../assets/phone.png'; + isUnchanged = true; + classes = 'special'; + // #docregion parent-data-type + parentItem = 'lamp'; + // #enddocregion parent-data-type + + // #docregion pass-object + currentItem = [{ + id: 21, + name: 'phone' + }]; + // #enddocregion pass-object + + interpolationTitle = 'Interpolation'; + propertyTitle = 'Property binding'; + + // #docregion malicious-content + evilTitle = 'Template Syntax'; + // #enddocregion malicious-content +} diff --git a/aio/content/examples/property-binding/src/app/app.module.ts b/aio/content/examples/property-binding/src/app/app.module.ts new file mode 100644 index 0000000000..24c86b6bcf --- /dev/null +++ b/aio/content/examples/property-binding/src/app/app.module.ts @@ -0,0 +1,24 @@ +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; + + +import { AppComponent } from './app.component'; +import { ItemDetailComponent } from './item-detail/item-detail.component'; +import { ListItemComponent } from './list-item/list-item.component'; +import { StringInitComponent } from './string-init/string-init.component'; + + +@NgModule({ + declarations: [ + AppComponent, + ItemDetailComponent, + ListItemComponent, + StringInitComponent + ], + imports: [ + BrowserModule + ], + providers: [], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/aio/content/examples/property-binding/src/app/item-detail/item-detail.component.css b/aio/content/examples/property-binding/src/app/item-detail/item-detail.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/property-binding/src/app/item-detail/item-detail.component.html b/aio/content/examples/property-binding/src/app/item-detail/item-detail.component.html new file mode 100644 index 0000000000..050f915d47 --- /dev/null +++ b/aio/content/examples/property-binding/src/app/item-detail/item-detail.component.html @@ -0,0 +1,4 @@ +

Your item is: {{ childItem }}

+ + + diff --git a/aio/content/examples/property-binding/src/app/item-detail/item-detail.component.spec.ts b/aio/content/examples/property-binding/src/app/item-detail/item-detail.component.spec.ts new file mode 100644 index 0000000000..7559cb65f6 --- /dev/null +++ b/aio/content/examples/property-binding/src/app/item-detail/item-detail.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ItemDetailComponent } from './item-detail.component'; + +describe('ItemDetailComponent', () => { + let component: ItemDetailComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ItemDetailComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ItemDetailComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/aio/content/examples/property-binding/src/app/item-detail/item-detail.component.ts b/aio/content/examples/property-binding/src/app/item-detail/item-detail.component.ts new file mode 100644 index 0000000000..e16be07036 --- /dev/null +++ b/aio/content/examples/property-binding/src/app/item-detail/item-detail.component.ts @@ -0,0 +1,26 @@ +import { Component, OnInit, Input } from '@angular/core'; +// import { Item } from '../item'; +// import { ITEMS } from '../mock-items'; + +@Component({ + selector: 'app-item-detail', + templateUrl: './item-detail.component.html', + styleUrls: ['./item-detail.component.css'] +}) +export class ItemDetailComponent implements OnInit { + + // #docregion input-type + @Input() childItem: string; + // #enddocregion input-type + + // items = ITEMS; + + + currentItem = 'bananas in boxes'; + + constructor() { } + + ngOnInit() { + } + +} diff --git a/aio/content/examples/property-binding/src/app/item.ts b/aio/content/examples/property-binding/src/app/item.ts new file mode 100644 index 0000000000..53bcca4514 --- /dev/null +++ b/aio/content/examples/property-binding/src/app/item.ts @@ -0,0 +1,7 @@ +// #docregion item-class +export class Item { + id: number; + name: string; +} +// #enddocregion item-class + diff --git a/aio/content/examples/property-binding/src/app/list-item/list-item.component.css b/aio/content/examples/property-binding/src/app/list-item/list-item.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/property-binding/src/app/list-item/list-item.component.html b/aio/content/examples/property-binding/src/app/list-item/list-item.component.html new file mode 100644 index 0000000000..f19e6c605e --- /dev/null +++ b/aio/content/examples/property-binding/src/app/list-item/list-item.component.html @@ -0,0 +1,11 @@ + +

Nested component's list of items:

+
    +
  • {{item.id}} {{item.name}}
  • +
+ +

Pass an object from parent to nested component:

+
    +
  • {{item.id}} {{item.name}}
  • +
+ diff --git a/aio/content/examples/property-binding/src/app/list-item/list-item.component.spec.ts b/aio/content/examples/property-binding/src/app/list-item/list-item.component.spec.ts new file mode 100644 index 0000000000..0568b6c4c2 --- /dev/null +++ b/aio/content/examples/property-binding/src/app/list-item/list-item.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListItemComponent } from './list-item.component'; + +describe('ItemListComponent', () => { + let component: ListItemComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ListItemComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ListItemComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/aio/content/examples/property-binding/src/app/list-item/list-item.component.ts b/aio/content/examples/property-binding/src/app/list-item/list-item.component.ts new file mode 100644 index 0000000000..48d1992cde --- /dev/null +++ b/aio/content/examples/property-binding/src/app/list-item/list-item.component.ts @@ -0,0 +1,17 @@ +import { Component, Input } from '@angular/core'; +import { ITEMS } from '../mock-items'; +import { Item } from '../item'; + +@Component({ + selector: 'app-list-item', + templateUrl: './list-item.component.html', + styleUrls: ['./list-item.component.css'] +}) +export class ListItemComponent { + listItems = ITEMS; + // #docregion item-input + @Input() items: Item[]; + // #enddocregion item-input + constructor() { } + +} diff --git a/aio/content/examples/property-binding/src/app/mock-items.ts b/aio/content/examples/property-binding/src/app/mock-items.ts new file mode 100644 index 0000000000..43cd74c5c9 --- /dev/null +++ b/aio/content/examples/property-binding/src/app/mock-items.ts @@ -0,0 +1,14 @@ +import { Item } from './item'; + +export const ITEMS: Item[] = [ + { id: 11, name: 'bottle' }, + { id: 12, name: 'boombox' }, + { id: 13, name: 'chair' }, + { id: 14, name: 'fishbowl' }, + { id: 15, name: 'lamp' }, + { id: 16, name: 'tv' }, + { id: 17, name: 'mug' }, + { id: 18, name: 'paintbrush' }, + { id: 19, name: 'plant' }, + { id: 20, name: 'teapot' } +]; diff --git a/aio/content/examples/property-binding/src/app/string-init/string-init.component.css b/aio/content/examples/property-binding/src/app/string-init/string-init.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/property-binding/src/app/string-init/string-init.component.html b/aio/content/examples/property-binding/src/app/string-init/string-init.component.html new file mode 100644 index 0000000000..b3cd69e133 --- /dev/null +++ b/aio/content/examples/property-binding/src/app/string-init/string-init.component.html @@ -0,0 +1 @@ +

{{prefix}}

diff --git a/aio/content/examples/property-binding/src/app/string-init/string-init.component.spec.ts b/aio/content/examples/property-binding/src/app/string-init/string-init.component.spec.ts new file mode 100644 index 0000000000..2c8e97ec82 --- /dev/null +++ b/aio/content/examples/property-binding/src/app/string-init/string-init.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { StringInitComponent } from './string-init.component'; + +describe('StringInitComponent', () => { + let component: StringInitComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ StringInitComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(StringInitComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/aio/content/examples/property-binding/src/app/string-init/string-init.component.ts b/aio/content/examples/property-binding/src/app/string-init/string-init.component.ts new file mode 100644 index 0000000000..a49bf41093 --- /dev/null +++ b/aio/content/examples/property-binding/src/app/string-init/string-init.component.ts @@ -0,0 +1,17 @@ +import { Component, OnInit, Input } from '@angular/core'; + +@Component({ + selector: 'app-string-init', + templateUrl: './string-init.component.html', + styleUrls: ['./string-init.component.css'] +}) +export class StringInitComponent implements OnInit { + + @Input() prefix: string; + + constructor() { } + + ngOnInit() { + } + +} diff --git a/aio/content/examples/property-binding/src/assets/phone.png b/aio/content/examples/property-binding/src/assets/phone.png new file mode 100644 index 0000000000..6e60e1f1a1 Binary files /dev/null and b/aio/content/examples/property-binding/src/assets/phone.png differ diff --git a/aio/content/examples/property-binding/src/index.html b/aio/content/examples/property-binding/src/index.html new file mode 100644 index 0000000000..01fd8c14ff --- /dev/null +++ b/aio/content/examples/property-binding/src/index.html @@ -0,0 +1,14 @@ + + + + + PropertyBinding + + + + + + + + + diff --git a/aio/content/examples/property-binding/src/main.ts b/aio/content/examples/property-binding/src/main.ts new file mode 100644 index 0000000000..91ec6da5f0 --- /dev/null +++ b/aio/content/examples/property-binding/src/main.ts @@ -0,0 +1,12 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.log(err)); diff --git a/aio/content/examples/property-binding/stackblitz.json b/aio/content/examples/property-binding/stackblitz.json new file mode 100644 index 0000000000..89869613e4 --- /dev/null +++ b/aio/content/examples/property-binding/stackblitz.json @@ -0,0 +1,10 @@ +{ + "description": "Property Binding", + "files": [ + "!**/*.d.ts", + "!**/*.js", + "!**/*.[0,1,2].*" + ], + "file": "src/app/app.component.ts", + "tags": ["property binding"] +} diff --git a/aio/content/examples/providers-viewproviders/e2e/src/app.e2e-spec.ts b/aio/content/examples/providers-viewproviders/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000000..d9e83d93fe --- /dev/null +++ b/aio/content/examples/providers-viewproviders/e2e/src/app.e2e-spec.ts @@ -0,0 +1,24 @@ +import { browser, element, by } from 'protractor'; +import { logging } from 'selenium-webdriver'; + +describe('Providers and ViewProviders', function () { + + + beforeEach(() => { + browser.get(''); + }); + + it('shows basic flower emoji', function() { + expect(element.all(by.css('p')).get(0).getText()).toContain('🌺'); + }); + + it('shows whale emoji', function() { + expect(element.all(by.css('p')).get(1).getText()).toContain('🐳'); + }); + + it('shows sunflower from FlowerService', function() { + expect(element.all(by.css('p')).get(8).getText()).toContain('🌻'); + }); + +}); + diff --git a/aio/content/examples/providers-viewproviders/example-config.json b/aio/content/examples/providers-viewproviders/example-config.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/providers-viewproviders/src/app/animal.service.ts b/aio/content/examples/providers-viewproviders/src/app/animal.service.ts new file mode 100755 index 0000000000..e7f6a98b08 --- /dev/null +++ b/aio/content/examples/providers-viewproviders/src/app/animal.service.ts @@ -0,0 +1,10 @@ +// #docregion animal-service +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class AnimalService { + emoji = '🐳'; +} +// #enddocregion animal-service diff --git a/aio/content/examples/providers-viewproviders/src/app/app.component.1.ts b/aio/content/examples/providers-viewproviders/src/app/app.component.1.ts new file mode 100644 index 0000000000..339661857a --- /dev/null +++ b/aio/content/examples/providers-viewproviders/src/app/app.component.1.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { FlowerService } from './flower.service'; +import { AnimalService } from './animal.service'; + + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: [ './app.component.css' ] +}) +// #docregion injection +export class AppComponent { + constructor(public flower: FlowerService) {} +} +// #enddocregion injection diff --git a/aio/content/examples/providers-viewproviders/src/app/app.component.css b/aio/content/examples/providers-viewproviders/src/app/app.component.css new file mode 100755 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/providers-viewproviders/src/app/app.component.html b/aio/content/examples/providers-viewproviders/src/app/app.component.html new file mode 100755 index 0000000000..1e958b5336 --- /dev/null +++ b/aio/content/examples/providers-viewproviders/src/app/app.component.html @@ -0,0 +1,15 @@ + +

From AppComponent:

+ +

Emoji from FlowerService: {{flower.emoji}}

+ + +

Emoji from AnimalService: {{animal.emoji}}

+ + +
+ +

From ChildComponent:

+ + + diff --git a/aio/content/examples/providers-viewproviders/src/app/app.component.ts b/aio/content/examples/providers-viewproviders/src/app/app.component.ts new file mode 100755 index 0000000000..1c9e56abef --- /dev/null +++ b/aio/content/examples/providers-viewproviders/src/app/app.component.ts @@ -0,0 +1,31 @@ +import { Component } from '@angular/core'; +import { FlowerService } from './flower.service'; +import { AnimalService } from './animal.service'; + + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: [ './app.component.css' ] +}) +// #docregion inject-animal-service +export class AppComponent { + constructor(public flower: FlowerService, public animal: AnimalService) {} +} +// #enddocregion inject-animal-service + +// When using @Host() together with @SkipSelf() in +// child.component.ts for the AnimalService, add the +// following viewProviders array to the @Component metadata: + +// viewProviders: [{ provide: AnimalService, useValue: { emoji: '🦔' } }] + +// So, the entire @ChildComponent() decorator and its +// metadata should be as follows: + +// @Component({ +// selector: 'app-root', +// templateUrl: './app.component.html', +// styleUrls: [ './app.component.css' ], +// viewProviders: [{ provide: AnimalService, useValue: { emoji: '🦔' } }] +// }) diff --git a/aio/content/examples/providers-viewproviders/src/app/app.module.ts b/aio/content/examples/providers-viewproviders/src/app/app.module.ts new file mode 100755 index 0000000000..eb20fc25b5 --- /dev/null +++ b/aio/content/examples/providers-viewproviders/src/app/app.module.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { FormsModule } from '@angular/forms'; + +import { AppComponent } from './app.component'; +import { ChildComponent } from './child/child.component'; +import { InspectorComponent } from './inspector/inspector.component'; + +// #docregion appmodule +@NgModule({ + imports: [ BrowserModule, FormsModule ], + declarations: [ AppComponent, ChildComponent, InspectorComponent ], + bootstrap: [ AppComponent ], + providers: [] +}) +export class AppModule { } +// #enddocregion appmodule diff --git a/aio/content/examples/providers-viewproviders/src/app/child/child.component.1.ts b/aio/content/examples/providers-viewproviders/src/app/child/child.component.1.ts new file mode 100644 index 0000000000..33b02df7f2 --- /dev/null +++ b/aio/content/examples/providers-viewproviders/src/app/child/child.component.1.ts @@ -0,0 +1,19 @@ +import { Component, OnInit, Host, SkipSelf, Optional } from '@angular/core'; +import { FlowerService } from '../flower.service'; + +// #docregion flowerservice +@Component({ + selector: 'app-child', + templateUrl: './child.component.html', + styleUrls: ['./child.component.css'], + // use the providers array to provide a service + providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }] +}) + +export class ChildComponent { + // inject the service + constructor( public flower: FlowerService) { } +} + +// #enddocregion flowerservice + diff --git a/aio/content/examples/providers-viewproviders/src/app/child/child.component.css b/aio/content/examples/providers-viewproviders/src/app/child/child.component.css new file mode 100755 index 0000000000..13fdf763f4 --- /dev/null +++ b/aio/content/examples/providers-viewproviders/src/app/child/child.component.css @@ -0,0 +1,4 @@ +.container { + border: 1px solid darkblue; + padding: 1rem; +} \ No newline at end of file diff --git a/aio/content/examples/providers-viewproviders/src/app/child/child.component.html b/aio/content/examples/providers-viewproviders/src/app/child/child.component.html new file mode 100755 index 0000000000..9bc45624f5 --- /dev/null +++ b/aio/content/examples/providers-viewproviders/src/app/child/child.component.html @@ -0,0 +1,24 @@ + + + +

Emoji from FlowerService: {{flower.emoji}}

+ + +

Emoji from AnimalService: {{animal.emoji}}

+ + +
+

Content projection

+ +

The following is coming from content. It doesn't get to see the puppy because the puppy is declared inside the view only.

+ + +
+ +

Inside the view

+ +

The following is inside the view so it does see the puppy.

+ + + + diff --git a/aio/content/examples/providers-viewproviders/src/app/child/child.component.ts b/aio/content/examples/providers-viewproviders/src/app/child/child.component.ts new file mode 100755 index 0000000000..415bdc5506 --- /dev/null +++ b/aio/content/examples/providers-viewproviders/src/app/child/child.component.ts @@ -0,0 +1,44 @@ +// #docplaster +import { Component, OnInit, Host, SkipSelf, Optional } from '@angular/core'; +import { FlowerService } from '../flower.service'; +import { AnimalService } from '../animal.service'; + +// #docregion provide-animal-service +@Component({ + selector: 'app-child', + templateUrl: './child.component.html', + styleUrls: ['./child.component.css'], + // provide services + providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }], + viewProviders: [{ provide: AnimalService, useValue: { emoji: '🐶' } }] +}) + +export class ChildComponent { + // inject service + constructor( public flower: FlowerService, public animal: AnimalService) { } +// #enddocregion provide-animal-service + + // viewProviders ensures that only the view gets to see this. + // With the AnimalService in the viewProviders, the + // InspectorComponent doesn't get to see it because the + // inspector is in the content. + + + // constructor( public flower: FlowerService, @Optional() @Host() public animal: AnimalService) { } + +// Comment out the above constructor and alternately +// uncomment the two following constructors to see the +// effects of @Host() and @Host() + @SkipSelf(). + +// constructor( +// @Host() public animal : AnimalService, +// @Host() @Optional() public flower : FlowerService) { } + +// constructor( +// @SkipSelf() @Host() public animal : AnimalService, +// @SkipSelf() @Host() @Optional() public flower : FlowerService) { } + +// #docregion provide-animal-service +} +// #enddocregion provide-animal-service + diff --git a/aio/content/examples/providers-viewproviders/src/app/flower.service.ts b/aio/content/examples/providers-viewproviders/src/app/flower.service.ts new file mode 100755 index 0000000000..00221005a3 --- /dev/null +++ b/aio/content/examples/providers-viewproviders/src/app/flower.service.ts @@ -0,0 +1,11 @@ +import { Injectable } from '@angular/core'; + +// #docregion flowerservice +@Injectable({ + providedIn: 'root' +}) +export class FlowerService { + emoji = '🌺'; +} +// #enddocregion flowerservice + diff --git a/aio/content/examples/providers-viewproviders/src/app/inspector/inspector.component.css b/aio/content/examples/providers-viewproviders/src/app/inspector/inspector.component.css new file mode 100755 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/providers-viewproviders/src/app/inspector/inspector.component.html b/aio/content/examples/providers-viewproviders/src/app/inspector/inspector.component.html new file mode 100755 index 0000000000..fe32d7578e --- /dev/null +++ b/aio/content/examples/providers-viewproviders/src/app/inspector/inspector.component.html @@ -0,0 +1,4 @@ + +

Emoji from FlowerService: {{flower.emoji}}

+

Emoji from AnimalService: {{animal.emoji}}

+ diff --git a/aio/content/examples/providers-viewproviders/src/app/inspector/inspector.component.ts b/aio/content/examples/providers-viewproviders/src/app/inspector/inspector.component.ts new file mode 100755 index 0000000000..d5e99835fe --- /dev/null +++ b/aio/content/examples/providers-viewproviders/src/app/inspector/inspector.component.ts @@ -0,0 +1,14 @@ +import { Component } from '@angular/core'; +import { FlowerService } from '../flower.service'; +import { AnimalService } from '../animal.service'; + +@Component({ + selector: 'app-inspector', + templateUrl: './inspector.component.html', + styleUrls: ['./inspector.component.css'] +}) +// #docregion injection +export class InspectorComponent { + constructor(public flower: FlowerService, public animal: AnimalService) { } +} +// #enddocregion injection diff --git a/aio/content/examples/providers-viewproviders/src/index.html b/aio/content/examples/providers-viewproviders/src/index.html new file mode 100644 index 0000000000..3f4775ce4a --- /dev/null +++ b/aio/content/examples/providers-viewproviders/src/index.html @@ -0,0 +1,14 @@ + + + + + providers vs. viewProviders + + + + + + + + + diff --git a/aio/content/examples/providers-viewproviders/src/main.ts b/aio/content/examples/providers-viewproviders/src/main.ts new file mode 100644 index 0000000000..91ec6da5f0 --- /dev/null +++ b/aio/content/examples/providers-viewproviders/src/main.ts @@ -0,0 +1,12 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.log(err)); diff --git a/aio/content/examples/providers-viewproviders/stackblitz.json b/aio/content/examples/providers-viewproviders/stackblitz.json new file mode 100644 index 0000000000..f52293403f --- /dev/null +++ b/aio/content/examples/providers-viewproviders/stackblitz.json @@ -0,0 +1,10 @@ +{ + "description": "Inputs and Outputs", + "files": [ + "!**/*.d.ts", + "!**/*.js", + "!**/*.[1,2].*" + ], + "file": "src/app/app.component.ts", + "tags": ["Inputs and Outputs"] +} diff --git a/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.html b/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.html index 86178e1c3c..1248cd0373 100644 --- a/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.html +++ b/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.html @@ -42,7 +42,7 @@

Aliases

-
+