mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Compare commits
158 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 57cb448de5 | |||
| 0bd668c943 | |||
| 2c0bb7fb0e | |||
| 735cdf3761 | |||
| 948fb5f937 | |||
| 9f1a5fa5da | |||
| cab06bd125 | |||
| cdc5e39532 | |||
| ed8e7c727b | |||
| e08cc50f3c | |||
| ca7456e722 | |||
| b353ad5bac | |||
| bd6d18b977 | |||
| 3b218a72ce | |||
| 4367c44f7f | |||
| b69bf37841 | |||
| 05a05b628b | |||
| c21f41d6d4 | |||
| 413db303f4 | |||
| 752ebd62c9 | |||
| 7001b5d633 | |||
| fccf375df1 | |||
| 8d85de7fe1 | |||
| 4c2b0d94e2 | |||
| 57174bb60b | |||
| 7a4a5253ea | |||
| c5a0e909ac | |||
| d07ce6156e | |||
| e3b874b4fb | |||
| 1ac37f932f | |||
| 8650f0dee2 | |||
| 030d77010d | |||
| 96ca49d145 | |||
| 8264382a6b | |||
| f5a5215166 | |||
| 5cd00f167c | |||
| 22f89c0a2d | |||
| c442912532 | |||
| 9f9dd901ae | |||
| 30e42df518 | |||
| 566499af1d | |||
| 4a5f37d216 | |||
| 74567f1c8a | |||
| 64399b26c0 | |||
| 1b296dbb80 | |||
| cddc426e18 | |||
| 8109013b0f | |||
| f25d7e880f | |||
| f240c70971 | |||
| 0172477ff2 | |||
| 0702d4a560 | |||
| 798aee7a83 | |||
| c477e876e3 | |||
| ecd0daf8fd | |||
| 6eca767811 | |||
| d8d6478d0e | |||
| 0c4d7e061e | |||
| 293dc3b046 | |||
| 8dca5a11f5 | |||
| 45fca0bc95 | |||
| 85819b9cdb | |||
| 87378a773d | |||
| 96dd0c715e | |||
| ccddacf11d | |||
| b216e76838 | |||
| 0d31904a96 | |||
| aa3df2a7d4 | |||
| 50b7901169 | |||
| 1439f059a3 | |||
| ac211d46b0 | |||
| 356984d9ba | |||
| 7ac94dd664 | |||
| 49aff2726f | |||
| 6c14c9324f | |||
| c0c7216c5f | |||
| 25e4f04d9f | |||
| 259707e31c | |||
| d17ba9bc87 | |||
| a4923f1f17 | |||
| e603450592 | |||
| c6861eefa4 | |||
| 910742389f | |||
| 98d545fafa | |||
| 7786e35faa | |||
| 49101330f8 | |||
| 4507704a7e | |||
| 854b839531 | |||
| 89f7b00e59 | |||
| f12b01ec88 | |||
| 0c8aaf082e | |||
| a4f024fb07 | |||
| e2e0f08d99 | |||
| e194fbfbaa | |||
| 8ad1ee764b | |||
| f222bee8fa | |||
| 9a9a00e0f9 | |||
| 5f9cac037b | |||
| 9778326f10 | |||
| fac5a7cf4e | |||
| ae145d19c6 | |||
| 30b6d34a49 | |||
| 3e0b7c1bdc | |||
| a58a35dfe4 | |||
| a7c9fbb087 | |||
| 20811aad27 | |||
| df453c3549 | |||
| 1f6c96a1dc | |||
| 656549d88a | |||
| c0f0baac58 | |||
| d38aa4f103 | |||
| 7397b6648a | |||
| 0fe9331958 | |||
| 7620f506c0 | |||
| 62ad2f0c71 | |||
| 424a26b3c7 | |||
| 18bd1a5ccb | |||
| 8922a11693 | |||
| 4e0341050b | |||
| 0616dc2839 | |||
| dc228c6fc1 | |||
| b1a7249c24 | |||
| 9ff4893bc0 | |||
| 025f7af694 | |||
| 1c4a99a6d1 | |||
| 51d53fc728 | |||
| be882c3efb | |||
| 18fa6d7556 | |||
| bb8a5a4c70 | |||
| 9c00506a26 | |||
| 79e8539ce2 | |||
| 6f79507ea7 | |||
| 6616019735 | |||
| 4d4858fa28 | |||
| 538fe47d9d | |||
| b07c549802 | |||
| 6f6ad0279b | |||
| d08f91f861 | |||
| 28aa7b3188 | |||
| 6ac0a68d73 | |||
| ea19bff302 | |||
| 1112e9196a | |||
| 0d8a5c4665 | |||
| 76ceebad04 | |||
| 99c2d76651 | |||
| 246cb9c381 | |||
| d7c75c6edb | |||
| 0daca457bb | |||
| 12f9ed01cc | |||
| 69713413f7 | |||
| 43d6816f9e | |||
| 4c4fea1304 | |||
| c6df89c827 | |||
| 9cae9b4a8c | |||
| 29b959ce31 | |||
| a24b24e8a4 | |||
| f51c008744 | |||
| 3dedd6a07a | |||
| 881376eb42 |
@@ -4,7 +4,7 @@ description: 'Installs the dependencies using Yarn'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3
|
||||
- uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c # v3
|
||||
with:
|
||||
path: |
|
||||
./node_modules/
|
||||
|
||||
@@ -21,16 +21,16 @@ jobs:
|
||||
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'adev: preview'))
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e52eb8237f2ed71195f87ce8046467a176568e58
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e52eb8237f2ed71195f87ce8046467a176568e58
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e52eb8237f2ed71195f87ce8046467a176568e58
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev to ensure it continues to work
|
||||
run: yarn bazel build --config=aio_local_deps //adev:build
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@73777547f819464aa5f48071b966eed34fd2c402
|
||||
with:
|
||||
workflow-artifact-name: 'adev-preview'
|
||||
pull-number: '${{github.event.pull_request.number}}'
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
steps:
|
||||
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # tag=v3
|
||||
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
|
||||
with:
|
||||
token: '${{secrets.GITHUB_TOKEN}}'
|
||||
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
npx -y firebase-tools@latest target:clear --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs
|
||||
npx -y firebase-tools@latest target:apply --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs ${{env.PREVIEW_SITE}}
|
||||
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@73777547f819464aa5f48071b966eed34fd2c402
|
||||
with:
|
||||
github-token: '${{secrets.GITHUB_TOKEN}}'
|
||||
workflow-artifact-name: 'adev-preview'
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: ./.github/actions/yarn-install
|
||||
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
bazelrc: ./.bazelrc.user
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
# the number of concurrent actions is determined based on the host resources.
|
||||
- run: bazel build //aio:build --jobs=32 --announce_rc --verbose_failures
|
||||
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
workflow-artifact-name: 'aio'
|
||||
pull-number: '${{github.event.pull_request.number}}'
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
npx -y firebase-tools@latest target:clear --project ${{env.PREVIEW_PROJECT}} hosting aio
|
||||
npx -y firebase-tools@latest target:apply --project ${{env.PREVIEW_PROJECT}} hosting aio ${{env.PREVIEW_SITE}}
|
||||
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
github-token: '${{secrets.GITHUB_TOKEN}}'
|
||||
workflow-artifact-name: 'aio'
|
||||
|
||||
@@ -16,6 +16,6 @@ jobs:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: angular/dev-infra/github-actions/branch-manager@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- uses: angular/dev-infra/github-actions/branch-manager@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
|
||||
- uses: ./.github/actions/yarn-install
|
||||
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
bazelrc: ./.bazelrc.user
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
cache-node-modules: true
|
||||
# Checking out the pull request commit is intended here as we need to run the changed code tests.
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Starting Saucelabs tunnel service
|
||||
run: ./tools/saucelabs/sauce-service.sh run &
|
||||
# Build test fixtures for a test that rely on Bazel-generated fixtures. Note that disabling
|
||||
|
||||
+32
-30
@@ -23,7 +23,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
@@ -60,13 +60,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Run unit tests
|
||||
@@ -78,13 +78,13 @@ jobs:
|
||||
runs-on: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile --network-timeout 100000
|
||||
- name: Run CI tests for framework
|
||||
@@ -94,15 +94,15 @@ jobs:
|
||||
runs-on: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
./aio/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Install node modules for aio
|
||||
run: yarn install --cwd aio --frozen-lockfile
|
||||
- name: Run AIO tests with upstream packages
|
||||
@@ -115,11 +115,11 @@ jobs:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e52eb8237f2ed71195f87ce8046467a176568e58
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e52eb8237f2ed71195f87ce8046467a176568e58
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e52eb8237f2ed71195f87ce8046467a176568e58
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev to ensure it continues to work
|
||||
@@ -130,15 +130,15 @@ jobs:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
./aio/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Install node modules
|
||||
run: yarn install --cwd aio --frozen-lockfile
|
||||
- name: Run AIO tests with local packages
|
||||
@@ -153,15 +153,15 @@ jobs:
|
||||
labels: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
./aio/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Install node modules for aio
|
||||
run: yarn install --cwd aio --frozen-lockfile
|
||||
- name: Set the stable branch environment variable
|
||||
@@ -184,7 +184,7 @@ jobs:
|
||||
run: yarn --cwd aio deploy-production
|
||||
- name: Notify about failed deployment
|
||||
if: ${{ failure() }}
|
||||
uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v=v1.24.0
|
||||
uses: slackapi/slack-github-action@2a8087d4af6f83146a87539a70defe909fe6dbe6 # v=v1.24.0
|
||||
with:
|
||||
channel-id: 'C07DT5M6V,CKV1F72BG'
|
||||
slack-message: 'Deploy to aio job failed for ${{ github.base_ref }} branch failed on build ${{ github.event.after }}: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
|
||||
@@ -197,13 +197,13 @@ jobs:
|
||||
labels: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- run: echo "https://${{secrets.SNAPSHOT_BUILDS_GITHUB_TOKEN}}:@github.com" > ${HOME}/.git_credentials
|
||||
@@ -215,7 +215,7 @@ jobs:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
@@ -223,9 +223,9 @@ jobs:
|
||||
./packages/zone.js/node_modules
|
||||
./packages/zone.js/test/typings/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- run: |
|
||||
@@ -235,9 +235,11 @@ jobs:
|
||||
//packages/zone.js/test/closure:closure_js \
|
||||
|
||||
- run: |
|
||||
rm -Rf packages/zone.js/build
|
||||
rm -Rf packages/zone.js/test/extra/*.umd.js
|
||||
|
||||
mkdir -p packages/zone.js/build/
|
||||
mkdir -p packages/zone.js/build/test/
|
||||
mkdir -p packages/zone.js/test/
|
||||
|
||||
cp dist/bin/packages/zone.js/bundles/zone.umd.js packages/zone.js/build/zone.umd.js
|
||||
cp dist/bin/packages/zone.js/npm_package/bundles/zone-mix.umd.js ./packages/zone.js/test/extra/
|
||||
@@ -262,7 +264,7 @@ jobs:
|
||||
JOBS: 2
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
cache-node-modules: true
|
||||
# Checking out the pull request commit is intended here as we need to run the changed code tests.
|
||||
@@ -270,9 +272,9 @@ jobs:
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Set up Sauce Tunnel Daemon
|
||||
run: yarn bazel run //tools/saucelabs-daemon/background-service -- $JOBS &
|
||||
env:
|
||||
|
||||
@@ -13,13 +13,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: angular/dev-infra/github-actions/commit-message-based-labels@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- uses: angular/dev-infra/github-actions/commit-message-based-labels@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
post_approval_changes:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: angular/dev-infra/github-actions/post-approval-changes@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- uses: angular/dev-infra/github-actions/post-approval-changes@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -14,6 +14,6 @@ jobs:
|
||||
if: github.repository == 'angular/angular'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: angular/dev-infra/github-actions/feature-request@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- uses: angular/dev-infra/github-actions/feature-request@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: angular/dev-infra/github-actions/google-internal-tests@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- uses: angular/dev-infra/github-actions/google-internal-tests@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
run-tests-guide-url: http://go/angular-g3sync-start
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -9,6 +9,6 @@ jobs:
|
||||
status:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: angular/dev-infra/github-actions/unified-status-check@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- uses: angular/dev-infra/github-actions/unified-status-check@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -22,15 +22,15 @@ jobs:
|
||||
version: ['https://next.angular.io/', 'https://angular.io/']
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
./aio/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- name: Install node modules in aio
|
||||
run: yarn install --frozen-lockfile --cwd aio
|
||||
- name: Run basic e2e and deployment config tests.
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
env:
|
||||
ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN: ${{ secrets.ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN }}
|
||||
- name: Create a PR (if necessary)
|
||||
uses: angular/dev-infra/github-actions/create-pr-for-changes@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/create-pr-for-changes@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
branch-prefix: update-cli-help
|
||||
pr-title: 'docs: update Angular CLI help [${{github.ref_name}}]'
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
- name: Generate `events.json`
|
||||
run: node aio/scripts/generate-events/index.mjs --ignore-invalid-dates
|
||||
- name: Create a PR (if necessary)
|
||||
uses: angular/dev-infra/github-actions/create-pr-for-changes@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
uses: angular/dev-infra/github-actions/create-pr-for-changes@7bd2697b40203c84826129b611e539fa663881f8
|
||||
with:
|
||||
branch-prefix: docs-update-events
|
||||
pr-title: 'docs: update events'
|
||||
|
||||
+20
-1
@@ -14,13 +14,26 @@ export const format: FormatConfig = {
|
||||
'packages/animations/**/*.{js,ts}',
|
||||
'packages/bazel/**/*.{js,ts}',
|
||||
'packages/benchpress/**/*.{js,ts}',
|
||||
'packages/common/**/*.{js,ts}',
|
||||
'packages/docs/**/*.{js,ts}',
|
||||
'packages/elements/**/*.{js,ts}',
|
||||
'packages/examples/**/*.{js,ts}',
|
||||
'packages/misc/**/*.{js,ts}',
|
||||
'packages/private/**/*.{js,ts}',
|
||||
'packages/service-worker/**/*.{js,ts}',
|
||||
'packages/upgrade/**/*.{js,ts}',
|
||||
|
||||
// Do not format d.ts files as they are generated
|
||||
'!**/*.d.ts',
|
||||
// Both third_party and .yarn are directories containing copied code which should
|
||||
// not be modified.
|
||||
'!third_party/**',
|
||||
'!.yarn/**',
|
||||
],
|
||||
},
|
||||
'clang-format': {
|
||||
'matchers': [
|
||||
'**/*.{js,ts}',
|
||||
//'**/*.{js,ts}',
|
||||
// TODO: burn down format failures and remove aio and integration exceptions.
|
||||
'!aio/**',
|
||||
'!integration/**',
|
||||
@@ -51,8 +64,14 @@ export const format: FormatConfig = {
|
||||
'!packages/animations/**/*.{js,ts}',
|
||||
'!packages/bazel/**/*.{js,ts}',
|
||||
'!packages/benchpress/**/*.{js,ts}',
|
||||
'!packages/common/**/*.{js,ts}',
|
||||
'!packages/docs/**/*.{js,ts}',
|
||||
'!packages/elements/**/*.{js,ts}',
|
||||
'!packages/examples/**/*.{js,ts}',
|
||||
'!packages/misc/**/*.{js,ts}',
|
||||
'!packages/private/**/*.{js,ts}',
|
||||
'!packages/service-worker/**/*.{js,ts}',
|
||||
'!packages/upgrade/**/*.{js,ts}',
|
||||
],
|
||||
},
|
||||
'buildifier': true,
|
||||
|
||||
+2
-1
@@ -1069,9 +1069,10 @@ groups:
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- twerske
|
||||
- josephperrott
|
||||
- jelbourn
|
||||
- bencodezen
|
||||
- jessicajaniuk
|
||||
|
||||
# =========================================================
|
||||
# Docs-infra
|
||||
|
||||
+44
-7
@@ -1,3 +1,41 @@
|
||||
<a name="17.1.2"></a>
|
||||
# 17.1.2 (2024-01-31)
|
||||
###
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [ccddacf11d](https://github.com/angular/angular/commit/ccddacf11deaebeda12e1bdb6e93ec401397d352) | fix | cta clickability issue in adev homepage. ([#52905](https://github.com/angular/angular/pull/52905)) |
|
||||
### animations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [98d545fafa](https://github.com/angular/angular/commit/98d545fafa7fc3b1fb3ae049ce655e33ef9bd423) | fix | cleanup DOM elements when root view is removed with async animations ([#53033](https://github.com/angular/angular/pull/53033)) |
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [cdc5e39532](https://github.com/angular/angular/commit/cdc5e3953237a192beafd6330f9d9e36ede34f2c) | fix | The date pipe should return ISO format for week and week-year as intended in the unit test. ([#53879](https://github.com/angular/angular/pull/53879)) |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f12b01ec88](https://github.com/angular/angular/commit/f12b01ec88eaf18041c2e46335428627aa0d7744) | fix | Update type check block to fix control flow source mappings ([#53980](https://github.com/angular/angular/pull/53980)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c477e876e3](https://github.com/angular/angular/commit/c477e876e39495b855b096440d53cf1dd1ad33c6) | fix | change defer block fixture default behavior to playthrough ([#54088](https://github.com/angular/angular/pull/54088)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8264382a6b](https://github.com/angular/angular/commit/8264382a6bf389fb3fca75fa2d6c0a2aa5a1e42f) | fix | error in standalone migration when non-array value is used as declarations in TestBed ([#54122](https://github.com/angular/angular/pull/54122)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.1.1"></a>
|
||||
# 17.1.1 (2024-01-24)
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f222bee8fa](https://github.com/angular/angular/commit/f222bee8fa037f437761e5f7f127f22f280e9154) | fix | revert commit that replaced `last` helper with native `Array.at(-1)` ([#54021](https://github.com/angular/angular/pull/54021)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.1.0"></a>
|
||||
# 17.1.0 (2024-01-17)
|
||||
### compiler
|
||||
@@ -329,17 +367,16 @@ Live long and prosper 🖖🏻
|
||||
|
||||
Node.js v16 is planned to be End-of-Life on 2023-09-11. Angular will stop supporting Node.js v16 in Angular v17. For Node.js release schedule details, please see: https://github.com/nodejs/release#release-schedule
|
||||
### common
|
||||
-
|
||||
- the NgSwitch directive now defaults to the === equality operator,
|
||||
migrating from the previously used ==. NgSwitch expressions and / or
|
||||
migrating from the previously used == operator. NgSwitch expressions and / or
|
||||
individual condition values need adjusting to this stricter equality
|
||||
check. The added warning message should help pinpointing NgSwitch
|
||||
usages where adjustements are needed.
|
||||
check. The added warning message should help pin-pointing NgSwitch
|
||||
usages where adjustments are needed.
|
||||
### core
|
||||
- Angular now required `zone.js` version `~0.14.0`
|
||||
- Angular now requires `zone.js` version `~0.14.0`
|
||||
- Versions of TypeScript older than 5.2 are no longer supported.
|
||||
- The `mutate` method was removed from the `WritableSignal` interface and completely
|
||||
dropped from the public API surface. As an alternative please use the update method and
|
||||
dropped from the public API surface. As an alternative, please use the `update` method and
|
||||
make immutable changes to the object.
|
||||
|
||||
Example before:
|
||||
@@ -437,7 +474,7 @@ Live long and prosper 🖖🏻
|
||||
- Swapping out the context object for `EmbeddedViewRef`
|
||||
is no longer supported. Support for this was introduced with v12.0.0, but
|
||||
this pattern is rarely used. There is no replacement, but you can use
|
||||
simple assignments in most cases, or `Object.assign , or alternatively
|
||||
simple assignments in most cases, or `Object.assign` , or alternatively
|
||||
still replace the full object by using a `Proxy` (see `NgTemplateOutlet`
|
||||
as an example).
|
||||
|
||||
|
||||
@@ -196,10 +196,10 @@ cldr_xml_data_repository(
|
||||
# sass rules
|
||||
http_archive(
|
||||
name = "io_bazel_rules_sass",
|
||||
sha256 = "7a90567717c3417a23ff4b21963a698a6e9aa669ac9e682121ea33f218a2816a",
|
||||
strip_prefix = "rules_sass-425ecafa8268bc013d684216363fe75bc802323e",
|
||||
sha256 = "386ef2b97bd4342e45db450ce7eb5acb343d22f7580c0bbae89186dc009fa14e",
|
||||
strip_prefix = "rules_sass-d970cb53ad159e7fd1d3a99a00a530cc2c83eff9",
|
||||
urls = [
|
||||
"https://github.com/bazelbuild/rules_sass/archive/425ecafa8268bc013d684216363fe75bc802323e.zip",
|
||||
"https://github.com/bazelbuild/rules_sass/archive/d970cb53ad159e7fd1d3a99a00a530cc2c83eff9.zip",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/testing';
|
||||
|
||||
import {ProgressBarComponent} from './progress-bar.component';
|
||||
import {PROGRESS_BAR_DELAY, ProgressBarComponent} from './progress-bar.component';
|
||||
import {RouterTestingHarness, RouterTestingModule} from '@angular/router/testing';
|
||||
|
||||
describe('ProgressBarComponent', () => {
|
||||
let component: ProgressBarComponent;
|
||||
@@ -16,7 +17,7 @@ describe('ProgressBarComponent', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ProgressBarComponent],
|
||||
imports: [ProgressBarComponent, RouterTestingModule],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ProgressBarComponent);
|
||||
@@ -24,7 +25,13 @@ describe('ProgressBarComponent', () => {
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
it('should call progressBar.complete() on route change', fakeAsync(async () => {
|
||||
const progressBarCompleteSpy = spyOn(component.progressBar, 'complete');
|
||||
|
||||
const harness = await RouterTestingHarness.create();
|
||||
await harness.navigateByUrl('/');
|
||||
|
||||
tick(PROGRESS_BAR_DELAY);
|
||||
expect(progressBarCompleteSpy).toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
import {filter, map, switchMap, take} from 'rxjs/operators';
|
||||
|
||||
/** Time to wait after navigation starts before showing the progress bar. This delay allows a small amount of time to skip showing the progress bar when a navigation is effectively immediate. 30ms is approximately the amount of time we can wait before a delay is perceptible.*/
|
||||
const PROGRESS_BAR_DELAY = 30;
|
||||
export const PROGRESS_BAR_DELAY = 30;
|
||||
|
||||
@Component({
|
||||
selector: 'adev-progress-bar',
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
// seconday nav - translated on x to display levels
|
||||
// secondary nav - translated on x to display levels
|
||||
.adev-nav-secondary {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@@ -38,13 +38,13 @@ export class ThemeManager {
|
||||
}
|
||||
|
||||
this.loadThemePreference();
|
||||
this.watchPreferedColorScheme();
|
||||
this.watchPreferredColorScheme();
|
||||
}
|
||||
|
||||
setTheme(theme: Theme): void {
|
||||
this.theme.set(theme);
|
||||
this.setThemeInLocalStorage();
|
||||
this.setThemeBodyClasses(theme === 'auto' ? preferedScheme() : theme);
|
||||
this.setThemeBodyClasses(theme === 'auto' ? preferredScheme() : theme);
|
||||
}
|
||||
|
||||
// 1. Read theme preferences stored in localStorage
|
||||
@@ -54,7 +54,7 @@ export class ThemeManager {
|
||||
const useTheme = savedUserPreference ?? 'auto';
|
||||
|
||||
this.theme.set(useTheme);
|
||||
this.setThemeBodyClasses(useTheme === 'auto' ? preferedScheme() : useTheme);
|
||||
this.setThemeBodyClasses(useTheme === 'auto' ? preferredScheme() : useTheme);
|
||||
}
|
||||
|
||||
// Set theme classes on the body element
|
||||
@@ -81,14 +81,14 @@ export class ThemeManager {
|
||||
}
|
||||
}
|
||||
|
||||
private watchPreferedColorScheme() {
|
||||
private watchPreferredColorScheme() {
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (event) => {
|
||||
const preferedScheme = event.matches ? 'dark' : 'light';
|
||||
this.setThemeBodyClasses(preferedScheme);
|
||||
const preferredScheme = event.matches ? 'dark' : 'light';
|
||||
this.setThemeBodyClasses(preferredScheme);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function preferedScheme(): 'dark' | 'light' {
|
||||
function preferredScheme(): 'dark' | 'light' {
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ export const getTooltipExtension = (
|
||||
dom: tooltip,
|
||||
|
||||
// Note: force the tooltip to scroll to the top on mount and on position change
|
||||
// because depending on the position of the mouse and the siez of the tooltip content,
|
||||
// because depending on the position of the mouse and the size of the tooltip content,
|
||||
// the tooltip might render with its initial scroll position on the bottom
|
||||
mount: (_) => forceTooltipScrollTop(),
|
||||
positioned: (_) => forceTooltipScrollTop(),
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</as-split-area>
|
||||
|
||||
<as-split-area [size]="50">
|
||||
<!-- Preview, Termnial & Console -->
|
||||
<!-- Preview, Terminal & Console -->
|
||||
@if (!displayOnlyTerminal()) {
|
||||
<as-split class="adev-right-side" direction="vertical" restrictMove="true" gutterSize="5">
|
||||
<!-- Preview Section: for larger screens -->
|
||||
|
||||
@@ -26,7 +26,7 @@ export const DEV_SERVER_READY_MSG = 'Watch mode enabled. Watching for file chang
|
||||
export const OUT_OF_MEMORY_MSG = 'Out of memory';
|
||||
|
||||
const enum PROCESS_EXIT_CODE {
|
||||
SUCCESS = 0, // process exited succesfully
|
||||
SUCCESS = 0, // process exited successfully
|
||||
ERROR = 10, // process exited with error
|
||||
SIGTERM = 143, // 143 = gracefully terminated by SIGTERM, e.g. Ctrl + C
|
||||
}
|
||||
@@ -73,7 +73,7 @@ export class NodeRuntimeSandbox {
|
||||
}
|
||||
|
||||
async init(): Promise<void> {
|
||||
// Note: the error state can already be set when loading the NodeRuntimeSanbox
|
||||
// Note: the error state can already be set when loading the NodeRuntimeSandbox
|
||||
// in an unsupported environment.
|
||||
if (this.nodeRuntimeState.error()) {
|
||||
return;
|
||||
@@ -155,7 +155,7 @@ export class NodeRuntimeSandbox {
|
||||
* Initialize the WebContainer for an Angular project
|
||||
*/
|
||||
private async initProject(): Promise<void> {
|
||||
// prevent re-initializion
|
||||
// prevent re-initialization
|
||||
if (this._isProjectInitialized()) return;
|
||||
|
||||
// clean up the sandbox if it was initialized before so that the CLI can
|
||||
@@ -230,7 +230,7 @@ export class NodeRuntimeSandbox {
|
||||
* Initialize the WebContainer for the Angular CLI
|
||||
*/
|
||||
private async initAngularCli() {
|
||||
// prevent re-initializion
|
||||
// prevent re-initialization
|
||||
if (this._isAngularCliInitialized()) return;
|
||||
|
||||
// clean up the sandbox if a project was initialized before so the CLI can
|
||||
@@ -292,7 +292,7 @@ export class NodeRuntimeSandbox {
|
||||
|
||||
const terminal = this.terminalHandler.interactiveTerminalInstance;
|
||||
|
||||
// use WebContainer spawn directly so that the proccess isn't killed on
|
||||
// use WebContainer spawn directly so that the process isn't killed on
|
||||
// cleanup
|
||||
const shellProcess = await webContainer.spawn('bash');
|
||||
|
||||
@@ -516,10 +516,10 @@ export class NodeRuntimeSandbox {
|
||||
|
||||
/**
|
||||
* Kill existing processes and remove files from the WebContainer
|
||||
* when switching tutorials that have diferent requirements
|
||||
* when switching tutorials that have different requirements
|
||||
*/
|
||||
private async cleanup() {
|
||||
// await the proccess to be killed before removing the files because
|
||||
// await the process to be killed before removing the files because
|
||||
// a process can create files during the promise
|
||||
await this.killExistingProcesses();
|
||||
await this.removeFiles();
|
||||
|
||||
@@ -80,7 +80,7 @@ export class TypingsLoader {
|
||||
.readFile(`./node_modules/${library}/package.json`, 'utf-8')
|
||||
.catch((error) => {
|
||||
// Note: "ENOENT" errors occurs:
|
||||
// - While reseting the NodeRuntimeSandbox.
|
||||
// - While resetting the NodeRuntimeSandbox.
|
||||
// - When the library is not a dependency in the project, its package.json won't exist.
|
||||
//
|
||||
// In both cases we ignore the error to continue the process.
|
||||
|
||||
@@ -142,7 +142,8 @@
|
||||
display: inline-block;
|
||||
padding: 7px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.5s linear;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.5s linear, visibility 0.5s linear;
|
||||
|
||||
button {
|
||||
font-size: 1rem;
|
||||
@@ -307,6 +308,7 @@
|
||||
.adev-cta,
|
||||
.adev-arrow {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import ApiItemLabel from './api-item-label.component';
|
||||
import {ApiItemType} from '../interfaces/api-item-type';
|
||||
|
||||
describe('ApiItemLabel', () => {
|
||||
let component: ApiItemLabel;
|
||||
@@ -23,7 +24,32 @@ describe('ApiItemLabel', () => {
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
it('should by default display short label for Class', () => {
|
||||
component.type = ApiItemType.CLASS;
|
||||
fixture.detectChanges();
|
||||
|
||||
const label = fixture.nativeElement.innerText;
|
||||
|
||||
expect(label).toBe('C');
|
||||
});
|
||||
|
||||
it('should display full label for Class when labelMode equals full', () => {
|
||||
component.type = ApiItemType.CLASS;
|
||||
component.mode = 'full';
|
||||
fixture.detectChanges();
|
||||
|
||||
const label = fixture.nativeElement.innerText;
|
||||
|
||||
expect(label).toBe('Class');
|
||||
});
|
||||
|
||||
it('should display short label for Class when labelMode equals short', () => {
|
||||
component.type = ApiItemType.CLASS;
|
||||
component.mode = 'short';
|
||||
fixture.detectChanges();
|
||||
|
||||
const label = fixture.nativeElement.innerText;
|
||||
|
||||
expect(label).toBe('C');
|
||||
});
|
||||
});
|
||||
|
||||
+79
-4
@@ -13,17 +13,44 @@ import {ApiItemsGroup} from '../interfaces/api-items-group';
|
||||
import {ApiReferenceManager} from '../api-reference-list/api-reference-manager.service';
|
||||
import {ApiItemType} from '../interfaces/api-item-type';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import {By} from '@angular/platform-browser';
|
||||
|
||||
describe('ApiItemsSection', () => {
|
||||
let component: ApiItemsSection;
|
||||
let fixture: ComponentFixture<ApiItemsSection>;
|
||||
let apiReferenceManagerSpy: jasmine.SpyObj<ApiReferenceManager>;
|
||||
|
||||
const fakeGroup: ApiItemsGroup = {
|
||||
const fakeFeaturedGroup: ApiItemsGroup = {
|
||||
title: 'Featured',
|
||||
isFeatured: true,
|
||||
items: [
|
||||
{title: 'Fake Title', itemType: ApiItemType.CLASS, url: 'api/fakeTitle', isFeatured: true},
|
||||
{
|
||||
title: 'Fake Featured Title',
|
||||
itemType: ApiItemType.CLASS,
|
||||
url: 'api/fakeFeaturedTitle',
|
||||
isFeatured: true,
|
||||
},
|
||||
{
|
||||
title: 'Fake Deprecated Title',
|
||||
itemType: ApiItemType.CONST,
|
||||
url: 'api/fakeDeprecatedTitle',
|
||||
isFeatured: false,
|
||||
isDeprecated: true,
|
||||
},
|
||||
{
|
||||
title: 'Fake Standard Title',
|
||||
itemType: ApiItemType.DIRECTIVE,
|
||||
url: 'api/fakeTitle',
|
||||
isFeatured: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const fakeGroup: ApiItemsGroup = {
|
||||
title: 'Example group',
|
||||
isFeatured: false,
|
||||
items: [
|
||||
{title: 'Fake Title', itemType: ApiItemType.CONST, url: 'api/fakeTitle', isFeatured: false},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -34,12 +61,60 @@ describe('ApiItemsSection', () => {
|
||||
});
|
||||
fixture = TestBed.createComponent(ApiItemsSection);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
it('should render star icon for featured group', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.detectChanges();
|
||||
|
||||
const starIcon = fixture.debugElement.query(By.css('.adev-api-items-section-header docs-icon'));
|
||||
|
||||
expect(starIcon).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not render star icon for standard group', () => {
|
||||
component.group = fakeGroup;
|
||||
fixture.detectChanges();
|
||||
|
||||
const starIcon = fixture.debugElement.query(By.css('.adev-api-items-section-header docs-icon'));
|
||||
|
||||
expect(starIcon).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
it('should render list of all APIs of provided group', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.detectChanges();
|
||||
|
||||
const apis = fixture.debugElement.queryAll(By.css('.adev-api-items-section-grid li'));
|
||||
|
||||
expect(apis.length).toBe(3);
|
||||
});
|
||||
|
||||
it('should display deprecated icon for deprecated API', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.detectChanges();
|
||||
|
||||
const deprecatedApiIcons = fixture.debugElement.queryAll(
|
||||
By.css('.adev-api-items-section-grid li .adev-deprecated'),
|
||||
);
|
||||
const deprecatedApiTitle = deprecatedApiIcons[0].parent?.query(By.css('.adev-item-title'));
|
||||
|
||||
expect(deprecatedApiIcons.length).toBe(1);
|
||||
expect(deprecatedApiIcons[0]).toBeTruthy();
|
||||
expect(deprecatedApiTitle?.nativeElement.innerText).toBe('Fake Deprecated Title');
|
||||
});
|
||||
|
||||
it('should display star icon for featured API', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.detectChanges();
|
||||
|
||||
const featuredApiIcons = fixture.debugElement.queryAll(
|
||||
By.css('.adev-api-items-section-grid li .adev-api-items-section-item-featured'),
|
||||
);
|
||||
const featuredApiTitle = featuredApiIcons[0].parent?.query(By.css('.adev-item-title'));
|
||||
|
||||
expect(featuredApiIcons.length).toBe(1);
|
||||
expect(featuredApiIcons[0]).toBeTruthy();
|
||||
expect(featuredApiTitle?.nativeElement.innerText).toBe('Fake Featured Title');
|
||||
});
|
||||
});
|
||||
|
||||
+37
-6
@@ -17,22 +17,25 @@ import {provideRouter} from '@angular/router';
|
||||
import {RouterTestingHarness, RouterTestingModule} from '@angular/router/testing';
|
||||
|
||||
import ApiReferenceDetailsPage from './api-reference-details-page.component';
|
||||
import {By} from '@angular/platform-browser';
|
||||
|
||||
describe('ApiReferenceDetailsPage', () => {
|
||||
let component: ApiReferenceDetailsPage;
|
||||
let loader: HarnessLoader;
|
||||
let harness: RouterTestingHarness;
|
||||
|
||||
let fakeApiReferenceScrollHandler = {
|
||||
setupListeners: () => {},
|
||||
membersMarginTopInPx: signal(0),
|
||||
membersMarginTopInPx: signal(10),
|
||||
updateMembersMarginTop: () => {},
|
||||
};
|
||||
|
||||
const SAMPLE_CONTENT_WITH_TABS = `<div class="adev-reference-tabs">
|
||||
<div data-tab="API" class="adev-reference-tab"></div>
|
||||
<div data-tab="Description" class="adev-reference-tab"></div>
|
||||
<div data-tab="Examples" class="adev-reference-tab"></div>
|
||||
<div data-tab="Usage Notes" class="adev-reference-tab"></div>
|
||||
<div data-tab="API" data-tab-url="api" class="adev-reference-tab"></div>
|
||||
<div data-tab="Description" data-tab-url="description" class="adev-reference-tab"></div>
|
||||
<div data-tab="Examples" data-tab-url="examples" class="adev-reference-tab"></div>
|
||||
<div data-tab="Usage Notes" data-tab-url="usage-notes" class="adev-reference-tab"></div>
|
||||
<div class="adev-reference-members-container"></div>
|
||||
</div>`;
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -54,7 +57,7 @@ describe('ApiReferenceDetailsPage', () => {
|
||||
],
|
||||
});
|
||||
TestBed.overrideProvider(ReferenceScrollHandler, {useValue: fakeApiReferenceScrollHandler});
|
||||
const harness = await RouterTestingHarness.create();
|
||||
harness = await RouterTestingHarness.create();
|
||||
const {fixture} = harness;
|
||||
component = await harness.navigateByUrl('/', ApiReferenceDetailsPage);
|
||||
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
@@ -72,4 +75,32 @@ describe('ApiReferenceDetailsPage', () => {
|
||||
|
||||
expect(tabs.length).toBe(4);
|
||||
}));
|
||||
|
||||
it('should display members cards when API tab is active', waitForAsync(async () => {
|
||||
const matTabGroup = await loader.getHarness(MatTabGroupHarness);
|
||||
const tabs = await matTabGroup.getTabs();
|
||||
|
||||
let membersCard = harness.fixture.debugElement.query(
|
||||
By.css('.adev-reference-members-container'),
|
||||
);
|
||||
expect(membersCard).toBeTruthy();
|
||||
|
||||
await matTabGroup.selectTab({label: await tabs[1].getLabel()});
|
||||
|
||||
membersCard = harness.fixture.debugElement.query(By.css('.adev-reference-members-container'));
|
||||
expect(membersCard).toBeFalsy();
|
||||
|
||||
await matTabGroup.selectTab({label: await tabs[0].getLabel()});
|
||||
|
||||
membersCard = harness.fixture.debugElement.query(By.css('.adev-reference-members-container'));
|
||||
expect(membersCard).toBeTruthy();
|
||||
}));
|
||||
|
||||
it('should setup scroll listeners when API members are loaded', () => {
|
||||
const setupListenersSpy = spyOn(fakeApiReferenceScrollHandler, 'setupListeners');
|
||||
|
||||
component.membersCardsLoaded();
|
||||
|
||||
expect(setupListenersSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
+17
-1
@@ -8,7 +8,7 @@
|
||||
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import ApiReferenceList from './api-reference-list.component';
|
||||
import ApiReferenceList, {ALL_STATUSES_KEY} from './api-reference-list.component';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import {ApiReferenceManager} from './api-reference-manager.service';
|
||||
import {signal} from '@angular/core';
|
||||
@@ -95,4 +95,20 @@ describe('ApiReferenceList', () => {
|
||||
|
||||
expect(component.filteredGroups()![0].items).toEqual([fakeItem2]);
|
||||
});
|
||||
|
||||
it('should set selected type when provided type is different than selected', () => {
|
||||
component.filterByItemType(ApiItemType.BLOCK);
|
||||
|
||||
expect(component.type()).toBe(ApiItemType.BLOCK);
|
||||
});
|
||||
|
||||
it('should reset selected type when provided type is equal to selected', () => {
|
||||
component.filterByItemType(ApiItemType.BLOCK);
|
||||
|
||||
expect(component.type()).toBe(ApiItemType.BLOCK);
|
||||
|
||||
component.filterByItemType(ApiItemType.BLOCK);
|
||||
|
||||
expect(component.type()).toBe(ALL_STATUSES_KEY);
|
||||
});
|
||||
});
|
||||
|
||||
+33
-7
@@ -6,16 +6,18 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
|
||||
import CliReferenceDetailsPage from './cli-reference-details-page.component';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import {RouterTestingHarness, RouterTestingModule} from '@angular/router/testing';
|
||||
import {signal} from '@angular/core';
|
||||
import {ReferenceScrollHandler} from '../services/reference-scroll-handler.service';
|
||||
import {provideRouter} from '@angular/router';
|
||||
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
|
||||
|
||||
describe('CliReferenceDetailsPage', () => {
|
||||
let component: CliReferenceDetailsPage;
|
||||
let fixture: ComponentFixture<CliReferenceDetailsPage>;
|
||||
let harness: RouterTestingHarness;
|
||||
|
||||
let fakeApiReferenceScrollHandler = {
|
||||
setupListeners: () => {},
|
||||
@@ -23,18 +25,42 @@ describe('CliReferenceDetailsPage', () => {
|
||||
updateMembersMarginTop: () => {},
|
||||
};
|
||||
|
||||
const SAMPLE_CONTENT = `
|
||||
<div class="cli">
|
||||
<div class="adev-reference-cli-content">First column content</div>
|
||||
<div class="adev-reference-members-container">Members content</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
beforeEach(async () => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CliReferenceDetailsPage, RouterTestingModule],
|
||||
providers: [
|
||||
provideRouter([
|
||||
{
|
||||
path: '**',
|
||||
component: CliReferenceDetailsPage,
|
||||
data: {
|
||||
'docContent': {
|
||||
id: 'id',
|
||||
contents: SAMPLE_CONTENT,
|
||||
},
|
||||
},
|
||||
},
|
||||
]),
|
||||
],
|
||||
});
|
||||
TestBed.overrideProvider(ReferenceScrollHandler, {useValue: fakeApiReferenceScrollHandler});
|
||||
|
||||
fixture = TestBed.createComponent(CliReferenceDetailsPage);
|
||||
component = fixture.componentInstance;
|
||||
harness = await RouterTestingHarness.create();
|
||||
const {fixture} = harness;
|
||||
component = await harness.navigateByUrl('/', CliReferenceDetailsPage);
|
||||
TestbedHarnessEnvironment.loader(fixture);
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
it('should set content on init', () => {
|
||||
expect(component.mainContentInnerHtml()).toBe('First column content');
|
||||
expect(component.cardsInnerHtml()).toBe('Members content');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -56,10 +56,12 @@ export function getApiNavigationItems(): NavigationItem[] {
|
||||
|
||||
const packageNavigationItem: NavigationItem = {
|
||||
label: packageNameWithoutPrefix,
|
||||
children: packageApis.map((api) => ({
|
||||
path: getApiUrl(packageNameWithoutPrefix, api.name),
|
||||
label: api.name,
|
||||
})),
|
||||
children: packageApis
|
||||
.map((api) => ({
|
||||
path: getApiUrl(packageNameWithoutPrefix, api.name),
|
||||
label: api.name,
|
||||
}))
|
||||
.sort((a, b) => a.label.localeCompare(b.label)),
|
||||
};
|
||||
|
||||
apiNavigationItems.push(packageNavigationItem);
|
||||
|
||||
@@ -6,11 +6,23 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ApiItemType} from '../interfaces/api-item-type';
|
||||
import {ApiLabel} from './api-label.pipe';
|
||||
|
||||
describe('ApiLabel', () => {
|
||||
it('create an instance', () => {
|
||||
const pipe = new ApiLabel();
|
||||
expect(pipe).toBeTruthy();
|
||||
let pipe: ApiLabel;
|
||||
|
||||
beforeEach(() => {
|
||||
pipe = new ApiLabel();
|
||||
});
|
||||
|
||||
it(`should return short label when labelType equals short`, () => {
|
||||
const result = pipe.transform(ApiItemType.CLASS, 'short');
|
||||
expect(result).toBe('C');
|
||||
});
|
||||
|
||||
it(`should return short label when labelType equals short`, () => {
|
||||
const result = pipe.transform(ApiItemType.CLASS, 'full');
|
||||
expect(result).toBe('Class');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -160,6 +160,9 @@ export class ReferenceScrollHandler implements OnDestroy, ReferenceScrollHandler
|
||||
for (const line of Array.from(activeLines)) {
|
||||
line.classList.remove(API_TAB_ACTIVE_CODE_LINE);
|
||||
}
|
||||
this.getAllMemberCards().forEach((card) => {
|
||||
card.blur();
|
||||
});
|
||||
} else {
|
||||
const lines = this.document.querySelectorAll<HTMLButtonElement>(
|
||||
`button[${MEMBER_ID_ATTRIBUTE}="${currentActiveMemberId}"]`,
|
||||
@@ -167,6 +170,7 @@ export class ReferenceScrollHandler implements OnDestroy, ReferenceScrollHandler
|
||||
for (const line of Array.from(lines)) {
|
||||
line.classList.add(API_TAB_ACTIVE_CODE_LINE);
|
||||
}
|
||||
this.document.getElementById(`${currentActiveMemberId}`)?.focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@use '@angular/docs/styles/media-queries' as mq;
|
||||
|
||||
// horizozntal tutorial nav bar
|
||||
// horizontal tutorial nav bar
|
||||
.adev-tutorial-nav-container {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
|
||||
@@ -125,6 +125,7 @@ export const routes: Route[] = [
|
||||
{
|
||||
path: '',
|
||||
loadComponent: () => import('./features/home/home.component'),
|
||||
data: {label: 'Home'}
|
||||
},
|
||||
{
|
||||
path: PagePrefix.DOCS,
|
||||
@@ -141,7 +142,7 @@ export const routes: Route[] = [
|
||||
{
|
||||
path: PagePrefix.PLAYGROUND,
|
||||
loadComponent: () => import('./features/playground/playground.component'),
|
||||
data: {...commonTutorialRouteData},
|
||||
data: {...commonTutorialRouteData, label: 'Playground'},
|
||||
},
|
||||
...SUB_NAVIGATION_ROUTES,
|
||||
...API_REFERENCE_ROUTES,
|
||||
|
||||
@@ -943,6 +943,7 @@ export const TUTORIALS_SUB_NAVIGATION_DATA: NavigationItem[] = [
|
||||
{
|
||||
path: DefaultPage.TUTORIALS,
|
||||
contentPath: 'tutorials/home',
|
||||
label: 'Tutorials'
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1336,6 +1337,11 @@ const REFERENCE_SUB_NAVIGATION_DATA: NavigationItem[] = [
|
||||
path: 'reference/migrations/typed-forms',
|
||||
contentPath: 'reference/migrations/typed-forms',
|
||||
},
|
||||
{
|
||||
label: 'Control Flow Syntax',
|
||||
path: 'reference/migrations/control-flow',
|
||||
contentPath: 'reference/migrations/control-flow',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -19,7 +19,7 @@ In the image above, there is a series of change detection calls triggered by eve
|
||||
|
||||
## Run tasks outside `NgZone`
|
||||
|
||||
In such cases, you can instruct Angular to avoid calling change detection for tasks scheduled by a given piece of code using [NgZone](/guide/zone).
|
||||
In such cases, you can instruct Angular to avoid calling change detection for tasks scheduled by a given piece of code using [NgZone](/api/core/NgZone).
|
||||
|
||||
<docs-code header="Run outside of the Zone" language='ts' linenums>
|
||||
import { Component, NgZone, OnInit } from '@angular/core';
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Architect } from '@angular-devkit/architect';
|
||||
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
|
||||
import { schema } from '@angular-devkit/core';
|
||||
import { promises as fs } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
describe('Copy File Builder', () => {
|
||||
let architect: Architect;
|
||||
@@ -19,7 +20,7 @@ describe('Copy File Builder', () => {
|
||||
|
||||
// This will either take a Node package name, or a path to the directory
|
||||
// for the package.json file.
|
||||
await architectHost.addBuilderFromPackage('..');
|
||||
await architectHost.addBuilderFromPackage(join(__dirname, '..'));
|
||||
});
|
||||
|
||||
it('can copy files', async () => {
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
// #docregion
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HeroModule } from './hero.module';
|
||||
import { HEROES } from './mock-heroes';
|
||||
|
||||
@Injectable({
|
||||
// we declare that this service should be created
|
||||
// by any injector that includes HeroModule.
|
||||
providedIn: HeroModule,
|
||||
})
|
||||
export class HeroService {
|
||||
getHeroes() { return HEROES; }
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AppPage } from './app.po';
|
||||
|
||||
describe('forms-overvoew App', () => {
|
||||
describe('forms-overview App', () => {
|
||||
let page: AppPage;
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
load("//aio/content/examples:examples.bzl", "docs_example")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
docs_example(
|
||||
name = "providers",
|
||||
)
|
||||
@@ -1,23 +0,0 @@
|
||||
import { element, by } from 'protractor';
|
||||
import { AppPage } from './app.po';
|
||||
|
||||
describe('providers App', () => {
|
||||
let page: AppPage;
|
||||
|
||||
beforeEach(async () => {
|
||||
page = new AppPage();
|
||||
await page.navigateTo();
|
||||
});
|
||||
|
||||
it('should display header that says Users list', async () => {
|
||||
expect(await page.getTitleText()).toEqual('Users list');
|
||||
});
|
||||
|
||||
it('shows a list of customers', async () => {
|
||||
const items = element.all(by.css('app-root li'));
|
||||
expect(await items.count()).toBe(10);
|
||||
expect(await items.get(0).getText()).toBe('1 Maria');
|
||||
expect(await items.get(9).getText()).toBe('10 Seth');
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
<h1>
|
||||
{{ title }}
|
||||
</h1>
|
||||
|
||||
<li *ngFor="let user of users">
|
||||
<span>{{ user.id }}</span> {{ user.name }}
|
||||
</li>
|
||||
@@ -1,25 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { User, UserService } from './user.service';
|
||||
|
||||
// #docregion component-providers
|
||||
@Component({
|
||||
// #enddocregion component-providers
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css'],
|
||||
// #docregion component-providers
|
||||
providers: [UserService]
|
||||
})
|
||||
// #enddocregion component-providers
|
||||
export class AppComponent implements OnInit {
|
||||
title = 'Users list';
|
||||
users: User[] = [];
|
||||
|
||||
constructor(private userService: UserService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.userService.getUsers().then(users => this.users = users);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { UserService } from './user.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [ BrowserModule ],
|
||||
declarations: [ AppComponent ],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule { }
|
||||
@@ -1,9 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { UserService } from './user.service';
|
||||
|
||||
@NgModule({
|
||||
providers: [UserService],
|
||||
})
|
||||
export class UserModule {
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class UserService {
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { UserModule } from './user.module';
|
||||
|
||||
@Injectable({
|
||||
providedIn: UserModule,
|
||||
})
|
||||
export class UserService {
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'any',
|
||||
})
|
||||
export class UserService {
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
export interface User {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class UserService {
|
||||
getUsers(): Promise<User[]> {
|
||||
return Promise.resolve([
|
||||
{ id: 1, name: 'Maria' },
|
||||
{ id: 2, name: 'Alex' },
|
||||
{ id: 3, name: 'Chuntao' },
|
||||
{ id: 4, name: 'Béatrice' },
|
||||
{ id: 5, name: 'Sarah' },
|
||||
{ id: 6, name: 'Andrés' },
|
||||
{ id: 7, name: 'Abdul' },
|
||||
{ id: 8, name: 'Pierre' },
|
||||
{ id: 9, name: 'Jiao' },
|
||||
{ id: 10, name: 'Seth' }
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Providers</title>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<app-root>Loading...</app-root>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,6 +0,0 @@
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module';
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||
.catch(err => console.error(err));
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"description": "Providers",
|
||||
"files": [
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[0,1,2].*"
|
||||
],
|
||||
"file": "src/app/app.component.ts",
|
||||
"tags": ["providers"]
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
<div class="section">
|
||||
<h2>@Optional() Component</h2>
|
||||
<p>This component still works even though the OptionalService (notice @Optional() in the consturctor isn't provided or configured anywhere. Angular goes through tree and visibilty rules, and if it doesn't find the requested service, returns null.</p>
|
||||
<p>This component still works even though the OptionalService (notice @Optional() in the constructor isn't provided or configured anywhere. Angular goes through tree and visibility rules, and if it doesn't find the requested service, returns null.</p>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// TODO: Feature Componetized like HeroCenter
|
||||
// TODO: Feature Componentized like HeroCenter
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
// TODO: Feature Componetized like CrisisCenter
|
||||
// TODO: Feature Componentized like CrisisCenter
|
||||
// #docregion rxjs-imports
|
||||
import { Observable } from 'rxjs';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
|
||||
@@ -41,7 +41,7 @@ describe('Lazy Loading AngularJS Tests', () => {
|
||||
|
||||
// Workaround for https://github.com/angular/protractor/issues/4724
|
||||
async function loadAngularJS() {
|
||||
// Abort if `resumeBootstrap` has already occured
|
||||
// Abort if `resumeBootstrap` has already occurred
|
||||
if (await browser.executeScript(`return '__TESTABILITY__NG1_APP_ROOT_INJECTOR__' in window;`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@ application-wide. Activities that trigger this checking include user interaction
|
||||
timers, and more.
|
||||
|
||||
**`ChangeDetectionStrategy.OnPush`** is an optional mode that reduces the amount of checking Angular
|
||||
needs to perform. In this mode, the framework only checks if a component's DOM needs an update when
|
||||
needs to perform. In this mode, the framework only checks if a component's DOM needs an update when:
|
||||
|
||||
- A component input has changes as a result of a binding in a template, or
|
||||
- When an event listener in this component runs
|
||||
- When the component is explicitly marked for check, via `ChangeDetectorRef.markForCheck` or something which wraps it, like `AsyncPipe`.
|
||||
- An event listener in this component runs
|
||||
- The component is explicitly marked for check, via `ChangeDetectorRef.markForCheck` or something which wraps it, like `AsyncPipe`.
|
||||
|
||||
Additionally, when an OnPush component is checked, Angular _also_ checks all of its ancestor
|
||||
components, traversing upwards through the application tree.
|
||||
|
||||
@@ -31,7 +31,7 @@ process.
|
||||
<td>Creation</td>
|
||||
<td><code>constructor</code></td>
|
||||
<td>
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/constructor">
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/constructor" target="_blank">
|
||||
Standard JavaScript class constructor
|
||||
</a>. Runs when Angular instantiates the component.
|
||||
</td>
|
||||
@@ -226,7 +226,7 @@ invoked after Angular has finished rendering _all components_ on the page into t
|
||||
|
||||
These functions are different from the other lifecycle hooks described in this guide. Rather than a
|
||||
class method, they are standalone functions that accept a callback. The execution of render
|
||||
callbacks is not tied to any specific component instance, but instead an application-wide hook.
|
||||
callbacks are not tied to any specific component instance, but instead an application-wide hook.
|
||||
|
||||
`afterRender` and `afterNextRender` must be called in
|
||||
an [injection context](guide/di/dependency-injection-context), typically a
|
||||
@@ -259,7 +259,7 @@ export class UserProfile {
|
||||
nativeElement.style.padding = computePadding();
|
||||
}, {phase: AfterRenderPhase.Write});
|
||||
|
||||
// Use the `Read` phase to read geometric properties after all writes have occured.
|
||||
// Use the `Read` phase to read geometric properties after all writes have occurred.
|
||||
afterNextRender(() => {
|
||||
this.elementHeight = nativeElement.getBoundingClientRect().height;
|
||||
}, {phase: AfterRenderPhase.Read});
|
||||
|
||||
@@ -40,7 +40,7 @@ directive's capabilities.
|
||||
|
||||
A **view container** is a node in Angular's component tree that can contain content. Any component
|
||||
or directive can inject `ViewContainerRef` to get a reference to a view container corresponding to
|
||||
that component or directive's location in the DOM..
|
||||
that component or directive's location in the DOM.
|
||||
|
||||
You can use the `createComponent`method on `ViewContainerRef` to dynamically create and render a
|
||||
component. When you create a new component with a `ViewContainerRef`, Angular appends it into the
|
||||
|
||||
@@ -147,7 +147,7 @@ export class CustomMenu {
|
||||
<custom-menu>
|
||||
<custom-menu-item>Cheese</custom-menu-item>
|
||||
<custom-menu-item>Tomato</custom-menu-item>
|
||||
</custom-expando>
|
||||
</custom-menu>
|
||||
`
|
||||
})
|
||||
</docs-code>
|
||||
|
||||
@@ -14,8 +14,7 @@ In the following example, the app component provides a `Logger` instance.
|
||||
providers: [Logger],
|
||||
</docs-code>
|
||||
|
||||
You can, however, configure DI to use a different class or any other different value to associate with the `Logger` class.
|
||||
Note that `Logger` becomes is only used as "token" for the dependency then.
|
||||
You can, however, configure DI to associate the `Logger` provider token with a different class or any other value.
|
||||
So when the `Logger` is injected, the configured value is used instead.
|
||||
|
||||
In fact, the class provider syntax is a shorthand expression that expands into a provider configuration, defined by the `Provider` interface.
|
||||
|
||||
@@ -1143,7 +1143,7 @@ graph BT;
|
||||
subgraph A[" "]
|
||||
direction LR
|
||||
RootInjector["(A) RootInjector"]
|
||||
ServicesA["CarService, EngineService, TitleService"]
|
||||
ServicesA["CarService, EngineService, TiresService"]
|
||||
end
|
||||
|
||||
subgraph B[" "]
|
||||
|
||||
@@ -5,7 +5,7 @@ This tutorial shows you how to create a template-driven form. The control elemen
|
||||
Template-driven forms use [two-way data binding](guide/templates/two-way-binding) to update the data model in the component as changes are made in the template and vice versa.
|
||||
|
||||
<docs-callout helpful title="Template vs Reactive forms">
|
||||
Angular supports two design approaches for interactive forms. Template-driven forms allow you to use form-specific directives in your Angular template.Reactive forms provide a model-driven approach to buildin forms.
|
||||
Angular supports two design approaches for interactive forms. Template-driven forms allow you to use form-specific directives in your Angular template.Reactive forms provide a model-driven approach to building forms.
|
||||
|
||||
Template-driven forms are a great choice for small or simple forms, while reactive forms are more scalable and suitable for complex forms. For a comparison of the two approaches, see [Choosing an approach](guide/forms#choosing-an-approach)
|
||||
</docs-callout>
|
||||
|
||||
@@ -39,7 +39,7 @@ In order for this interceptor to actually intercept requests, you must configure
|
||||
|
||||
## Configuring interceptors
|
||||
|
||||
You declare the set of interceptors to use when when configuring `HttpClient` through dependency injection, by using the `withInterceptors` feature:
|
||||
You declare the set of interceptors to use when configuring `HttpClient` through dependency injection, by using the `withInterceptors` feature:
|
||||
|
||||
<docs-code language="ts">
|
||||
bootstrapApplication(AppComponent, {providers: [
|
||||
@@ -175,7 +175,7 @@ A DI-based interceptor is an injectable class which implements the `HttpIntercep
|
||||
public class LoggingInterceptor implements HttpInterceptor {
|
||||
intercept(req: HttpRequest<any>, handler: HttpHandler): Observable<HttpEvent<any>> {
|
||||
console.log('Request URL: ' + req.url);
|
||||
return handler.next(req);
|
||||
return handler.handle(req);
|
||||
}
|
||||
}
|
||||
</docs-code>
|
||||
|
||||
@@ -4,12 +4,14 @@ Before you can use `HttpClient` in your app, you must configure it using [depend
|
||||
|
||||
## Providing `HttpClient` through dependency injection
|
||||
|
||||
`HttpClient` is provided using the `provideHttpClient` helper function, which most apps include in the application `providers` in `main.ts`.
|
||||
`HttpClient` is provided using the `provideHttpClient` helper function, which most apps include in the application `providers` in `app.config.ts`.
|
||||
|
||||
<docs-code language="ts">
|
||||
bootstrapApplication(App, {providers: [
|
||||
provideHttpClient(),
|
||||
]});
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
provideHttpClient(),
|
||||
]
|
||||
};
|
||||
</docs-code>
|
||||
|
||||
If your app is using NgModule-based bootstrap instead, you can include `provideHttpClient` in the providers of your app's NgModule:
|
||||
|
||||
@@ -39,38 +39,6 @@ Additionally, these providers are also available to all the classes in the appli
|
||||
|
||||
You should always provide your service in the root injector unless there is a case where you want the service to be available only if the consumer imports a particular `@NgModule`.
|
||||
|
||||
## `providedIn` and NgModules
|
||||
|
||||
It's also possible to specify that a service should be provided in a particular `@NgModule`.
|
||||
For example, if you don't want `UserService` to be available to applications unless they import a `UserModule` you've created, you can specify that the service should be provided in the module:
|
||||
|
||||
<docs-code header="src/app/user.service.ts" highlight="[5]">
|
||||
import { Injectable } from '@angular/core';
|
||||
import { UserModule } from './user.module';
|
||||
|
||||
@Injectable({
|
||||
providedIn: UserModule,
|
||||
})
|
||||
export class UserService {
|
||||
}
|
||||
</docs-code>
|
||||
|
||||
The example above shows the **preferred** way to provide a service in a module.
|
||||
This method is preferred because it enables tree-shaking of the service if nothing injects it.
|
||||
|
||||
If it's not possible to specify in the service which module should provide it, you can also declare a provider for the service within the module:
|
||||
|
||||
<docs-code header="src/app/user.module.ts" highlight="[5]">
|
||||
import { NgModule } from '@angular/core';
|
||||
import { UserService } from './user.service';
|
||||
|
||||
@NgModule({
|
||||
providers: [UserService],
|
||||
})
|
||||
export class UserModule {
|
||||
}
|
||||
</docs-code>
|
||||
|
||||
## Limiting provider scope by lazy loading modules
|
||||
|
||||
In the basic CLI-generated app, modules are eagerly loaded which means that they are all loaded when the application launches.
|
||||
|
||||
@@ -58,7 +58,7 @@ The tabs for the example show the following:
|
||||
| Files | Details |
|
||||
|:--- |:--- |
|
||||
| flying-heroes.component.html | Template with the new pipe used. |
|
||||
| flying-heroes.pipe.ts | File with custom pipe that filters flying heros. |
|
||||
| flying-heroes.pipe.ts | File with custom pipe that filters flying heroes. |
|
||||
|
||||
<docs-code-multifile path="adev/src/content/examples/pipes/src/app/flying-heroes.component.ts_FlyingHeroesComponent" preview>
|
||||
<docs-code header="src/app/flying-heroes.component.html" path="adev/src/content/examples/pipes/src/app/flying-heroes.component.html" visibleRegion="template-flying-heroes"/>
|
||||
|
||||
@@ -443,7 +443,7 @@ gotoItems(hero: Hero) {
|
||||
You can configure your routes to lazy load modules, which means that Angular only loads modules as needed, rather than loading all modules when the application launches.
|
||||
Additionally, preload parts of your application in the background to improve the user experience.
|
||||
|
||||
For more information on lazy loading and preloading see the dedicated guide lazy loading.
|
||||
For more information on lazy loading and preloading see the dedicated guide [Lazy loading](guide/ngmodules/lazy-loading).
|
||||
|
||||
## Preventing unauthorized access
|
||||
|
||||
|
||||
@@ -271,5 +271,5 @@ For more information about routing, see the following topics:
|
||||
|
||||
<docs-pill-row>
|
||||
<docs-pill href="guide/routing/common-router-tasks" title="In-app Routing and Navigation"/>
|
||||
<docs-pill href="api/router" title="Router API"/>
|
||||
<docs-pill href="api/router/Router" title="Router API"/>
|
||||
</docs-pill-row>
|
||||
|
||||
@@ -110,7 +110,7 @@ To learn more about the Angular Router, see the following topics:
|
||||
|
||||
<docs-pill-row>
|
||||
<docs-pill href="guide/routing/common-router-tasks" title="In-app Routing and Navigation"/>
|
||||
<docs-pill href="api/router" title="Router API"/>
|
||||
<docs-pill href="api/router/Router" title="Router API"/>
|
||||
</docs-pill-row>
|
||||
|
||||
HELPFUL: This content is based on [Custom Route Matching with the Angular Router](https://medium.com/@brandontroberts/custom-route-matching-with-the-angular-router-fbdd48665483), by [Brandon Roberts](https://twitter.com/brandontroberts).
|
||||
|
||||
@@ -35,13 +35,13 @@ You can bind to keyboard events using Angular's binding syntax. You can specify
|
||||
|
||||
Combinations of keys can be separated by a `.` (period). For example, `keydown.enter` will allow you to bind events to the `enter` key. You can also use modifier keys, such as `shift`, `alt`, `control`, and the `command` keys from Mac. The following example shows how to bind a keyboard event to `keydown.shift.t`.
|
||||
|
||||
```typescript
|
||||
```html
|
||||
<input (keydown.shift.t)="onKeydown($event)" />
|
||||
```
|
||||
|
||||
Depending on the operating system, some key combinations might create special characters instead of the key combination that you expect. MacOS, for example, creates special characters when you use the option and shift keys together. If you bind to `keydown.shift.alt.t`, on macOS, that combination produces a `ˇ` character instead of a `t`, which doesn't match the binding and won't trigger your event handler. To bind to `keydown.shift.alt.t` on macOS, use the `code` keyboard event field to get the correct behavior, such as `keydown.code.shiftleft.altleft.keyt` shown in this example.
|
||||
|
||||
```typescript
|
||||
```html
|
||||
<input (keydown.code.shiftleft.altleft.keyt)="onKeydown($event)" />
|
||||
```
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ The template syntax guides show you how to control the UX/UI by coordinating dat
|
||||
|
||||
## Empower your HTML
|
||||
|
||||
Extend the HTML vocabulary of your applications With special Angular syntax in your templates.
|
||||
Extend the HTML vocabulary of your applications with special Angular syntax in your templates.
|
||||
For example, Angular helps you get and set DOM \(Document Object Model\) values dynamically with features such as built-in template functions, variables, event listening, and data binding.
|
||||
|
||||
Almost all HTML syntax is valid template syntax.
|
||||
|
||||
@@ -230,7 +230,7 @@ The following example re-implements the previous test with `DebugElement.query()
|
||||
|
||||
Some noteworthy observations:
|
||||
|
||||
* The `By.css()` static method selects `DebugElement` nodes with a [standard CSS selector](https://developer.mozilla.org/docs/Web/Guide/CSS/Getting_started/Selectors 'CSS selectors').
|
||||
* The `By.css()` static method selects `DebugElement` nodes with a [standard CSS selector](https://developer.mozilla.org/docs/Learn/CSS/Building_blocks/Selectors 'CSS selectors').
|
||||
* The query returns a `DebugElement` for the paragraph.
|
||||
* You must unwrap that result to get the paragraph element.
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ Other common examples of event listeners include:
|
||||
|
||||
### $event
|
||||
|
||||
If you need to access the [event](https://developer.mozilla.org/en-US/docs/Web/API/Event) object, Angular provides an implicit `$event` variable that you can be pass to a function:
|
||||
If you need to access the [event](https://developer.mozilla.org/en-US/docs/Web/API/Event) object, Angular provides an implicit `$event` variable that you can pass to a function:
|
||||
|
||||
```html
|
||||
<button (click)="createUser($event)">Submit</button>
|
||||
|
||||
@@ -7,7 +7,7 @@ As a design system, this page contains visual and Markdown authoring guidance fo
|
||||
* Custom Angular docs elements: [`docs-card`](#cards), [`docs-callout`](#callouts), [`docs-pill`](#pills), and [`docs-steps`](#workflow)
|
||||
* Custom text elements: [alerts](#alerts)
|
||||
* Code examples: [`docs-code`](#code)
|
||||
* Built-in Markdown styled elements: links, lists, [headers](#headers), [horizonal lines](#horizontal-line-divider), [tables](#tables)
|
||||
* Built-in Markdown styled elements: links, lists, [headers](#headers), [horizontal lines](#horizontal-line-divider), [tables](#tables)
|
||||
* and more!
|
||||
|
||||
Get ready to:
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# Migration to Control Flow syntax
|
||||
|
||||
|
||||
[Control flow syntax](guide/templates/control-flow) is available from Angular 17 and simplified way to use the control-flow directives like *ngFor, *ngIf and *ngSwitch.
|
||||
|
||||
The new syntax is baked into the template, so you don't need to import `CommonModule` anymore. But wait there is more to it, there is an migration availble for migrating all your old code to use new Control Flow Syntax with Angular 17 release. Run the schematic with the following command:
|
||||
|
||||
<docs-code language="shell">
|
||||
|
||||
ng generate @angular/core:control-flow
|
||||
|
||||
</docs-code>
|
||||
@@ -18,4 +18,7 @@ Learn about how you can migrate your existing angular project to the latest feat
|
||||
|
||||
Strictly typed reactive forms add type safety and the types enable a variety of other improvements, such as better autocomplete in IDEs, and an explicit way to specify form structure.
|
||||
</docs-card>
|
||||
<docs-card title="Control Flow Syntax" link="Migrate now" href="reference/migrations/control-flow">
|
||||
Control Flow Syntax is available with Angular 17 release and allows you to use more ergonomic syntax which is close to javascript, better type checking and lazy load part of the component. It replaces the need to imports CommonModule to use functionalities like *ngFor,`*ngIf.
|
||||
</docs-card>
|
||||
</docs-card-container>
|
||||
|
||||
@@ -4,8 +4,8 @@ The logo graphics available for download on this page are provided under [CC BY
|
||||
|
||||
<docs-card-container>
|
||||
<docs-card title="Angular logos" href="https://drive.google.com/drive/folders/1IgcAwLDVZUz8ycnFa7T4_H6B4V4LhYUQ?usp=sharing" link="Download from Google Drive">
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
Black and white are the default color variations and should be used in most circumstances. A gradient version of the icon and lockup is available in both static and animated formats and can be used in cases where a color icon is required.
|
||||
</docs-card>
|
||||
|
||||
@@ -109,7 +109,7 @@ As a general rule, a fix is considered for an LTS version if it resolves one of:
|
||||
|
||||
## Deprecation policy
|
||||
|
||||
When the Angular team intends to remove an API or feature, it will be marked as *deprecated*. This occurs when when an API is obsolete, superseded by another API, or otherwise discontinued. Deprecated API remain available through their deprecated phase, which lasts a minimum two major versions (approximately one year).
|
||||
When the Angular team intends to remove an API or feature, it will be marked as *deprecated*. This occurs when an API is obsolete, superseded by another API, or otherwise discontinued. Deprecated API remain available through their deprecated phase, which lasts a minimum two major versions (approximately one year).
|
||||
|
||||
To help ensure that you have sufficient time and a clear path to update, this is our deprecation policy:
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ You can read more by following the links associated with the package names below
|
||||
| [Vercel](https://vercel.com/solutions/angular) | [`vercel init angular`](https://github.com/vercel/vercel/tree/main/examples/angular) |
|
||||
| [Netlify](https://www.netlify.com) | [`ng add @netlify-builder/deploy`](https://npmjs.org/package/@netlify-builder/deploy) |
|
||||
| [GitHub pages](https://pages.github.com) | [`ng add angular-cli-ghpages`](https://npmjs.org/package/angular-cli-ghpages) |
|
||||
| [NPM](https://npmjs.com) | [`ng add ngx-deploy-npm`](https://npmjs.org/package/ngx-deploy-npm) |
|
||||
| [Amazon Cloud S3](https://aws.amazon.com/s3/?nc2=h_ql_prod_st_s3) | [`ng add @jefiozie/ngx-aws-deploy`](https://www.npmjs.com/package/@jefiozie/ngx-aws-deploy) |
|
||||
|
||||
If you're deploying to a self-managed server or there's no builder for your favorite cloud platform, you can either [create a builder](tools/cli/cli-builder) that allows you to use the `ng deploy` command, or read through this guide to learn how to manually deploy your application.
|
||||
|
||||
@@ -169,10 +169,6 @@ To add a staging environment, create a copy of `src/environments/environment.ts`
|
||||
"production": { … },
|
||||
"staging": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.development.ts"
|
||||
},
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.staging.ts"
|
||||
|
||||
@@ -129,7 +129,7 @@ When you select a bar, DevTools displays useful information about it including:
|
||||
|
||||
### Understand component execution
|
||||
|
||||
The bar chat displayed after clicking on a change detection cycle displays a detailed view about how much time your application spent running change detection in that particular component or directive.
|
||||
The bar chart displayed after clicking on a change detection cycle displays a detailed view about how much time your application spent running change detection in that particular component or directive.
|
||||
|
||||
This example shows the total time spent by the `NgForOf` directive and which method was called on it.
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ It works with external templates in separate HTML files, and also with in-line t
|
||||
|
||||
## Configuring compiler options for the Angular Language Service
|
||||
|
||||
To enable the latest Language Service features, set the `strictTemplates` option in `tsconfig.json` by setting `strictTemplates` to `true,` as shown in the following example:
|
||||
To enable the latest Language Service features, set the `strictTemplates` option in `tsconfig.json` by setting `strictTemplates` to `true`, as shown in the following example:
|
||||
|
||||
<docs-code language="json">
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ In the **Edit** pane of your IDE:
|
||||
<docs-step title="Add the styles for the component">
|
||||
In this step, you will copy over the pre-written styles for the `HousingLocationComponent` to your app so that the app renders properly.
|
||||
|
||||
1. Open `src/app/housing-location/housing-location.css`, and paste the styles below into the file:
|
||||
1. Open `src/app/housing-location/housing-location.component.css`, and paste the styles below into the file:
|
||||
|
||||
Note: In the browser, these can go in `src/app/housing-location/housing-location.component.ts` in the `styles` array.
|
||||
|
||||
|
||||
@@ -47,5 +47,6 @@ In the code editor:
|
||||
Summary: In this lesson, you created a new property decorated with the `@Input()` decorator. You also used the non-null assertion operator to notify the compiler that the value of the new property won't be `null` or `undefined`.
|
||||
|
||||
<docs-pill-row>
|
||||
<docs-pill href="guide/components/inputs-outputs" title="Sharing data between child and parent directives and components"/>
|
||||
<docs-pill href="guide/components/inputs" title="Accepting data with input properties"/>
|
||||
<docs-pill href="guide/components/outputs" title="Custom events with outputs"/>
|
||||
</docs-pill-row>
|
||||
|
||||
@@ -16,7 +16,7 @@ In this example, there are two components `UserComponent` and `AppComponent`.
|
||||
Update the `AppComponent` template to include a reference to the `UserComponent` which uses the selector `app-user`. Be sure to add `UserComponent` to the imports array of `AppComponent`, this makes it available for use in the `AppComponent` template.
|
||||
|
||||
```ts
|
||||
template: `<app-user>`,
|
||||
template: `<app-user />`,
|
||||
imports: [UserComponent]
|
||||
```
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- We set all theme clases to allow critters to inline the theme styles and prevent flickering -->
|
||||
<!-- We set all theme classes to allow critters to inline the theme styles and prevent flickering -->
|
||||
<html lang="en" class="adev-dark-mode adev-light-mode">
|
||||
<head>
|
||||
<script>
|
||||
|
||||
@@ -14,7 +14,7 @@ A type of [block](api/core/defer) that can be used to defer load the JavaScript
|
||||
<img alt="loading image" src="loading.gif" />
|
||||
} @error {
|
||||
<!-- error template fragment -->
|
||||
<p>An loading error occured</p>
|
||||
<p>An loading error occurred</p>
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Architect } from '@angular-devkit/architect';
|
||||
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
|
||||
import { schema } from '@angular-devkit/core';
|
||||
import { promises as fs } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
describe('Copy File Builder', () => {
|
||||
let architect: Architect;
|
||||
@@ -19,7 +20,7 @@ describe('Copy File Builder', () => {
|
||||
|
||||
// This will either take a Node package name, or a path to the directory
|
||||
// for the package.json file.
|
||||
await architectHost.addBuilderFromPackage('..');
|
||||
await architectHost.addBuilderFromPackage(join(__dirname, '..'));
|
||||
});
|
||||
|
||||
it('can copy files', async () => {
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// #docplaster
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
// #docregion standalonedeclaration
|
||||
@Component({
|
||||
selector: 'app-component-overview',
|
||||
template: '<h1>Hello World!</h1>',
|
||||
styles: ['h1 { font-weight: normal; }'],
|
||||
standalone: true
|
||||
})
|
||||
// #enddocregion standalonedeclaration
|
||||
|
||||
export class ComponentOverviewComponent {
|
||||
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// #docplaster
|
||||
import {NgModule} from '@angular/core';
|
||||
// #docregion componentmoduledeclaration
|
||||
// Your component path
|
||||
import {ComponentOverviewComponent} from './component-overview.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
// Existing Components
|
||||
ComponentOverviewComponent
|
||||
]
|
||||
// Rest of the Module Content
|
||||
})
|
||||
// #enddocregion componentmoduledeclaration
|
||||
export class ComponentOverviewModule {}
|
||||
@@ -1,13 +0,0 @@
|
||||
// #docregion
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HeroModule } from './hero.module';
|
||||
import { HEROES } from './mock-heroes';
|
||||
|
||||
@Injectable({
|
||||
// we declare that this service should be created
|
||||
// by any injector that includes HeroModule.
|
||||
providedIn: HeroModule,
|
||||
})
|
||||
export class HeroService {
|
||||
getHeroes() { return HEROES; }
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AppPage } from './app.po';
|
||||
|
||||
describe('forms-overvoew App', () => {
|
||||
describe('forms-overview App', () => {
|
||||
let page: AppPage;
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user