Compare commits

...

158 Commits

Author SHA1 Message Date
Jessica Janiuk 57cb448de5 release: cut the v17.1.2 release 2024-01-31 11:04:26 -08:00
Ivan Zlatanov 0bd668c943 refactor(router): RouterLink read urlTree only once (#53817)
In RouterLink, urlTree is created every time we access it, so when used we should read it only once.

PR Close #53817
2024-01-31 17:37:12 +00:00
Angular Robot 2c0bb7fb0e build: update actions/cache digest to e12d46a (#54176)
See associated pull request for more information.

PR Close #54176
2024-01-31 17:36:28 +00:00
Angular Robot 735cdf3761 build: update actions/checkout digest to f43a0e5 (#54177)
See associated pull request for more information.

PR Close #54177
2024-01-31 17:36:00 +00:00
Angular Robot 948fb5f937 build: update slackapi/slack-github-action digest to 2a8087d (#52000)
See associated pull request for more information.

PR Close #52000
2024-01-31 16:47:32 +00:00
narendherraj 9f1a5fa5da docs: fix link missing to lazy loading module (#54113)
author narendherraj <narendherraj@gmail.com> 1706354106 +0530
committer narendherraj <narendherraj@gmail.com> 1706718969 +0530

docs: fix link missing to lazy loading module

docs: fix link missing to lazy loading module

docs: fix link missing lazy loading module updated

PR Close #54113
2024-01-31 16:45:51 +00:00
Angular Robot cab06bd125 build: update io_bazel_rules_sass digest to d970cb5 (#52388)
See associated pull request for more information.

PR Close #52388
2024-01-31 16:45:07 +00:00
Matthieu Riegler cdc5e39532 fix(common): The date pipe should return ISO format for week and week-year as intended in the unit test. (#53879)
ISO 8601 defines
* Monday as the first day of the week.
* week 01 is the week with the first Thursday

Therefore:
Sunday Dec 31st 2023 is the last day of the last week of the year : W52 2023.

PR Close #53879
2024-01-31 16:41:10 +00:00
Alejandro ed8e7c727b docs(docs-infra): add tab titles to home, playground and tutorial (#53026)
PR Close #53026
2024-01-31 16:30:49 +00:00
Paweł Kubiak e08cc50f3c test(docs-infra): unit tests in the reference pages (#53529)
Implementation of additional unit tests for `Reference` pages in `adev`.

PR Close #53529
2024-01-31 16:13:31 +00:00
Jared Bada ca7456e722 docs(docs-infra): @input getter setter syntax change (#51023)
PR Close #51023
2024-01-31 16:04:04 +00:00
kabrunko-dev b353ad5bac fix(docs-infra): sort api reference items (#54116)
Sort correctly items from angular.dev api reference secondary navigation menu

PR Close #54116
2024-01-31 15:44:23 +00:00
Elias bd6d18b977 docs: Fix minor grammar mistake (#54094)
PR Close #54094
2024-01-31 15:34:27 +00:00
vatsa03 3b218a72ce docs(core): fix example sections (#54121)
PR Close #54121
2024-01-31 15:22:30 +00:00
Matthieu Riegler 4367c44f7f docs: Update docs about equality. (#54158)
Since v17, `ngSwitch` uses a strict equality.

Fixes #54156

PR Close #54158
2024-01-31 15:07:52 +00:00
arturovt b69bf37841 fix(zone.js): patch Response methods returned by fetch (#50653)
This commit updates the implementation of the `fetch` patch and additionally
patches `Response` methods which return promises. These are `arrayBuffer`, `blob`,
`formData`, `json` and `text`. This fixes the issue when zone becomes stable too early
before all of the `fetch` tasks complete. Given the following code:
```ts
appRef.isStable.subscribe(console.log);
fetch(...).then(response => response.json()).then(console.log);
```
The `isStable` observer would log `false, true, false, true`. This was happening because
`json()` was returning a native promise (and not a `ZoneAwarePromise`). But calling `then`
on the native promise returns a `ZoneAwarePromise` which notifies Angular about the task
being scheduled and forces to re-calculate the `isStable` state.

Issue: #50327

PR Close #50653
2024-01-31 14:57:26 +00:00
arturovt 05a05b628b fix(zone.js): add __Zone_ignore_on_properties to ZoneGlobalConfigurations (#50737)
This commit updates the signature of the `ZoneGlobalConfigurations` interface and adds
missing `__Zone_ignore_on_properties` property, which may be setup to ignore specific `on`
properties from being patched.

PR Close #50737
2024-01-31 14:56:57 +00:00
Matthieu Riegler c21f41d6d4 refactor(router): remove duplicate helper methods (#53762)
`isNavigationCancelingError` & `isRedirectingNavigationCancelingError` had duplicate implementations. This commit also cleans-up those functions.

PR Close #53762
2024-01-31 14:56:25 +00:00
Matthieu Riegler 413db303f4 refactor(forms): Provide RadioControlRegistry in root. (#54130)
The `RadioControlRegistry` was only provided in a module, providedIn: 'root' fixes that issue.

Fixes #54117

Co-authored-by: sr5434 <118690585+sr5434@users.noreply.github.com>

PR Close #54130
2024-01-31 14:55:57 +00:00
ahmadhakeem18 752ebd62c9 docs: focus on the respective card of the current active line while scrolling (#53733)
make the active cards have the focus while scrolling like their
respective lines in the scroll service

PR Close #53733
2024-01-30 21:27:55 +00:00
Joey Perrott 7001b5d633 refactor: migrate docs, examples, private, service worker and upgrade to prettier formatting (#54163)
Migrate formatting to prettier for docs, examples, private, service worker and upgrade from clang-format

PR Close #54163
2024-01-30 20:08:40 +00:00
Matthieu Riegler fccf375df1 refactor(devtools): Add hydration informations (#53910)
This commit adds hydration informations to the devtools.
* List of hydrated/hydrated components
* Shows hydration overlays
* Shows hydration errors for NG0500, 501 & 502

PR Close #53910
2024-01-30 20:03:15 +00:00
Mahdi Lazraq 8d85de7fe1 docs: fix path to housing location css file in lesson 03 (#54106)
PR Close #54106
2024-01-30 17:50:12 +00:00
Joey Perrott 4c2b0d94e2 refactor: migrate common to prettier formatting (#54159)
Migrate formatting to prettier for common from clang-format

PR Close #54159
2024-01-30 16:08:40 +00:00
kabrunko-dev 57174bb60b refactor(common): simplify i18n plural and select pipe metadata (#53939)
Remove pure property from pipe decorator

PR Close #53939
2024-01-30 15:06:25 +00:00
kabrunko-dev 7a4a5253ea refactor(common): simplify date pipe metadata (#53939)
Remove pure property from date pipe decorator

PR Close #53939
2024-01-30 15:06:25 +00:00
Andrew Scott c5a0e909ac refactor(core): Update ComponentFixture behavior when using zoneless scheduler (#54024)
When the zoneless scheduler is provided, we want to update the behavior
of `ComponentFixture` to address common issues and painpoints in testing.
Developers should never have to call `detectChanges` on a fixture
manually. Instead of calling `detectChanges` after performing an
action that updates state and requies a template refresh, developers
should wait for change detection to run because the update needs to also have
notified the scheduler. If this was not the case, the component would
not work correctly in the application. Calling `detectChanges` to force
an update could hide real bugs.

This commit also updates the zoneless tests to uses `ComponentFixture`
instead of manually attaching to the `ApplicationRef` and rewriting a
lot of the helpers (`getDebugNode`, `isStable` as a value, `whenStable` as a
Promise).

PR Close #54024
2024-01-29 20:21:48 +00:00
Mark Thompson d07ce6156e docs: Update component-overview.md (#52282)
Refined the text a bit
PR Close #52282
2024-01-29 19:30:59 +00:00
Renan Ferro e3b874b4fb docs: add new component imports documentation structure (#52282)
PR Close #52282
2024-01-29 19:30:59 +00:00
Jesse Zomer 1ac37f932f docs: fix shareReplay refcount default (#54145)
according to the official rxjs docs the refcount default is false. See https://rxjs.dev/api/operators/shareReplay

Co-authored-by: Andrew Scott <atscott01@gmail.com>

PR Close #54145
2024-01-29 19:30:34 +00:00
therealdennis08 8650f0dee2 docs: correct grammar error on start page (#53993)
Fixed grammatical error

PR Close #53993
2024-01-29 16:41:29 +00:00
Ido Strauss 030d77010d docs: update TypeScript version support details for Angular v15 and v16 (#54131)
Clarify the range of TypeScript versions supported in Angular v15 and v16 upgrade guides. The previous documentation's phrasing led to potential misunderstandings, as it suggested broader compatibility than actually supported. This change prevents errors by explicitly stating the maximum TypeScript version for each Angular version, ensuring developers have clear guidance during upgrades.

PR Close #54131
2024-01-29 15:57:01 +00:00
Swami 96ca49d145 docs: update input/output guide links (#54135)
PR Close #54135
2024-01-29 15:43:05 +00:00
Kristiyan Kostadinov 8264382a6b fix(migrations): error in standalone migration when non-array value is used as declarations in TestBed (#54122)
Adds some logic to skip over `TestBed.configureTestingModule` calls where the `declarations` aren't initialized to an array. We can't migrate these cases, because test migrations don't have access to the Angular compiler. Previously the migration would throw a runtime error.

PR Close #54122
2024-01-29 15:40:05 +00:00
Santosh Yadav f5a5215166 docs: add link for control flow migration (#53375)
PR Close #53375
2024-01-29 15:39:06 +00:00
Dwouglas Mhagnum 5cd00f167c InMemoryBackendConfigArgs.passThruUnknownUrl: fix tsdoc (#52273)
PR Close #52273
2024-01-26 20:39:38 +00:00
Matt Ezell 22f89c0a2d docs: Corrected link for defer related blocks (#52704)
PR Close #52704
2024-01-26 20:38:37 +00:00
Muhammad Ahsan Ayaz c442912532 docs(changelog): release notes, fix the typos etc (#52628)
fixed the typos in a few places
added a missing backtick
removed an unnecessary bullet point

PR Close #52628
2024-01-26 20:38:05 +00:00
Wojciech 9f9dd901ae docs: Update update-to-version-16.md (#51857)
Fix example for required inputs that leads to TS2564 error - property has no initializer

PR Close #51857
2024-01-26 19:13:24 +00:00
Matthieu Riegler 30e42df518 refactor(core): remove InjectionToken descriptions in optimized builds. (#53747)
We started guarding the `InjectionToken` descriptions with `ngDevMode`. Let's generalize that accross the FW.

PR Close #53747
2024-01-26 19:12:41 +00:00
Matthieu Riegler 566499af1d docs: remove mention of providedIn module. This feature has been deprecated. (#54072)
PR Close #54072
2024-01-26 19:09:28 +00:00
fhoekstra 4a5f37d216 docs(router): fix variable reference in text (#54099)
PR Close #54099
2024-01-26 19:02:42 +00:00
iliasaddab 74567f1c8a docs: update i18n-common-merge.md (#52400)
correct spelling

PR Close #52400
2024-01-26 17:38:09 +00:00
Matthieu Riegler 64399b26c0 docs: add 2 new diagnostics created recently. (#52329)
PR Close #52329
2024-01-26 17:28:01 +00:00
Matthieu Riegler 1b296dbb80 refactor(platform-browser): remove non necessary factories (#52439)
Let's keep the code a simple as necessary

PR Close #52439
2024-01-26 17:26:52 +00:00
Matthieu Riegler cddc426e18 refactor(platform-browser): remove the depency on window for the AngularProfiler. (#52440)
`performance` and `console` are both available on NodeJS, we can replace `window` with `globalThis`.

PR Close #52440
2024-01-26 17:24:40 +00:00
Matthieu Riegler 8109013b0f refactor(common): Use Nullish coalescing assignment when possible. (#53931)
Inspired by #53923, lets simplify code when possible.

PR Close #53931
2024-01-26 16:58:36 +00:00
Angular Robot f25d7e880f docs: update events (#53654)
Generated `events.json` with the latest events retrieved from the Firebase DB.

Closes #53229

PR Close #53654
2024-01-26 16:58:07 +00:00
Shuaib hasan akib f240c70971 docs(docs-infra): cleanup repeated scss from typography (#51579)
PR Close #51579
2024-01-26 16:03:43 +00:00
Sylvain DEDIEU 0172477ff2 docs(docs-infra): add if cases in templates to avoid internal marked parameters or methods to appear in the documentation (#52020)
Fix case of not wanted internal properties displayed in the documentation by adding if blocks in the concerned templates. So if the option is marked as internal the template won't create an entry in the documentation table for the concerned property of method

Fixes #52018

PR Close #52020
2024-01-26 15:47:16 +00:00
Chellappan 0702d4a560 refactor(forms): Specify Provider type for DEFAULT_VALUE_ACCESSOR (#54029)
Change from `any` to `Provider` type for enhanced type safety and clarity

PR Close #54029
2024-01-26 15:46:31 +00:00
Ezéchiel Amen AGBLA 798aee7a83 docs: remove link (#54090)
PR Close #54090
2024-01-26 15:46:01 +00:00
cexbrayat c477e876e3 fix(core): change defer block fixture default behavior to playthrough (#54088)
This is a followup to #53956

The default behavior needs to be changed in `TestBedCompiler` as well to have an effect.

PR Close #54088
2024-01-26 15:44:40 +00:00
Magda98 ecd0daf8fd docs(docs-infra): move comma in Angular Language Service section (#53759)
PR Close #53759
2024-01-25 23:48:57 +00:00
jivanf 6eca767811 docs: Use correct service name in hierarchical dependency injection guide (#53723)
This commit replaces `TitleService` with `TiresService` in the specialized providers scenario described in the guide.
PR Close #53723
2024-01-25 23:47:01 +00:00
Antoine PARIZE d8d6478d0e docs: testing-components-basics.md and components-basics.md links to css selector documentation are dead (#53586)
docs: testing-components-basics.md and components-basics.md links to css selector documentation are dead

As MDN's documentation link to the "css selector" topic is dead, this commit makes the angular documentation use the new valid link.

PR Close #53586
2024-01-25 23:34:03 +00:00
oliv37 0c4d7e061e docs: fix add builder from package (#53154)
PR Close #53154
2024-01-25 23:31:01 +00:00
pBouillon 293dc3b046 docs: fix reference to forwardRef in ForwardRefFn JSdoc (#53556)
PR Close #53556
2024-01-25 23:16:46 +00:00
lsst25 8dca5a11f5 docs(docs-infra): close tag in the example of Composing Components tutorial (#52923)
PR Close #52923
2024-01-25 23:04:47 +00:00
Ross MacPhee 45fca0bc95 docs: fix nonsensical injection provider docs (#53456)
PR Close #53456
2024-01-25 23:02:46 +00:00
nickolashkraus 85819b9cdb docs: With >>> with (#53472)
PR Close #53472
2024-01-25 22:58:34 +00:00
Srinath Vayalpati 87378a773d docs: fix router api url link (#53398)
PR Close #53398
2024-01-25 22:58:09 +00:00
Andrea Canciani 96dd0c715e refactor: fix a number of typos throughout the codebase (#52826)
Fix several typos, mostly in the `adev` site.

PR Close #52826
2024-01-25 22:55:00 +00:00
Sai Kumar Kola ccddacf11d fix: cta clickability issue in adev homepage. (#52905)
PR Close #52905
2024-01-25 22:48:47 +00:00
Aditya Kumar b216e76838 docs: Fix open link in new tab (#53647)
Signed-off-by: Aditya Kumar <aditya.kumar60@infosys.com>

PR Close #53647
2024-01-25 22:40:50 +00:00
louay.meskini 0d31904a96 docs: Fix links for NgZone (#53667)
PR Close #53667
2024-01-25 22:38:51 +00:00
jase aa3df2a7d4 docs: fix http handler usage on interceptor example (#53772)
PR Close #53772
2024-01-25 22:38:19 +00:00
Trung Vo 50b7901169 docs: add Trung Vo to GDE resources (#53599)
PR Close #53599
2024-01-25 22:29:26 +00:00
Aditya Kumar 1439f059a3 docs: Fix router api url link on tutorial page (#53416)
Signed-off-by: Aditya Kumar <aditya.kumar60@infosys.com>

PR Close #53416
2024-01-25 22:27:11 +00:00
Ezéchiel Amen AGBLA ac211d46b0 docs: bad redirection in core Injector page for providers and injection token links (#52775)
PR Close #52775
2024-01-25 21:34:35 +00:00
Gleb28 356984d9ba docs: removed repeated words "when" (#53828)
Fixes #53827

PR Close #53828
2024-01-25 21:31:33 +00:00
Sylvain DEDIEU 7ac94dd664 docs: change the file of the provideHttpClient standalone example to match cli generated project (#52806)
The "Providing HttpClient through dependency injection" documentation now shows that in case of a standalone boostraped app, the provideHttpClient is to include in the app.config.ts file.

Also updated the http setup server communication example to align the new doc (adev) with the old one (aio).

PR Close #52806
2024-01-25 21:24:59 +00:00
Sasidharan SD 49aff2726f docs: fix invalid file replacement configuration (#52802)
PR Close #52802
2024-01-25 21:22:44 +00:00
Aditya Kumar 6c14c9324f docs: Fix minor grammatical fixes in the documentations (#53418)
Signed-off-by: Aditya Kumar <aditya.kumar60@infosys.com>

PR Close #53418
2024-01-25 21:21:59 +00:00
Nelson Gutierrez c0c7216c5f docs: add correct language for syntax highlighting on new docs (#52712)
PR Close #52712
2024-01-25 21:19:29 +00:00
Nelson Gutierrez 25e4f04d9f docs: add correct syntax highlighting type in event binding documentation (#52712)
PR Close #52712
2024-01-25 21:19:29 +00:00
ilir.beqiri 259707e31c docs: fix type at change detection with pipes section (#53940)
Fix a typo of word 'heroes' at docs guide for change detection with pure pipes

PR Close #53940
2024-01-25 20:46:19 +00:00
Jessica Janiuk d17ba9bc87 ci: update adev approvers list (#54081)
This temporarily updates the adev approvers list before we decide how we will handle adev content reviews going forward.

PR Close #54081
2024-01-25 20:40:09 +00:00
Ben Hong a4923f1f17 ci: add ben to reviewers for adev files (#54078)
For ADEV changes going forward, Ben will be helping the team to review all PRs associated with this project.

PR Close #54078
2024-01-25 20:18:51 +00:00
vladboisa e603450592 docs: fix & update MDN Shadow API link examples (#54040)
PR Close #54040
2024-01-25 18:02:58 +00:00
Ben Hong c6861eefa4 docs: add documentation and script for local docs dev environment (#54038)
PR Close #54038
2024-01-25 18:02:28 +00:00
d-codez 910742389f docs: correct grammar in event handling documentation (#54009)
PR Close #54009
2024-01-25 18:01:51 +00:00
arturovt 98d545fafa fix(animations): cleanup DOM elements when root view is removed with async animations (#53033)
Currently, when using `provideAnimationsAsync`, Angular uses `AnimationRenderer`
as the renderer. When the root view is removed, the `AnimationRenderer` defers the actual
work to the `TransitionAnimationEngine` to do this, and the `TransitionAnimationEngine`
doesn't actually remove the DOM node, but just calls `markElementAsRemoved()`.

The actual DOM node is not removed until `TransitionAnimationEngine` "flushes".

Unfortunately, though, that "flush" will never happen, since the root view is being
destroyed and there will be no more flushes.

This commit adds `flush()` call when the root view is being destroyed.

PR Close #53033
2024-01-25 16:32:57 +00:00
Kristiyan Kostadinov 7786e35faa refactor(compiler): distinguish two-way bindings in the AST (#54065)
During the template parsing stage two-way bindings are split up into a property and event binding. All the downstream code treats these binding the same as their one-way equivalents. For some future work we'll have to distinguish between the two so these changes update the `BoundElementProperty.type` and `ParsedEvent.type` to include a `TwoWay` type. All existing call-sites have been updated to treat `TwoWay` the same as `Property`/`Regular`, but more specialized logic will be added in the future.

PR Close #54065
2024-01-25 16:31:57 +00:00
Dylan Hunn 49101330f8 refactor(compiler): Fix defer deps fn duplicate names in Template Pipeline (#54060)
Previously, defer deps fns names were only prefixed with the component name, meaning that distinct deps fns in the same component would produce a name collision. Now, we take into account the entire template function name when naming inner deps fns.

PR Close #54060
2024-01-25 16:31:01 +00:00
Diego Julião 4507704a7e docs: remove ngx-deploy-npm from deployers table (#53999)
PR Close #53999
2024-01-25 16:07:40 +00:00
Andrew Scott 854b839531 refactor(core): race rAF and setTimeout in zoneless scheduler (#54023)
Update zoneless scheduler to run change detection after the first of
either `requestAnimationFrame` or `setTimeout` callbacks execute.

PR Close #54023
2024-01-24 18:39:15 -05:00
Jan Olaf Krems 89f7b00e59 refactor(core): Allow mutation instead of reassignment of ngDevMode (#53862)
In some bundling scenarios, there may be local references to `ngDevMode` that need to be kept in sync with the global variable. This becomes hard to impossible if the global is reassigned. This allows setting the global to an empty object instead of `true` and preserve identity during `initNgDevMode`.
PR Close #53862
2024-01-24 18:38:51 -05:00
Andrew Scott f12b01ec88 fix(compiler): Update type check block to fix control flow source mappings (#53980)
The source mappings and types for various pieces of the control flow
were not quite right and prevented the language service from providing
accurate information.

fixes https://github.com/angular/vscode-ng-language-service/issues/1988

PR Close #53980
2024-01-24 18:37:58 -05:00
Dylan Hunn 0c8aaf082e refactor(compiler): Support externally provided defer deps fns (#54043)
In #53591, Andrew added local compliation support for defer blocks. However, this requires the ability to emit pre-generated static defer deps functions. We now also support that feature in Template Pipeline.

PR Close #54043
2024-01-24 18:35:24 -05:00
nikvarma a4f024fb07 docs: typo Chat to chart fix (#53892)
PR Close #53892
2024-01-24 21:23:52 +01:00
Pawel Kozlowski e2e0f08d99 release: cut the v17.1.1 release 2024-01-24 19:31:20 +01:00
Max e194fbfbaa docs: fix typo in Custom directives section (#54044)
There was a grammatically incorrect sentence in the What is Angular page, Custom directives section. This change makes it more correct.
PR Close #54044
2024-01-24 15:32:22 +01:00
Paul Gschwendtner 8ad1ee764b build: ensure zone.js typing test is hermetic (#54048)
Currently the ZoneJS typing tests executes outside of Bazel, as a legacy
artifact of the monorepo merging (as it seems - not ideal at all).

Looks like this test relies on its own node modules, that were NOT
locked using a yarn lock file. This commit adds one, and specifically
locks it to a `@types/node` version that does not include the most
recent patch release (which seemingly introduced a breaking change)
that causes issues with TypeScript's lib checking.

Whenever we perform lock file maintenance in the future, we have the
following options:

- Consider disabling lib checking via `skipLibCheck` for this test. This
  may be acceptable.
- Continue locking the node version,
- Waiting for chokidar to comply with the new signature
- Waiting for the breaking change to be rolled back.

Culprit change:
https://github.com/DefinitelyTyped/DefinitelyTyped/pull/68300

PR Close #54048
2024-01-24 14:57:05 +01:00
Andrew Scott f222bee8fa fix(router): revert commit that replaced last helper with native Array.at(-1) (#54021)
While `Array.at` is technically supported in all browsers we officially
support, the change was needlessly breaking without any real benefit.

PR Close #54021
2024-01-24 10:54:55 +01:00
Alan Agius 9a9a00e0f9 docs: update docs to reflect changes in Angular CLI version 17.1 (#53949)
This changes include mentioning the experimental application builder migration and changes to the `outputPath` and `optimization` option.

PR Close #53949
2024-01-23 18:56:19 +01:00
Younes Jaaidi 5f9cac037b test(core): fix test with false-negative risk (#54025)
change assertion to handle the case where the function doesn't throw

PR Close #54025
2024-01-23 16:58:57 +01:00
Dylan Hunn 9778326f10 refactor(compiler): ICUs should roll up to the root i18n block for application (#54026)
Previously, if an ICU was inside a nested i18n root, it would use the nested root to calculate whether it should be applied. Now, we use the root i18n block.

PR Close #54026
2024-01-23 15:09:37 +01:00
Aristeidis Bampakos fac5a7cf4e docs: update Aristeidis Bampakos bio (#51779)
PR Close #51779
2024-01-23 10:22:23 +01:00
Matthieu Riegler ae145d19c6 refactor(devtools): migrate to standalone (#53998)
Migrated with the schematics and cleanup by hand.

PR Close #53998
2024-01-23 09:53:24 +01:00
Matthieu Riegler 30b6d34a49 refactor(devtools): remove date utility. (#53997)
We can use the `toIsoString()` function instead !

PR Close #53997
2024-01-23 09:52:14 +01:00
Srinath Vayalpati 3e0b7c1bdc docs: fixed req.method in http client testing (#53395)
PR Close #53395
2024-01-23 09:51:00 +01:00
ilir.beqiri a58a35dfe4 docs: fix typo at component template metadata property (#54015)
Rename the component metadata property, templateUrl to template in the reactive forms tutorial step

PR Close #54015
2024-01-23 09:47:43 +01:00
Matthieu Riegler a7c9fbb087 docs: update version compatibility table for aio & adev (#54008)
PR Close #54008
2024-01-23 09:46:57 +01:00
divyasudagoni 20811aad27 docs: move import statement of ngmodule from standalone component to module code #53952 (#54016)
PR Close #54016
2024-01-22 19:43:37 +01:00
Joey Perrott df453c3549 refactor: migrate bazel, benchpress, elements and misc to prettier formatting (#53995)
Migrate formatting to prettier for bazel, benchpress, elements and misc from clang-format

PR Close #53995
2024-01-22 09:07:16 +01:00
Joey Perrott 1f6c96a1dc refactor: migrate animations to prettier formatting (#53977)
Migrate formatting to prettier for animations from clang-format

PR Close #53977
2024-01-19 20:08:58 +01:00
Joey Perrott 656549d88a refactor(devtools): migrate devtools to prettier formatting (#53945)
Migrate formatting to prettier for devtools from clang-format

PR Close #53945
2024-01-19 19:09:54 +01:00
Tomasz Ducin c0f0baac58 refactor(devtools): improving type safety (#53436)
This PR reduces the number of unnecessary `any` occurrences in devtools packages.

PR Close #53436
2024-01-19 17:35:26 +01:00
Paul d38aa4f103 docs: update start-data.md (#52577)
PR Close #52577
2024-01-19 17:34:45 +01:00
Matthieu Riegler 7397b6648a build: Adding myself for devtools approval (#53989)
This to help Alex with the reviewing of devtools PRs.

PR Close #53989
2024-01-19 17:33:21 +01:00
Paul Gschwendtner 0fe9331958 build: update g3 sync config to match internal one (#53987)
There were some changes to the Copybara config that should
be reflected here as well.

PR Close #53987
2024-01-19 17:18:11 +01:00
Andrew Scott 7620f506c0 refactor(core): node removal notifies scheduler only when animations are enabled (#53857)
Node removal is immediate and does not require change detection to run
when animations are not provided. This refactor makes the animation
engine notify the scheduler rather than doing it on all node removals.

PR Close #53857
2024-01-19 10:28:25 +01:00
Joey Perrott 62ad2f0c71 refactor: migrate scripts to prettier formatting (#53976)
Migrate formatting to prettier for scripts from clang-format

PR Close #53976
2024-01-19 10:22:07 +01:00
Jessica Janiuk 424a26b3c7 docs: updates defer guide to reflect updated default defer block test behavior (#53975)
This updates the deferrable view guide to specify playthrough as the default with examples of configuring to manual.

PR Close #53975
2024-01-19 10:16:36 +01:00
Joey Perrott 18bd1a5ccb build: update version of @angular/docs (#53974)
Update docs to later version

PR Close #53974
2024-01-18 18:49:58 +01:00
Joey Perrott 8922a11693 ci: provide proper location for artifacts to allow for firebase to find the artifacts for deployment (#53960)
Move the artifacts during deployment into adev/ so that its at the same level as the firebase.json file.

PR Close #53960
2024-01-18 18:08:30 +01:00
Ankita Sood 4e0341050b docs: add ankita (#52319)
add Ankita as GDE in contributors.json

PR Close #52319
2024-01-18 14:28:35 +01:00
lilbeqiri 0616dc2839 build(devtools): prevent underscores from being added at build time (#53921)
Add the keepNames config property to esbuild in order to prevent prepending of underscores to the class names.

PR Close #53921
2024-01-18 10:22:13 +01:00
Sasidharan SD dc228c6fc1 docs: fix broken code example (#53531)
PR Close #53531
2024-01-18 10:16:20 +01:00
Sasidharan SD b1a7249c24 docs: fix spelling errors in tutorials steps (#53840)
PR Close #53840
2024-01-18 10:14:48 +01:00
Matthieu Riegler 9ff4893bc0 refactor(devtools): Add support for signals. (#53269)
The devtools now support signals.
Writable signals of primitives are editable.
Object Signal and other non-writable signals (like computed) are not editable.

Co-authored-by: Tomasz Ducin <tomasz.ducin@gmail.com>

PR Close #53269
2024-01-17 16:47:17 -08:00
Matthieu Riegler 025f7af694 refactor(compiler): remove mentions of unused compiler options. (#53746)
Those options where removed in #49672.

PR Close #53746
2024-01-17 16:41:35 -08:00
macvag 1c4a99a6d1 docs: fix broken hyperlink in tutorials first app search (#53816)
PR Close #53816
2024-01-17 16:40:06 -08:00
Dylan Hunn 51d53fc728 release: cut the v17.1.0 release 2024-01-17 14:45:22 -08:00
Dylan Hunn be882c3efb Revert "refactor(core): improve forwardRef typings (#53880)"
This reverts commit af6f6e6448.
2024-01-17 13:57:11 -08:00
cexbrayat 18fa6d7556 refactor(compiler-cli): interpolatedSignalNotInvoked diagnostic for input signals (#53883)
This updates the extended diagnotic to handle input signals as well.

PR Close #53883
2024-01-17 11:36:43 -08:00
Matthieu Riegler bb8a5a4c70 refactor(router): Use Nullish coalescing assignment when possible. (#53930)
Inspired by #53923, lets simplify code when possible.

PR Close #53930
2024-01-17 11:36:13 -08:00
Joey Perrott 9c00506a26 ci: use ng-dev-previews project for previews (#53958)
Rather than use the actual adev site, we should be using the ng-dev-preview site

PR Close #53958
2024-01-17 11:19:29 -08:00
Andrew Kushnir 79e8539ce2 refactor(compiler): extra diagnostics for @defer in local compilation mode (#53899)
This commit adds extra logic to produce a diagnostic in case `@Component.deferredImports` contain types from imports that also bring eager symbols. This would result in retaining a regular import and generating a dynamic import, which would not allow to defer-load dependencies.

PR Close #53899
2024-01-17 10:46:15 -08:00
Jessica Janiuk 6f79507ea7 fix(core): Change defer block fixture default behavior to playthrough (#53956)
This inverts the default behavior of test bed to use playthrough for defer blocks instead of manual.

fixes: #53686

PR Close #53956
2024-01-17 10:45:42 -08:00
Joey Perrott 6616019735 refactor: migrate modules to prettier formatting (#53954)
Migrate formatting to prettier for modules directory from clang-format

PR Close #53954
2024-01-17 09:42:01 -08:00
Matthieu Riegler 4d4858fa28 docs: add platform-browser/animations/async entry to AIO (#53914)
fixes #53912

PR Close #53914
2024-01-17 09:14:44 -08:00
Joey Perrott 538fe47d9d ci: use the config from adev for adev previews (#53955)
Properly use the adev firebase config.

PR Close #53955
2024-01-17 09:13:44 -08:00
Andrew Kushnir b07c549802 refactor(compiler): enable register and resolve phases for local compilation (#53901)
This commit update the logic to enable `register` and `resolve` phases for local compilation. Those phases will be useful for local compilation in certain cases (will be used in followup PRs).

PR Close #53901
2024-01-17 09:03:57 -08:00
Joey Perrott 6f6ad0279b ci: set up previews of adev (#53941)
Set up preview actions to allow for a preview of the adev site to be deployed for a PR with the `adev: preview` label.

PR Close #53941
2024-01-16 19:18:33 -08:00
Joey Perrott d08f91f861 ci: run adev tests on CI (#53941)
Run tests in adev for CI

PR Close #53941
2024-01-16 19:18:32 -08:00
Joey Perrott 28aa7b3188 refactor: migrate tools to prettier formatting (#53947)
Migrate formatting to prettier for tools directory from clang-format

PR Close #53947
2024-01-16 19:17:51 -08:00
AleksanderBodurri 6ac0a68d73 docs(devtools): update development docs (#53948)
These docs are out of date with how we currently build devtools in dev mode and as a browser extension. This commit brings these docs up to date.

PR Close #53948
2024-01-16 19:17:20 -08:00
AleksanderBodurri ea19bff302 docs(devtools): remove devtools/CONTRIBUTING.md (#53948)
This is an artifact left over form the repo merge. There is already an existing CONTRIBUTING.md for this repo

PR Close #53948
2024-01-16 19:17:20 -08:00
Pawel Kozlowski 1112e9196a refactor(core): re-organize queries code (#53922)
This commit splits the query implementation and instructions
into a separate files. This is a pattern frequently used by
other functional areas of the framework and is a preparation for
introducing queries-as-signals where we are going to see more
instructions delegating to the same core functionality.

PR Close #53922
2024-01-16 16:00:36 -08:00
Ilija Leko 0d8a5c4665 docs: fix-build-path-in-http-server-command (#53226)
PR Close #53226
2024-01-16 09:37:12 -08:00
Paul Gschwendtner 76ceebad04 fix(compiler-cli): do not throw fatal error if extended type check fails (#53896)
Currently when the extended type check fails due to an import reference
that cannot be generated, the fatal diagnostic is not caught and
not properly exposed as a `ts.Diagnostic` that can be gracefully
handled. This is inconsistent to non-extended type checking diagnostics.

This is problematic because Angular CLI applications currently fail in
obscure ways because:

- the CLI does not expect `getDiagnosticsForFile` to actually throw
  runtime errors.
- the CLI does not seem to properly print these errors given the
  parallel workers and build excection, and those errors are
  especially hard to debug because there is no `stack` for
  `FatalDiagnosticError`'s.

Example: `MyDir` is not exported and the type check block cannot reference it.

PR Close #53896
2024-01-16 09:36:36 -08:00
Joey Perrott 99c2d76651 build(docs-infra): enable prerendering for adev (#53871)
Enable the prerender option for adev's angular.json file.

PR Close #53871
2024-01-16 09:35:46 -08:00
Sasidharan SD 246cb9c381 docs: remove repeated sentence (#53853)
PR Close #53853
2024-01-12 10:26:33 -08:00
Pawel Kozlowski d7c75c6edb refactor(core): improve forwardRef typings (#53880)
This commit improves the forwardRef typings for better
type safety and inference.

PR Close #53880
2024-01-12 10:26:02 -08:00
Andrew Scott 0daca457bb fix(core): TestBed should still use the microtask queue to schedule effects (#53843)
Prior to this commit, `TestBed` would require tests call `flushEffects`
or `fixture.detectChanges` in order to execute effects. In general, we
want to discourage authoring tests like this because it makes the timing
of change detection and effects differ from what happens in the
application. Instead, developers should perform actions and `await` (or
`flush`/`tick` when using `fakeAsync`) some `Promise` so that Angular
can react to the changes in the same way that it does in the
application.

Note that this still _allows_ developers to flush effects synchronously
with `flushEffects` and `detectChanges` but also enables the <action>,
`await` pattern described above.

PR Close #53843
2024-01-11 12:05:58 -08:00
Andrew Kushnir 12f9ed01cc refactor(compiler-cli): add tests for defer blocks and local compilation (#53591)
This commit adds tests to cover local compilation support for `@defer` blocks.

PR Close #53591
2024-01-10 15:29:00 -08:00
Andrew Kushnir 69713413f7 refactor(compiler): update TemplateDefinitionBuilder to support local compilation (#53591)
This commit updates the logic of the `TemplateDefinitionBuilder` to support local compilation and generate a single dependency function for all explicitly deferred deps within a component.

PR Close #53591
2024-01-10 15:28:59 -08:00
Andrew Kushnir 43d6816f9e refactor(compiler-cli): add checks to prevent same deps in imports and deferredImports (#53591)
This commit updates the typechecker logic to prevent same deps in `imports` and `deferredImports`.

PR Close #53591
2024-01-10 15:28:59 -08:00
Andrew Kushnir 4c4fea1304 refactor(compiler): add support for internal deferredImports field (#53591)
This commit updates the logic to add support for internal `deferredImports` field in compiler.

PR Close #53591
2024-01-10 15:28:59 -08:00
Andrew Kushnir c6df89c827 refactor(compiler-cli): update DeferredSymbolTracker to use explicit deps config (#53591)
This commit updates the `DeferredSymbolTracker` class to take info account the `onlyExplicitDeferDependencyImports` flag. The `DeferredSymbolTracker` class also exposes a new API to register import declarations as explicitly deferred, which will be used in followup commits.

PR Close #53591
2024-01-10 15:28:59 -08:00
Andrew Kushnir 9cae9b4a8c refactor(compiler-cli): add an internal config to enforce explicit deps in @defer for local compilation mode (#53591)
This commit adds an internal config option to enforce explicit deps in `@defer` for local compilation mode.

PR Close #53591
2024-01-10 15:28:59 -08:00
Andrew Kushnir 29b959ce31 refactor(compiler): add an internal API to check is an element is inside a defer block (#53591)
This commit updates the logic to expose an internal API on the `R3BoundTarget` to check if an element belongs to any defer block.

PR Close #53591
2024-01-10 15:28:59 -08:00
Andrew Kushnir a24b24e8a4 refactor(compiler-cli): store full Pipe metadata in typechecking code (#53591)
This commit updates typechecker to store full Pipe metadata in internal data strctures, so that this information is available to more places in the code, which will be updated in a followup commit.

PR Close #53591
2024-01-10 15:28:59 -08:00
Andrew Kushnir f51c008744 refactor(compiler-cli): extract various logic into separate functions (#53591)
This commit updates a few places to extract the logic into a separate functions which will be reused in a few places in followup commits.

PR Close #53591
2024-01-10 15:28:59 -08:00
Joey Perrott 3dedd6a07a build: set up adev testing (#53854)
Set up testing for the adev directory

PR Close #53854
2024-01-10 15:22:37 -08:00
Andrew Scott 881376eb42 release: cut the v17.1.0-rc.0 release 2024-01-10 14:25:36 -08:00
1152 changed files with 55845 additions and 44774 deletions
+1 -1
View File
@@ -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/
+38
View File
@@ -0,0 +1,38 @@
# This workflow builds the previews for pull requests when a certain label is applied.
# The actual deployment happens as part of a dedicated second workflow to avoid security
# issues where the building would otherwise occur in an authorized context where secrets
# could be leaked. More details can be found here:
# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/.
name: Build adev for preview deployment
on:
pull_request:
types: [synchronize, labeled]
permissions: read-all
jobs:
adev-build:
runs-on: ubuntu-latest
if: |
(github.event.action == 'labeled' && github.event.label.name == 'adev: preview') ||
(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@e52eb8237f2ed71195f87ce8046467a176568e58
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@e52eb8237f2ed71195f87ce8046467a176568e58
- name: Setup Bazel RBE
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@73777547f819464aa5f48071b966eed34fd2c402
with:
workflow-artifact-name: 'adev-preview'
pull-number: '${{github.event.pull_request.number}}'
artifact-build-revision: '${{github.event.pull_request.head.sha}}'
deploy-directory: './dist/bin/adev/build/browser'
+50
View File
@@ -0,0 +1,50 @@
# This workflow runs whenever the ADEV build workflow has completed. Deployment happens
# as part of a dedicated second workflow to avoid security issues where the building would
# otherwise occur in an authorized context where secrets could be leaked.
#
# More details can be found here:
# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/.
name: Deploying adev preview to Firebase
on:
workflow_run:
workflows: ['Build adev for preview deployment']
types: [completed]
permissions:
# Needed in order to be able to comment on the pull request.
pull-requests: write
# Needed in order to checkout the repository
contents: read
# Needed in order to retrieve the artifacts from the previous job
actions: read
env:
PREVIEW_PROJECT: ng-dev-previews
PREVIEW_SITE: ng-dev-previews-fw
jobs:
deploy:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
with:
token: '${{secrets.GITHUB_TOKEN}}'
- name: Configure Firebase deploy target
working-directory: ./
run: |
# We can use `npx` as the Firebase deploy actions uses it too.
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@73777547f819464aa5f48071b966eed34fd2c402
with:
github-token: '${{secrets.GITHUB_TOKEN}}'
workflow-artifact-name: 'adev-preview'
firebase-config-dir: './adev'
firebase-public-dir: './adev/build/browser'
firebase-project-id: '${{env.PREVIEW_PROJECT}}'
firebase-service-key: '${{secrets.FIREBASE_PREVIEW_SERVICE_TOKEN}}'
+5 -3
View File
@@ -123,7 +123,7 @@ jobs:
- 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
run: yarn bazel test --config=aio_local_deps //adev:test
aio-local:
runs-on:
@@ -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 }}'
@@ -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/
+43 -2
View File
@@ -5,11 +5,35 @@ import {FormatConfig} from '@angular/ng-dev';
*/
export const format: FormatConfig = {
'prettier': {
'matchers': ['**/*.{yaml,yml}'],
'matchers': [
'**/*.{yaml,yml}',
'devtools/**/*.{js,ts}',
'tools/**/*.{js,ts}',
'modules/**/*.{js,ts}',
'scripts/**/*.{js,ts}',
'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/**',
@@ -31,6 +55,23 @@ export const format: FormatConfig = {
'!packages/common/src/i18n/currencies.ts',
// Temporarily disable formatting for adev
'!adev/**',
// Migrated to prettier
'!devtools/**/*.{js,ts}',
'!tools/**/*.{js,ts}',
'!modules/**/*.{js,ts}',
'!scripts/**/*.{js,ts}',
'!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
View File
@@ -31,8 +31,6 @@
"packages/http/**",
"**/.gitignore",
"**/.gitkeep",
"**/yarn.lock",
"**/package.json",
"**/third_party/**",
"**/tsconfig-build.json",
"**/tsconfig-tsec.json",
+4 -1
View File
@@ -1069,9 +1069,10 @@ groups:
])
reviewers:
users:
- twerske
- josephperrott
- jelbourn
- bencodezen
- jessicajaniuk
# =========================================================
# Docs-infra
@@ -1150,6 +1151,7 @@ groups:
- josephperrott
- mgechev
- twerske
- ~jeanmeche
# =========================================================
# Dev-infra
@@ -1394,6 +1396,7 @@ groups:
- devversion # Paul Gschwendtner
- dgp1130 # Doug Parker
- dylhunn # Dylan Hunn
- jeanmeche # Matthieu Riegler
- jelbourn # Jeremy Elbourn
- jessicajaniuk # Jessica Janiuk
- JiaLiPassion # Jia Li
+82 -205
View File
@@ -1,3 +1,79 @@
<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
| Commit | Type | Description |
| -- | -- | -- |
| [79ff91a813](https://github.com/angular/angular/commit/79ff91a813e544929cb5eb5f9aab762a9f3d0435) | fix | allow TS jsDocParsingMode host option to be programmatically set ([#53126](https://github.com/angular/angular/pull/53126)) |
| [5613051a8b](https://github.com/angular/angular/commit/5613051a8bd2626ae347292807b2bf21085c4c02) | fix | allow TS jsDocParsingMode host option to be programmatically set again ([#53292](https://github.com/angular/angular/pull/53292)) |
| [df8a825910](https://github.com/angular/angular/commit/df8a825910951bebf34a4eede42f3ce5cd3e6fb7) | fix | project empty block root node ([#53620](https://github.com/angular/angular/pull/53620)) |
| [478d622265](https://github.com/angular/angular/commit/478d6222650884478314985e3d5132587c4f670c) | fix | project empty block root node in template pipeline ([#53620](https://github.com/angular/angular/pull/53620)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [abdc7e4578](https://github.com/angular/angular/commit/abdc7e45786667e4283912024a641975f1917d97) | feat | support type-checking for generic signal inputs ([#53521](https://github.com/angular/angular/pull/53521)) |
| [e620b3a724](https://github.com/angular/angular/commit/e620b3a724cb615af24b7779c0ab492d24efb8cc) | fix | add compiler option to disable control flow content projection diagnostic ([#53311](https://github.com/angular/angular/pull/53311)) |
| [4c1d69e288](https://github.com/angular/angular/commit/4c1d69e2880f22745c820eee630d10071e4fa86b) | fix | add diagnostic for control flow that prevents content projection ([#53190](https://github.com/angular/angular/pull/53190)) |
| [76ceebad04](https://github.com/angular/angular/commit/76ceebad047f62972654a8c934c77d8d02d9fa14) | fix | do not throw fatal error if extended type check fails ([#53896](https://github.com/angular/angular/pull/53896)) |
| [1a6eaa0fea](https://github.com/angular/angular/commit/1a6eaa0fea1024b919e17ac9d2e8c07df7916de8) | fix | input transform in local compilation mode ([#53645](https://github.com/angular/angular/pull/53645)) |
| [56a76d73e0](https://github.com/angular/angular/commit/56a76d73e037aeea1975808d5c51608fd23d4fa6) | fix | modify `getConstructorDependencies` helper to work with reflection host after the previous change ([#52215](https://github.com/angular/angular/pull/52215)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [863be4b698](https://github.com/angular/angular/commit/863be4b6981dc60ca0610b0e61d2ba1f5759e2a3) | feat | expose new `input` API for signal-based inputs ([#53872](https://github.com/angular/angular/pull/53872)) |
| [94096c6ede](https://github.com/angular/angular/commit/94096c6ede67436a349ae07901f2bb418bf9f461) | feat | support TypeScript 5.3 ([#52572](https://github.com/angular/angular/pull/52572)) |
| [69b384c0d1](https://github.com/angular/angular/commit/69b384c0d16f631741339d8757c32ef08260cfce) | fix | `SignalNode` reactive node incorrectly exposing unset field ([#53571](https://github.com/angular/angular/pull/53571)) |
| [6f79507ea7](https://github.com/angular/angular/commit/6f79507ea7f272d8d09250e222ca831f407867d8) | fix | Change defer block fixture default behavior to playthrough ([#53956](https://github.com/angular/angular/pull/53956)) |
| [32f908ab70](https://github.com/angular/angular/commit/32f908ab70f1b9ed3f92df1cae05ddde68932404) | fix | do not accidentally inherit input transforms when overridden ([#53571](https://github.com/angular/angular/pull/53571)) |
| [bdd61c768a](https://github.com/angular/angular/commit/bdd61c768a28b56c68634b99c036986499829f45) | fix | replace assertion with more intentional error ([#52234](https://github.com/angular/angular/pull/52234)) |
| [0daca457bb](https://github.com/angular/angular/commit/0daca457bb5bb6ffe14b7037264f8497eb5b3daf) | fix | TestBed should still use the microtask queue to schedule effects ([#53843](https://github.com/angular/angular/pull/53843)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [5c1d441029](https://github.com/angular/angular/commit/5c1d4410298e20cb03d7a1ddf7931538b6a181b4) | feat | Add info property to `NavigationExtras` ([#53303](https://github.com/angular/angular/pull/53303)) |
| [50d7916278](https://github.com/angular/angular/commit/50d79162785bb8d3e158a7a4a3733f4c75d3b127) | feat | Add router configuration to resolve navigation promise on error ([#48910](https://github.com/angular/angular/pull/48910)) |
| [a5a9b408e2](https://github.com/angular/angular/commit/a5a9b408e2eb64dcf1d3ca16da4897649dd2fc34) | feat | Add transient info to RouterLink input ([#53784](https://github.com/angular/angular/pull/53784)) |
| [726530a9af](https://github.com/angular/angular/commit/726530a9af9c8daf7295cc3548f24e70f380d70e) | feat | Allow `onSameUrlNavigation: 'ignore'` in `navigateByUrl` ([#52265](https://github.com/angular/angular/pull/52265)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="17.0.9"></a>
# 17.0.9 (2024-01-10)
### common
@@ -30,36 +106,6 @@
<!-- CHANGELOG SPLIT MARKER -->
<a name="17.1.0-next.5"></a>
# 17.1.0-next.5 (2023-12-21)
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [3a689c2050](https://github.com/angular/angular/commit/3a689c20509ed5972b3831988fc0014d293d0cc3) | fix | correctly intercept index in loop tracking function ([#53604](https://github.com/angular/angular/pull/53604)) |
| [df8a825910](https://github.com/angular/angular/commit/df8a825910951bebf34a4eede42f3ce5cd3e6fb7) | fix | project empty block root node ([#53620](https://github.com/angular/angular/pull/53620)) |
| [478d622265](https://github.com/angular/angular/commit/478d6222650884478314985e3d5132587c4f670c) | fix | project empty block root node in template pipeline ([#53620](https://github.com/angular/angular/pull/53620)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [aecb675fa5](https://github.com/angular/angular/commit/aecb675fa5059e510e0223e00fa114d92e799b04) | fix | avoid repeated work when parsing version ([#53598](https://github.com/angular/angular/pull/53598)) |
| [872e7f25fe](https://github.com/angular/angular/commit/872e7f25fea8a01f980e4e406ad382a9e187ce5c) | fix | tree shake version class ([#53598](https://github.com/angular/angular/pull/53598)) |
### migrations
| Commit | Type | Description |
| -- | -- | -- |
| [d49333edc3](https://github.com/angular/angular/commit/d49333edc3fe170c57d953aa2d8df58d0db379e0) | fix | cf migration - detect and error when result is invalid i18n nesting ([#53638](https://github.com/angular/angular/pull/53638)) ([#53639](https://github.com/angular/angular/pull/53639)) |
| [8e2178792d](https://github.com/angular/angular/commit/8e2178792d474e84817c27851cd6b9600deb15b5) | fix | cf migration - ensure full check runs for all imports ([#53637](https://github.com/angular/angular/pull/53637)) |
| [22b95de9bc](https://github.com/angular/angular/commit/22b95de9bcb92267b8f848a1aafa71af70d5577b) | fix | cf migration - fix bug in attribute formatting ([#53636](https://github.com/angular/angular/pull/53636)) |
| [b40bb22a66](https://github.com/angular/angular/commit/b40bb22a66a3c2ae478778f3ef0be0ce971a1b2c) | fix | cf migration - improve import declaration handling ([#53622](https://github.com/angular/angular/pull/53622)) |
| [8bf752539f](https://github.com/angular/angular/commit/8bf752539f6b4b5955e3d61a76423910af55181b) | fix | cf migration - preserve indentation on attribute strings ([#53625](https://github.com/angular/angular/pull/53625)) |
| [7bb312fcf6](https://github.com/angular/angular/commit/7bb312fcf612c57d6606ae14f21707f10d8ff9ce) | fix | cf migration - stop removing empty newlines from i18n blocks ([#53578](https://github.com/angular/angular/pull/53578)) |
| [db6b4a6bc4](https://github.com/angular/angular/commit/db6b4a6bc479b0fac0a4a99e1a202c38d1ea8944) | fix | Fix cf migration bug with parsing for loop conditions properly ([#53558](https://github.com/angular/angular/pull/53558)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [502f300757](https://github.com/angular/angular/commit/502f3007575a5445c2876c92548415cb003582b1) | fix | Should not freeze original object used for route data ([#53635](https://github.com/angular/angular/pull/53635)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="17.0.8"></a>
# 17.0.8 (2023-12-21)
### compiler
@@ -89,45 +135,6 @@
<!-- CHANGELOG SPLIT MARKER -->
<a name="17.1.0-next.4"></a>
# 17.1.0-next.4 (2023-12-13)
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [b98d8f79ed](https://github.com/angular/angular/commit/b98d8f79ed4979fb91661dbdfb6266a917b41474) | fix | handle ambient types in input transform function ([#51474](https://github.com/angular/angular/pull/51474)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [9e5456912a](https://github.com/angular/angular/commit/9e5456912a699315f1f5e8458d35df946c01dc12) | fix | generate less type checking code in for loops ([#53515](https://github.com/angular/angular/pull/53515)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [2565121851](https://github.com/angular/angular/commit/25651218512becb3a491b1c94d643a5066a6d3cb) | fix | Avoid refreshing a host view twice when using transplanted views ([#53021](https://github.com/angular/angular/pull/53021)) |
| [629343f247](https://github.com/angular/angular/commit/629343f24741760e76d98ea1005debaf4775bfc7) | fix | Multiple subscribers to ApplicationRef.isStable should all see values ([#53541](https://github.com/angular/angular/pull/53541)) |
| [42f4f70e97](https://github.com/angular/angular/commit/42f4f70e97b47f7ffcf15e8af2c1a3fa3f393903) | fix | remove signal equality check short-circuit ([#53446](https://github.com/angular/angular/pull/53446)) |
| [f35adcb9b2](https://github.com/angular/angular/commit/f35adcb9b255741515d54bbce694f4cd34aac249) | fix | update feature usage marker ([#53542](https://github.com/angular/angular/pull/53542)) |
| [1fc5442947](https://github.com/angular/angular/commit/1fc5442947b07be7c11fe7c79b9e69f9458c8108) | perf | avoid changes Observable creation on QueryList ([#53498](https://github.com/angular/angular/pull/53498)) |
| [e3a6bf9b6c](https://github.com/angular/angular/commit/e3a6bf9b6c3bef03df9bfc8f05b817bc875cbad6) | perf | optimize memory allocation when reconcilling lists ([#52245](https://github.com/angular/angular/pull/52245)) |
### migrations
| Commit | Type | Description |
| -- | -- | -- |
| [a02767956a](https://github.com/angular/angular/commit/a02767956a00e0b44b690411f01584f6660c83ea) | fix | CF Migration - ensure bound ngIfElse cases ignore line breaks ([#53435](https://github.com/angular/angular/pull/53435)) |
| [6aa1bb78e8](https://github.com/angular/angular/commit/6aa1bb78e8b9ca866b3c2d84f4005a0e67f2b6bc) | fix | cf migration - undo changes when html fails to parse post migration ([#53530](https://github.com/angular/angular/pull/53530)) |
| [cc02852ac4](https://github.com/angular/angular/commit/cc02852ac44bfea13e8b9d5768694a094fc2c4b5) | fix | CF migration only remove newlines of changed template content ([#53508](https://github.com/angular/angular/pull/53508)) |
| [ce1076785c](https://github.com/angular/angular/commit/ce1076785c98ecc9660637cafa4a62a63be8d315) | fix | cf migration validate structure of ngswitch before migrating ([#53530](https://github.com/angular/angular/pull/53530)) |
| [1f5c8bf116](https://github.com/angular/angular/commit/1f5c8bf116783c25234ab7fa301a0be842e58007) | fix | ensure we do not overwrite prior template replacements in migration ([#53393](https://github.com/angular/angular/pull/53393)) |
| [79f791543b](https://github.com/angular/angular/commit/79f791543b607eea1bb6a28b9c744760ba4fd028) | fix | fix cf migration import removal when errors occur ([#53502](https://github.com/angular/angular/pull/53502)) |
### platform-browser
| Commit | Type | Description |
| -- | -- | -- |
| [fdb9cb7a5b](https://github.com/angular/angular/commit/fdb9cb7a5be4695abaa60efc89ecd50ddb9e9e6e) | fix | Get correct base path when using "." as base href when serving from the file:// protocol. ([#53547](https://github.com/angular/angular/pull/53547)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [48c5041687](https://github.com/angular/angular/commit/48c50416872313f23d2759232c990cf8d2de6996) | fix | provide more actionable error message when route is not matched in production mode ([#53523](https://github.com/angular/angular/pull/53523)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="17.0.7"></a>
# 17.0.7 (2023-12-13)
### compiler
@@ -167,47 +174,6 @@
<!-- CHANGELOG SPLIT MARKER -->
<a name="17.1.0-next.3"></a>
# 17.1.0-next.3 (2023-12-06)
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [5613051a8b](https://github.com/angular/angular/commit/5613051a8bd2626ae347292807b2bf21085c4c02) | fix | allow TS jsDocParsingMode host option to be programmatically set again ([#53292](https://github.com/angular/angular/pull/53292)) |
| [77ac4cd324](https://github.com/angular/angular/commit/77ac4cd32491d0c994cb4ea50372601c955cec3d) | fix | generate proper code for nullish coalescing in styling host bindings ([#53305](https://github.com/angular/angular/pull/53305)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [e620b3a724](https://github.com/angular/angular/commit/e620b3a724cb615af24b7779c0ab492d24efb8cc) | fix | add compiler option to disable control flow content projection diagnostic ([#53311](https://github.com/angular/angular/pull/53311)) |
| [d7a83f9521](https://github.com/angular/angular/commit/d7a83f95213cdd5d3ceefbc95fa1190856b0198c) | fix | avoid conflicts with built-in global variables in for loop blocks ([#53319](https://github.com/angular/angular/pull/53319)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [77939a3bd3](https://github.com/angular/angular/commit/77939a3bd39073d07e24797a4632ec2d2a6b92e0) | fix | cleanup signal consumers for all views ([#53351](https://github.com/angular/angular/pull/53351)) |
| [899f6c4a12](https://github.com/angular/angular/commit/899f6c4a12127f87aeedf47ee128ce949ebe717c) | fix | handle hydration of multiple nodes projected in a single slot ([#53270](https://github.com/angular/angular/pull/53270)) |
| [4b23221b4e](https://github.com/angular/angular/commit/4b23221b4e5f8be7bcffc8ace255143653550d3d) | fix | support hydration for cases when content is re-projected using ng-template ([#53304](https://github.com/angular/angular/pull/53304)) |
| [82609d471c](https://github.com/angular/angular/commit/82609d471c9802b847a5654918eca1ba3ebb29b3) | fix | support swapping hydrated views in `@for` loops ([#53274](https://github.com/angular/angular/pull/53274)) |
### migrations
| Commit | Type | Description |
| -- | -- | -- |
| [1c1e8c477b](https://github.com/angular/angular/commit/1c1e8c477b8d5c8deecf05744bd1d5f7c86d2e14) | fix | CF migration - ensure NgIfElse attributes are properly removed ([#53298](https://github.com/angular/angular/pull/53298)) |
| [2998d482dd](https://github.com/angular/angular/commit/2998d482dd3f1f5ff7f08260c3947ded74dac126) | fix | CF Migration - Fix case of aliases on i18n ng-templates preventing removal ([#53299](https://github.com/angular/angular/pull/53299)) |
| [aad5e5bd0e](https://github.com/angular/angular/commit/aad5e5bd0e7f6581f51fc3a23c98a7f11219a8f8) | fix | CF Migration add support for ngIf with just a then ([#53297](https://github.com/angular/angular/pull/53297)) |
| [6f75471307](https://github.com/angular/angular/commit/6f75471307a9458d0cffd0ee2bbf4190640c3c3a) | fix | CF Migration fix missing alias for bound ngifs ([#53296](https://github.com/angular/angular/pull/53296)) |
| [2a5a8f6f05](https://github.com/angular/angular/commit/2a5a8f6f052961c010a68a05d868f50220f2fcf2) | fix | Change CF Migration ng-template placeholder generation and handling ([#53394](https://github.com/angular/angular/pull/53394)) |
| [03e2f1bb25](https://github.com/angular/angular/commit/03e2f1bb25693d1a5f4e53fc4f4cd1937cf6bda1) | fix | fix regexp for else and then in cf migration ([#53257](https://github.com/angular/angular/pull/53257)) |
| [f4a96a9160](https://github.com/angular/angular/commit/f4a96a9160927903c38e172f6375c4bc5f8e0905) | fix | handle aliases on bound ngIf migrations ([#53261](https://github.com/angular/angular/pull/53261)) |
| [5a0ed28c9d](https://github.com/angular/angular/commit/5a0ed28c9d3f1c7507feee482e37c3346d52b033) | fix | handle nested ng-template replacement safely in CF migration ([#53368](https://github.com/angular/angular/pull/53368)) |
| [01b18a4248](https://github.com/angular/angular/commit/01b18a4248f068df33c0ca8a2d62ef2fc69f941c) | fix | handle templates outside of component in cf migration ([#53368](https://github.com/angular/angular/pull/53368)) |
| [9834fd2738](https://github.com/angular/angular/commit/9834fd27387ed5edc65bed56aa003fc45d250420) | fix | remove setting that removes comments in CF migration ([#53350](https://github.com/angular/angular/pull/53350)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [5c1d441029](https://github.com/angular/angular/commit/5c1d4410298e20cb03d7a1ddf7931538b6a181b4) | feat | Add info property to `NavigationExtras` ([#53303](https://github.com/angular/angular/pull/53303)) |
| [50d7916278](https://github.com/angular/angular/commit/50d79162785bb8d3e158a7a4a3733f4c75d3b127) | feat | Add router configuration to resolve navigation promise on error ([#48910](https://github.com/angular/angular/pull/48910)) |
| [1940280d27](https://github.com/angular/angular/commit/1940280d27bb3ece585d6345dbd742d208f46912) | fix | Ensure canMatch guards run on wildcard routes ([#53239](https://github.com/angular/angular/pull/53239)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="17.0.6"></a>
# 17.0.6 (2023-12-06)
### compiler
@@ -247,43 +213,6 @@
<!-- CHANGELOG SPLIT MARKER -->
<a name="17.1.0-next.2"></a>
# 17.1.0-next.2 (2023-11-29)
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [79ff91a813](https://github.com/angular/angular/commit/79ff91a813e544929cb5eb5f9aab762a9f3d0435) | fix | allow TS jsDocParsingMode host option to be programmatically set ([#53126](https://github.com/angular/angular/pull/53126)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [4c1d69e288](https://github.com/angular/angular/commit/4c1d69e2880f22745c820eee630d10071e4fa86b) | fix | add diagnostic for control flow that prevents content projection ([#53190](https://github.com/angular/angular/pull/53190)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [58cf389d80](https://github.com/angular/angular/commit/58cf389d8095dd522a998b6b9a7d7b8da1656644) | fix | avoid stale provider info when TestBed.overrideProvider is used ([#52918](https://github.com/angular/angular/pull/52918)) |
| [c7c7ea9813](https://github.com/angular/angular/commit/c7c7ea9813f6dcf91c096bb37d36bfe0c715a04f) | fix | inherit host directives ([#52992](https://github.com/angular/angular/pull/52992)) |
| [b35c6731e5](https://github.com/angular/angular/commit/b35c6731e51de9c33707010fc780cbaa559be6c3) | fix | Reattached views that are dirty from a signal update should refresh ([#53001](https://github.com/angular/angular/pull/53001)) |
### migrations
| Commit | Type | Description |
| -- | -- | -- |
| [dbca1c9d61](https://github.com/angular/angular/commit/dbca1c9d618be4d195d779ef80606c6d22f7c977) | fix | Add ngForTemplate support to control flow migration ([#53076](https://github.com/angular/angular/pull/53076)) |
| [53912fdf74](https://github.com/angular/angular/commit/53912fdf74e1224f95edc3dd550c51451e613c44) | fix | allows colons in ngIf else cases to migrate ([#53076](https://github.com/angular/angular/pull/53076)) |
| [fadfee4324](https://github.com/angular/angular/commit/fadfee43247acec7e450d5cc929a0a6780a54bd1) | fix | cf migration fix migrating empty switch default ([#53237](https://github.com/angular/angular/pull/53237)) |
| [b2aeaf5d97](https://github.com/angular/angular/commit/b2aeaf5d97327842a5bb657e9f02bb4f1358304b) | fix | CF migration log warning when collection aliasing detected in `@for` ([#53238](https://github.com/angular/angular/pull/53238)) |
| [c6326289f8](https://github.com/angular/angular/commit/c6326289f87089b3415ba0f3e371206b8a396b66) | fix | cf migration removes unnecessary bound ngifelse attribute ([#53236](https://github.com/angular/angular/pull/53236)) |
| [e6f10e81d2](https://github.com/angular/angular/commit/e6f10e81d2486b5cc1f468777b7e1057d3f09dc5) | fix | control flow migration formatting fixes ([#53076](https://github.com/angular/angular/pull/53076)) |
| [6291c8db09](https://github.com/angular/angular/commit/6291c8db092c0ab67f6789cc03c19dfa0bdc251d) | fix | fix off by one issue with template removal in CF migration ([#53255](https://github.com/angular/angular/pull/53255)) |
| [f1b7d40057](https://github.com/angular/angular/commit/f1b7d400575a6a02a2fc2b642c2b8c15cca9b3c4) | fix | fixes CF migration i18n ng-template offsets ([#53212](https://github.com/angular/angular/pull/53212)) |
| [a738b48717](https://github.com/angular/angular/commit/a738b48717e16613b34c3e50480cd49f2a31858f) | fix | fixes control flow migration common module removal ([#53076](https://github.com/angular/angular/pull/53076)) |
| [a3599515bb](https://github.com/angular/angular/commit/a3599515bb2513fbcb2899284c7f6b4bc021ddaf) | fix | properly handle ngIfThen cases in CF migration ([#53256](https://github.com/angular/angular/pull/53256)) |
| [8a52674faa](https://github.com/angular/angular/commit/8a52674faacefd4042726383fdf0aed59a04fb7e) | fix | Update CF migration to skip templates with duplicate ng-template names ([#53204](https://github.com/angular/angular/pull/53204)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [29e0834c4d](https://github.com/angular/angular/commit/29e0834c4deecfa8bf384b5e4359796c8123afcd) | fix | Resolvers in different parts of the route tree should be able to execute together ([#52934](https://github.com/angular/angular/pull/52934)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="17.0.5"></a>
# 17.0.5 (2023-11-29)
### core
@@ -313,39 +242,6 @@
<!-- CHANGELOG SPLIT MARKER -->
<a name="17.1.0-next.1"></a>
# 17.1.0-next.1 (2023-11-20)
### common
| Commit | Type | Description |
| -- | -- | -- |
| [29c5416d14](https://github.com/angular/angular/commit/29c5416d14638a05a894269aa5dbe67e98754418) | fix | remove `load` on image once it fails to load ([#52990](https://github.com/angular/angular/pull/52990)) |
| [7affa57754](https://github.com/angular/angular/commit/7affa5775427e92ef6e949c879765b7c8aa172da) | fix | scan images once page is loaded ([#52991](https://github.com/angular/angular/pull/52991)) |
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [ec2d6e7b9c](https://github.com/angular/angular/commit/ec2d6e7b9c2b386247d1320ee89f8e3ac5e5a0dd) | fix | changed after checked error in for loops ([#52935](https://github.com/angular/angular/pull/52935)) |
| [406049b95e](https://github.com/angular/angular/commit/406049b95e5234f17a7a18839ac848640f53fdde) | fix | generate i18n instructions for blocks ([#52958](https://github.com/angular/angular/pull/52958)) |
| [d9d566d315](https://github.com/angular/angular/commit/d9d566d31540582d73201675d0b8ed901261669e) | fix | nested for loops incorrectly calculating computed variables ([#52931](https://github.com/angular/angular/pull/52931)) |
| [5fb707f81a](https://github.com/angular/angular/commit/5fb707f81aee43751e61d2ed0861afc9b85bc85a) | fix | produce placeholder for blocks in i18n bundles ([#52958](https://github.com/angular/angular/pull/52958)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [b4d022e230](https://github.com/angular/angular/commit/b4d022e230ca141b12437949d11dc384bfe5c082) | fix | add diagnostic for control flow that prevents content projection ([#52726](https://github.com/angular/angular/pull/52726)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [ed0fbd4071](https://github.com/angular/angular/commit/ed0fbd4071339b1af22d82bac07d51c6c41790cd) | fix | cleanup loading promise when no dependencies are defined ([#53031](https://github.com/angular/angular/pull/53031)) |
| [1ce31d819b](https://github.com/angular/angular/commit/1ce31d819b2e4f4425a41f07167a6edce98e77e1) | fix | handle local refs when `getDeferBlocks` is invoked in tests ([#52973](https://github.com/angular/angular/pull/52973)) |
### migrations
| Commit | Type | Description |
| -- | -- | -- |
| [e33f6e0f1a](https://github.com/angular/angular/commit/e33f6e0f1a483cad908fa6d7376d62332797499c) | fix | control flow migration fails for async pipe with unboxing of observable ([#52756](https://github.com/angular/angular/pull/52756)) ([#52972](https://github.com/angular/angular/pull/52972)) |
| [5564d020cd](https://github.com/angular/angular/commit/5564d020cdcea8273b65cf69c45c3f935195af66) | fix | Fixes control flow migration if then else case ([#53006](https://github.com/angular/angular/pull/53006)) |
| [28f6cbf9c9](https://github.com/angular/angular/commit/28f6cbf9c91f957b4926fe34610387e1f1919d4f) | fix | fixes migrations of nested switches in control flow ([#53010](https://github.com/angular/angular/pull/53010)) |
| [e090b48bf8](https://github.com/angular/angular/commit/e090b48bf8534761d46523be57a7889a325bcdec) | fix | tweaks to formatting in control flow migration ([#53058](https://github.com/angular/angular/pull/53058)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="17.0.4"></a>
# 17.0.4 (2023-11-20)
### common
@@ -379,24 +275,6 @@
<!-- CHANGELOG SPLIT MARKER -->
<a name="17.1.0-next.0"></a>
# 17.1.0-next.0 (2023-11-15)
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [56a76d73e0](https://github.com/angular/angular/commit/56a76d73e037aeea1975808d5c51608fd23d4fa6) | fix | modify `getConstructorDependencies` helper to work with reflection host after the previous change ([#52215](https://github.com/angular/angular/pull/52215)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [94096c6ede](https://github.com/angular/angular/commit/94096c6ede67436a349ae07901f2bb418bf9f461) | feat | support TypeScript 5.3 ([#52572](https://github.com/angular/angular/pull/52572)) |
| [bdd61c768a](https://github.com/angular/angular/commit/bdd61c768a28b56c68634b99c036986499829f45) | fix | replace assertion with more intentional error ([#52234](https://github.com/angular/angular/pull/52234)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [726530a9af](https://github.com/angular/angular/commit/726530a9af9c8daf7295cc3548f24e70f380d70e) | feat | Allow `onSameUrlNavigation: 'ignore'` in `navigateByUrl` ([#52265](https://github.com/angular/angular/pull/52265)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="17.0.3"></a>
# 17.0.3 (2023-11-15)
### animations
@@ -489,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:
@@ -597,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).
+19
View File
@@ -61,6 +61,25 @@ Get started with Angular, learn the fundamentals and explore advanced topics on
- [Lazy Loading][lazyloading]
- [Animations][animations]
### Local Development
To contribute to Angular docs, you can setup a local environment with the following commands:
```bash
# Clone Angular repo
git clone https://github.com/angular/angular.git
# Navigate to project directory
cd angular
# Install dependencies
yarn
# Build and run local dev server
# Note: Initial build will take some time
yarn docs
```
## Development Setup
### Prerequisites
+3 -3
View File
@@ -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",
],
)
+40 -2
View File
@@ -1,6 +1,6 @@
load("//:packages.bzl", "link_packages")
load("@build_bazel_rules_nodejs//:index.bzl", "copy_to_bin")
load("@npm//@angular-devkit/architect-cli:index.bzl", "architect")
load("@npm//@angular-devkit/architect-cli:index.bzl", "architect", "architect_test")
package(default_visibility = ["//visibility:public"])
@@ -21,6 +21,13 @@ APPLICATION_FILES = [
],
)
TEST_FILES = APPLICATION_FILES + [
"karma.conf.js",
"tsconfig.spec.json",
] + glob(
["**/*.spec.ts"],
)
APPLICATION_DEPS = link_packages([
"@npm//@angular-devkit/build-angular",
"@npm//@angular/animations",
@@ -69,6 +76,21 @@ APPLICATION_DEPS = link_packages([
"@npm//angular-split",
])
TEST_DEPS = APPLICATION_DEPS + link_packages([
"@npm//@angular/platform-browser-dynamic",
"@npm//@angular/build-tooling/bazel/browsers/chromium",
"@npm//@types/jasmine",
"@npm//@types/node",
"@npm//assert",
"@npm//jasmine",
"@npm//jasmine-core",
"@npm//karma-chrome-launcher",
"@npm//karma-coverage",
"@npm//karma-jasmine",
"@npm//karma-jasmine-html-reporter",
"//aio/tools:windows-chromium-path",
])
copy_to_bin(
name = "application_files_bin",
srcs = APPLICATION_FILES,
@@ -78,7 +100,7 @@ architect(
name = "build",
args = [
"angular-dev:build",
"--output-path=build-app",
"--output-path=build",
],
chdir = "$(RULEDIR)",
data = APPLICATION_DEPS + [
@@ -100,3 +122,19 @@ architect(
":application_files_bin",
],
)
architect_test(
name = "test",
args = [
"angular-dev:test",
"--no-watch",
],
chdir = package_name(),
data = TEST_DEPS + TEST_FILES,
env = {
"CHROME_BIN": "../$(CHROMIUM)",
},
toolchains = [
"@npm//@angular/build-tooling/bazel/browsers/chromium:toolchain_alias",
],
)
+2 -2
View File
@@ -26,8 +26,7 @@
"index": "src/index.html",
"browser": "src/main.ts",
"server": "src/main.server.ts",
// TODO(josephperrott): enabled prerender
"prerender": false,
"prerender": true,
"polyfills": ["src/polyfills.ts", "zone.js"],
"tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "scss",
@@ -89,6 +88,7 @@
"polyfills": ["zone.js", "zone.js/testing"],
"tsConfig": "tsconfig.spec.json",
"include": ["src/app"],
"karmaConfig": "karma.conf.js",
"inlineStyleLanguage": "scss",
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["@angular/docs/styles/global-styles.scss"],
+73
View File
@@ -0,0 +1,73 @@
{
"hosting": {
"target": "angular-docs",
"public": "./build/browser",
"ignore": ["**/.*"],
"headers": [
{
"source": "assets/tutorials/common/*.jpg",
"headers": [
{
"key": "Cross-Origin-Resource-Policy",
"value": "cross-origin"
},
{
"key": "Access-Control-Allow-Origin",
"value": "*"
}
]
},
{
"source": "*.[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].+(css|js)",
"headers": [
{
"key": "Cache-Control",
"value": "public,max-age=31536000,immutable"
},
{
"key": "Access-Control-Allow-Origin",
"value": "*"
}
]
},
{
"source": "/[0-9a-f][0-9a-f][0-9a-f].[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].js",
"headers": [
{
"key": "Cross-Origin-Embedder-Policy",
"value": "require-corp"
}
]
},
{
"source": "/@(ngsw-worker.js|ngsw.json)",
"headers": [
{
"key": "Cache-Control",
"value": "no-cache"
}
]
},
{
"source": "/**",
"headers": [
{
"key": "Cross-Origin-Opener-Policy",
"value": "same-origin"
},
{
"key": "Cross-Origin-Embedder-Policy",
"value": "require-corp"
}
]
}
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
+74
View File
@@ -0,0 +1,74 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
const {getAdjustedChromeBinPathForWindows} = require('../aio/tools/windows-chromium-path');
process.env.CHROME_BIN = getAdjustedChromeBinPathForWindows();
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('@angular-devkit/build-angular/plugins/karma'),
{'reporter:jasmine-seed': ['type', JasmineSeedReporter]},
],
proxies: {
'/dummy/image': 'src/assets/images/logos/angular/angular.png',
},
client: {
clearContext: false, // leave Jasmine Spec Runner output visible in browser
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
random: true,
seed: '',
},
},
jasmineHtmlReporter: {
suppressAll: true // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, './coverage/site'),
subdir: '.',
reporters: [
{ type: 'html' },
{ type: 'text-summary' }
],
},
reporters: ['progress', 'kjhtml', 'jasmine-seed'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
customLaunchers: {
ChromeHeadlessNoSandbox: {
base: 'ChromeHeadless',
// See /integration/README.md#browser-tests for more info on these args
flags: ['--no-sandbox', '--headless', '--disable-gpu', '--disable-dev-shm-usage', '--hide-scrollbars', '--mute-audio'],
},
},
browsers: ['ChromeHeadlessNoSandbox'],
browserNoActivityTimeout: 60000,
singleRun: false,
restartOnFileChange: true,
});
};
// Helpers
function JasmineSeedReporter(baseReporterDecorator) {
baseReporterDecorator(this);
this.onBrowserComplete = (browser, result) => {
const seed = result.order && result.order.random && result.order.seed;
if (seed) this.write(`${browser}: Randomized with seed ${seed}.\n`);
};
this.onRunComplete = () => undefined;
}
@@ -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;
@@ -7,7 +7,7 @@
*/
import {Injector} from '@angular/core';
import {WINDOW} from '@angular/docs';
import {ENVIRONMENT, WINDOW} from '@angular/docs';
import {AnalyticsService} from './analytics.service';
describe('AnalyticsService', () => {
@@ -36,6 +36,7 @@ describe('AnalyticsService', () => {
injector = Injector.create({
providers: [
{provide: ENVIRONMENT, useValue: {}},
{provide: AnalyticsService, deps: [WINDOW]},
{provide: WINDOW, useFactory: () => mockWindow, deps: []},
],
@@ -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';
}
@@ -19,7 +19,7 @@ import {EmbeddedTutorialManager} from '../embedded-tutorial-manager.service';
import {CodeEditor, REQUIRED_FILES} from './code-editor.component';
import {CodeMirrorEditor} from './code-mirror-editor.service';
import {FakeChangeDetectorRef} from '../../../../../shared/src/lib/utils/test-utils.spec';
import {FakeChangeDetectorRef} from '@angular/docs/testing';
import {TutorialType} from '@angular/docs';
const files = [
@@ -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 -->
@@ -8,16 +8,9 @@
import {TestBed} from '@angular/core/testing';
import type {FileSystemTree} from '@webcontainer/api';
import type {
TutorialConfig,
TutorialMetadata,
} from '@angular/docs';
import {
TUTORIALS_COMMON_DIRECTORY,
TUTORIALS_METADATA_WEB_PATH,
TUTORIALS_SOURCE_CODE_WEB_PATH,
TutorialType,
} from '@angular/docs';
import type {TutorialConfig, TutorialMetadata} from '@angular/docs';
import {TUTORIALS_ASSETS_WEB_PATH} from '../editor/constants';
import {TutorialType} from '@angular/docs';
import {EmbeddedTutorialManager} from './embedded-tutorial-manager.service';
describe('EmbeddedTutorialManager', () => {
@@ -252,13 +245,7 @@ describe('EmbeddedTutorialManager', () => {
},
},
};
const commonSourceCode: FileSystemTree = {
'common.ts': {
file: {
contents: 'code',
},
},
};
const metadata: TutorialMetadata = {
tutorialFiles: {'app.js': ''},
openFiles: ['app.js'],
@@ -271,14 +258,13 @@ describe('EmbeddedTutorialManager', () => {
const fetchMock = spyOn(window, 'fetch');
fetchMock.and.returnValues(
Promise.resolve(new Response(JSON.stringify(commonSourceCode))),
Promise.resolve(new Response(JSON.stringify(tutorialSourceCode))),
Promise.resolve(new Response(JSON.stringify(metadata))),
);
await service.fetchAndSetTutorialFiles(tutorial);
expect(fetchMock).toHaveBeenCalledTimes(3);
expect(fetchMock).toHaveBeenCalledTimes(2);
expect(service.tutorialId()).toEqual(tutorial);
expect(service.tutorialFilesystemTree()).toEqual(tutorialSourceCode);
@@ -289,8 +275,6 @@ describe('EmbeddedTutorialManager', () => {
expect(service.type()).toEqual(metadata.type);
expect(service.commonFilesystemTree()).toEqual(commonSourceCode);
expect(service.hiddenFiles()).toEqual(metadata.hiddenFiles);
expect(service.answerFiles()).toEqual(metadata.answerFiles!);
});
@@ -299,15 +283,11 @@ describe('EmbeddedTutorialManager', () => {
const fetchMock = spyOn(window, 'fetch');
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
.and.returnValues(Promise.resolve(new Response(null, {status: 404})));
fetchMock
.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`)
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`)
.and.returnValues(Promise.resolve(new Response(null, {status: 404})));
await expectAsync(service.fetchAndSetTutorialFiles(tutorial)).toBeRejectedWithError(
@@ -315,38 +295,15 @@ describe('EmbeddedTutorialManager', () => {
);
});
it('should throw an error if the tutorial common project cannot be fetched', async () => {
const fetchMock = spyOn(window, 'fetch');
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
.and.returnValues(Promise.resolve(new Response(null, {status: 404})));
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
fetchMock
.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
await expectAsync(service.fetchAndSetTutorialFiles(tutorial)).toBeRejectedWithError(
'Missing source code for tutorial common',
);
});
it('should not set shouldReinstallDependencies if project did not change', async () => {
const fetchMock = spyOn(window, 'fetch');
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
fetchMock.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`).and.returnValues(
fetchMock.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`).and.returnValues(
Promise.resolve(
new Response(
JSON.stringify({
@@ -368,15 +325,12 @@ describe('EmbeddedTutorialManager', () => {
it('should trigger shouldReInstallDependencies if new metadata has different dependencies', async () => {
const fetchMock = spyOn(window, 'fetch');
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
fetchMock.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`).and.returnValues(
fetchMock.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`).and.returnValues(
Promise.resolve(
new Response(
JSON.stringify({
@@ -404,14 +358,10 @@ describe('EmbeddedTutorialManager', () => {
const fetchMock = spyOn(window, 'fetch');
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
fetchMock.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`).and.returnValues(
fetchMock.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`).and.returnValues(
Promise.resolve(
new Response(
JSON.stringify({
@@ -437,14 +387,10 @@ describe('EmbeddedTutorialManager', () => {
const fetchMock = spyOn(window, 'fetch');
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
fetchMock.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`).and.returnValues(
fetchMock.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`).and.returnValues(
Promise.resolve(
new Response(
JSON.stringify({
@@ -472,16 +418,12 @@ describe('EmbeddedTutorialManager', () => {
const fetchMock = spyOn(window, 'fetch');
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
const allFiles = ['file1.ts', 'file2.ts'];
fetchMock.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`).and.returnValues(
fetchMock.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`).and.returnValues(
Promise.resolve(
new Response(
JSON.stringify({
@@ -507,16 +449,12 @@ describe('EmbeddedTutorialManager', () => {
const fetchMock = spyOn(window, 'fetch');
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
const allFiles = ['file1.ts', 'file2.ts'];
fetchMock.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`).and.returnValues(
fetchMock.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`).and.returnValues(
Promise.resolve(
new Response(
JSON.stringify({
@@ -539,16 +477,12 @@ describe('EmbeddedTutorialManager', () => {
const fetchMock = spyOn(window, 'fetch');
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${TUTORIALS_COMMON_DIRECTORY}.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
fetchMock
.withArgs(`${TUTORIALS_SOURCE_CODE_WEB_PATH}/${tutorial}.json`)
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
const allFiles = ['file1.ts', 'file2.ts'];
fetchMock.withArgs(`${TUTORIALS_METADATA_WEB_PATH}/${tutorial}.json`).and.returnValues(
fetchMock.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`).and.returnValues(
Promise.resolve(
new Response(
JSON.stringify({
@@ -15,7 +15,7 @@ import {TutorialType} from '@angular/docs';
import {
FakeWebContainer,
FakeWebContainerProcess,
} from '../../../../shared/src/lib/utils/test-utils.spec';
} from '@angular/docs/testing';
import {AlertManager} from './alert-manager.service';
import {EmbeddedTutorialManager} from './embedded-tutorial-manager.service';
import {LoadingStep} from './enums/loading-steps';
@@ -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();
@@ -11,7 +11,8 @@ import {By} from '@angular/platform-browser';
import {Terminal} from './terminal.component';
import {TerminalHandler, TerminalType} from './terminal-handler.service';
import {FakeEventTarget, WINDOW} from '@angular/docs';
import {WINDOW} from '@angular/docs';
import {FakeEventTarget} from '@angular/docs/testing';
describe('Terminal', () => {
let component: Terminal;
@@ -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');
});
});
@@ -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');
});
});
@@ -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();
});
});
@@ -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);
});
});
@@ -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;
@@ -19,7 +19,7 @@ import {
EmbeddedEditor,
EmbeddedTutorialManager,
NodeRuntimeSandbox
} from '@angular/docs';
} from '../../editor';
import {mockAsyncProvider} from '../../core/services/inject-async';
import Tutorial from './tutorial.component';
+2 -1
View File
@@ -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,
+6
View File
@@ -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';
@@ -78,7 +78,7 @@ For example, imagine the following scenario:
1. After some time, a new version of the application is deployed to the server.
This newer version includes the files `index.html`, `main.<main-hash-2>.js` and `lazy-chunk.<lazy-hash-2>.js`.
IMPORANT: The hashes are different now, because the content of the files changed. The old version is no longer available on the server.
IMPORTANT: The hashes are different now, because the content of the files changed. The old version is no longer available on the server.
1. In the meantime, the user's browser decides to evict `lazy-chunk.<lazy-hash-1>.js` from its cache.
Browsers might decide to evict specific (or all) resources from a cache in order to reclaim disk space.
@@ -110,7 +110,7 @@ Make a change to the application, and watch the service worker install the updat
<docs-code language="shell">
ng build
npx http-server -p 8080 -c-1 dist/
npx http-server -p 8080 -c-1 dist/&lt;project-name&gt;/browser
</docs-code>
@@ -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,4 +1,4 @@
<div class="section">
<h2>&commat;Optional() Component</h2>
<p>This component still works even though the OptionalService (notice &commat;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 &commat;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
+1 -1
View File
@@ -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>
+4 -1
View File
@@ -240,10 +240,13 @@ In the example below, the prefetching starts when a browser becomes idle and the
## Testing
Angular provides TestBed APIs to simplify the process of testing `@defer` blocks and triggering different states during testing. By default, `@defer` blocks in tests are in "paused" (`@placeholder`) state, so that you can manually transition between states.
Angular provides TestBed APIs to simplify the process of testing `@defer` blocks and triggering different states during testing. By default, `@defer` blocks in tests will play through like a defer block would behave in a real application. If you want to manually step through states, you can switch the defer block behavior to `Manual` in the TestBed configuration.
```typescript
it('should render a defer block in different states', async () => {
// configures the defer block behavior to start in "paused" state for manual control.
TestBed.configureTestingModule({deferBlockBehavior: DeferBlockBehavior.Manual});
@Component({
// ...
template: `
@@ -11,7 +11,7 @@ The injection context is available in these situations:
* In the `factory` function specified for an `InjectionToken`.
* Within a stack frame that is run in a injection context.
Knowing when your are in an injection context, will allow you to use the [`inject`](api/core/inject) function to inject instances.
Knowing when you are in an injection context, will allow you to use the [`inject`](api/core/inject) function to inject instances.
## Class constructors
@@ -33,6 +33,7 @@ class MyComponent {
Some APIs are designed to be run in an injection context. This is the case, for example, of the router guards. It allows the use of [`inject`](api/core/inject) to access a service within the guard function.
Here is an example for `CanActivateFn`
<docs-code language="typescript" highlight="[3]">
const canActivateTeam: CanActivateFn =
(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
@@ -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.
@@ -12,9 +12,6 @@ With hierarchical dependency injection, you can isolate sections of the applicat
## Types of injector hierarchies
Injectors in Angular have rules that you can leverage to achieve the desired visibility of injectables in your applications.
By understanding these rules, you can determine whether to declare a provider at the application level, in a Component, or in a Directive.
Angular has two injector hierarchies:
| Injector hierarchies | Details |
@@ -1146,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>
+2 -2
View File
@@ -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>
+6 -4
View File
@@ -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:
+1 -1
View File
@@ -50,7 +50,7 @@ const configPromise = firstValueFrom(config$);
const req = httpTesting.expectOne('/api/config', 'Request to load the configuration');
// We can assert various properties of the request if desired.
expect(req.method).toBe('GET');
expect(req.request.method).toBe('GET');
// Flushing the request causes it to complete, delivering the result.
req.flush(DEFAULT_CONFIG);
@@ -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)" />
```
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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:
@@ -224,7 +224,7 @@ For details of those options and their possible values, see the [Angular CLI Ref
## Complex configuration values
The `assets`, `index`, `styles`, and `scripts` options can have either simple path string values, or object values with specific fields.
The `assets`, `index`, `outputPath`, `styles`, and `scripts` options can have either simple path string values, or object values with specific fields.
The `sourceMap` and `optimization` options can be set to a simple boolean value. They can also be given a complex value using the configuration file.
The following sections provide more details of how these complex values are used in each case.
@@ -418,6 +418,7 @@ Several options can be used to fine-tune the optimization of an application.
|:--- |:--- |:--- |:--- |
| `minify` | Minify CSS definitions by removing extraneous whitespace and comments, merging identifiers, and minimizing values. | `boolean` | `true` |
| `inlineCritical` | Extract and inline critical CSS definitions to improve [First Contentful Paint](https://web.dev/first-contentful-paint). | `boolean` | `true` |
| `removeSpecialComments` | Remove comments in global CSS that contains `@license` or `@preserve` or that starts with `//!` or `/*!`. | `boolean` | `true` |
#### Fonts optimization options
@@ -508,3 +509,16 @@ When supplying the value as a string the filename of the specified path will be
|:--- |:--- |:--- |:--- |
| `input` | The path of a file to use for the application's generated HTML index. | `string` | None (required) |
| `output` | The output path of the application's generated HTML index file. The full provided path will be used and will be considered relative to the application's configured output path. | `string` | `index.html` |
### Output path configuration
The `outputPath` option can be either a String which will be used as the `base` value or an Object for more fine-tune configuration.
Several options can be used to fine-tune the output structure of an application.
| Options | Details | Value type | Default value |
|:--- |:--- |:--- |:--- |
| `base` | Specify the output path relative to workspace root. | `string` | |
| `browser` | The output directory name for your browser build is within the base output path. This can be safely served to users. | `string` | `browser` |
| `server` | The output directory name of your server build within the output path base. | `string` | `server` |
| `media` | The output directory name for your media files located within the output browser directory. These media files are commonly referred to as resources in CSS files. | `string` | `media` |
@@ -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>
+2 -2
View File
@@ -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">
![Angular workmark gradient logo](./images/press-kit/angular_wordmark_gradient.png "Angular workmark gradient logo")
![Angular workmark white logo](./images/press-kit/angular_wordmark_white.png "Angular workmark white logo")
![Angular wordmark gradient logo](./images/press-kit/angular_wordmark_gradient.png "Angular wordmark gradient logo")
![Angular wordmark white logo](./images/press-kit/angular_wordmark_white.png "Angular wordmark white logo")
![Angular wordmark black logo](./images/press-kit/angular_wordmark_black.png "Angular wordmark black logo")
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>
+1 -1
View File
@@ -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:
+1
View File
@@ -9,6 +9,7 @@ This table covers [Angular versions under active support](reference/releases#act
| Angular | Node.js | TypeScript | RxJS |
| ------------------ | ------------------------------------ | -------------- | ------------------ |
| 17.1.0 | ^18.13.0 \|\| ^20.9.0 | >=5.2.0 <5.4.0 | ^6.5.3 \|\| ^7.4.0 |
| 17.0.x | ^18.13.0 \|\| ^20.9.0 | >=4.9.3 <5.3.0 | ^6.5.3 \|\| ^7.4.0 |
| 16.1.x \|\| 16.2.x | ^16.14.0 \|\| ^18.10.0 | >=4.9.3 <5.2.0 | ^6.5.3 \|\| ^7.4.0 |
| 16.0.x | ^16.14.0 \|\| ^18.10.0 | >=4.9.3 <5.1.0 | ^6.5.3 \|\| ^7.4.0 |
-1
View File
@@ -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": { &hellip; },
"staging": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.development.ts"
},
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.staging.ts"
+16 -20
View File
@@ -106,7 +106,7 @@ Also, the later sections of this guide provide additional information on several
For applications new to SSR, the [Angular SSR Guide](guide/ssr) provides additional information regarding the setup process for adding SSR to an application.
For applications that are already using SSR, additional manual adjustments will be needed to update the application server to support the new integrated SSR capabilities.
For applications that are already using SSR, additional adjustments will be needed to update the application server to support the new integrated SSR capabilities.
The `application` builder now provides the integrated functionality for all of the following preexisting builders:
- `app-shell`
@@ -117,25 +117,23 @@ The `application` builder now provides the integrated functionality for all of t
The `ng update` process will automatically remove usages of the `@nguniversal` scope packages where some of these builders were previously located.
The new `@angular/ssr` package will also be automatically added and used with configuration and code being adjusted during the update.
The `@angular/ssr` package supports the `browser` builder as well as the `application` builder.
To convert from the separate SSR builders to the integrated capabilities of the `application` builder, there are several required manual steps.
However, as each application is different, there may be more application specific changes needed beyond these to complete the process.
To convert from the separate SSR builders to the integrated capabilities of the `application` builder, run the experimental `use-application-builder` migration.
1. Combine the options for the above mentioned SSR builders into the `application` builder options within the `angular.json` file.
The previously used builders and their target configurations can then be fully removed from the file.
2. Combine server TypeScript configuration from `tsconfig.server.json` into `tsconfig.app.json`.
The `types` and `files` options are typically the only setting that needs to be combined but others may be needed based on application specific customizations.
You should also add the TypeScript option `"esModuleInterop": true` to ensure `express` imports are [ESM compliant](#esm-default-imports-vs-namespace-imports).
The `tsconfig.server.json` can then be removed as it will no longer be used during builds.
3. Remove and/or update any `npm` scripts referencing the now removed builder targets.
The `ng build` and `ng serve` commands provide equivalent functionality when using the `application` builder.
4. Update application server code to remove Webpack specific elements.
5. Update application server code to use new bootstrapping and output directory structure.
An example of the changes for a v16 project that has been converted can be found [here](https://github.com/alan-agius4/angular-cli-use-application-builder/commit/1defdb93a7f508662bc427439e51505668bf84cd#diff-1ba718c1eb8aa39cd20c2562d92523068c734d75f54655e97d652b992d9b4259).
6. Remove any CommonJS assumptions in the application server code such as `require`, `__filename`, `__dirname`, or other constructs from the [CommonJS module scope](https://nodejs.org/api/modules.html#the-module-scope).
All application code should be ESM compatible.
This does not apply to third-party dependencies.
<docs-code language="shell">
In the future, a schematic will make this migration process easier for existing applications.
ng update @angular/cli --name use-application-builder
</docs-code>
The migration does the following:
* Converts existing `browser` or `browser-esbuild` target to `application`
* Removes any previous SSR builders (because `application` does that now).
* Updates configuration accordingly.
* Merges `tsconfig.server.json` with `tsconfig.app.json` and adds the TypeScript option `"esModuleInterop": true` to ensure `express` imports are [ESM compliant](#esm-default-imports-vs-namespace-imports).
* Updates application server code to use new bootstrapping and output directory structure.
HELPFUL: Remember to remove any CommonJS assumptions in the application server code such as `require`, `__filename`, `__dirname`, or other constructs from the [CommonJS module scope](https://nodejs.org/api/modules.html#the-module-scope). All application code should be ESM compatible. This does not apply to third-party dependencies.
## Executing a build
@@ -175,8 +173,6 @@ Several build options are not yet implemented but will be added in the future as
- [WASM imports](https://github.com/angular/angular-cli/issues/25102) -- WASM can still be loaded manually via [standard web APIs](https://developer.mozilla.org/en-US/docs/WebAssembly/Loading_and_running).
Building libraries with the new build system via `ng-packagr` is also not yet possible but library build support will be available in a future release.
## ESM default imports vs. namespace imports
TypeScript by default allows default exports to be imported as namespace imports and then used in call expressions.
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -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>

Some files were not shown because too many files have changed in this diff Show More