diff --git a/aio/content/guide/deprecations.md b/aio/content/guide/deprecations.md
index 7c33b7d2b8..7ead16e1e5 100644
--- a/aio/content/guide/deprecations.md
+++ b/aio/content/guide/deprecations.md
@@ -95,6 +95,7 @@ Tip: In the [API reference section](api) of this doc site, deprecated APIs are i
| [`ANALYZE_FOR_ENTRY_COMPONENTS`](api/core/ANALYZE_FOR_ENTRY_COMPONENTS) | none | v9 | See [`ANALYZE_FOR_ENTRY_COMPONENTS`](#entryComponents) |
| [`WrappedValue`](api/core/WrappedValue) | none | v10 | See [removing `WrappedValue`](#wrapped-value) |
| [`async`](api/core/testing/async) | [`waitForAsync`](api/core/testing/waitForAsync) | v11 | The `async` function from `@angular/core/testing` has been renamed to `waitForAsync` in order to avoid confusion with the native JavaScript `async` syntax. The existing function is deprecated and will be removed in a future version. |
+[ `ViewChildren.emitDistinctChangesOnly` / `ContentChildren.emitDistinctChangesOnly` | none (was part of [issue #40091](https://github.com/angular/angular/issues/40091)) ] | This is a temporary flag introduced as part of bugfix of [issue #40091](https://github.com/angular/angular/issues/40091) and will be removed. |
{@a testing}
### @angular/core/testing
diff --git a/packages/compiler-cli/ngcc/test/rendering/renderer_spec.ts b/packages/compiler-cli/ngcc/test/rendering/renderer_spec.ts
index b80b39b3a0..5ea2e0ce07 100644
--- a/packages/compiler-cli/ngcc/test/rendering/renderer_spec.ts
+++ b/packages/compiler-cli/ngcc/test/rendering/renderer_spec.ts
@@ -570,7 +570,7 @@ A.ɵdir = /*@__PURE__*/ ɵngcc0.ɵɵdefineDirective({ type: A, selectors: [["",
UndecoratedBase.ɵfac = function UndecoratedBase_Factory(t) { return new (t || UndecoratedBase)(); };
// TRANSPILED
UndecoratedBase.ɵdir = /*@__PURE__*/ ɵngcc0.ɵɵdefineDirective({ type: UndecoratedBase, viewQuery: function UndecoratedBase_Query(rf, ctx) { if (rf & 1) {
- ɵngcc0.ɵɵviewQuery(_c0, 3);
+ ɵngcc0.ɵɵviewQuery(_c0, 7);
} if (rf & 2) {
let _t;
ɵngcc0.ɵɵqueryRefresh(_t = ɵngcc0.ɵɵloadQuery()) && (ctx.test = _t.first);
diff --git a/packages/compiler-cli/src/ngtsc/annotations/src/directive.ts b/packages/compiler-cli/src/ngtsc/annotations/src/directive.ts
index 52f5a8b2bb..623935e23d 100644
--- a/packages/compiler-cli/src/ngtsc/annotations/src/directive.ts
+++ b/packages/compiler-cli/src/ngtsc/annotations/src/directive.ts
@@ -605,7 +605,7 @@ export function extractQueryMetadata(
if (typeof emitDistinctChangesOnlyValue !== 'boolean') {
throw createValueHasWrongTypeError(
emitDistinctChangesOnlyExpr, emitDistinctChangesOnlyValue,
- `@${name} options.emitDistinctChangesOnlys must be a boolean`);
+ `@${name} options.emitDistinctChangesOnly must be a boolean`);
}
emitDistinctChangesOnly = emitDistinctChangesOnlyValue;
}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/GOLDEN_PARTIAL.js
index 611b733f93..8f49e5621a 100644
--- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/GOLDEN_PARTIAL.js
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/GOLDEN_PARTIAL.js
@@ -32,7 +32,7 @@ import * as i0 from "@angular/core";
export class ViewQueryComponent {
}
ViewQueryComponent.ɵfac = function ViewQueryComponent_Factory(t) { return new (t || ViewQueryComponent)(); };
-ViewQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ViewQueryComponent, selector: "view-query-component", viewQueries: [{ propertyName: "someDir", first: true, predicate: SomeDirective, emitDistinctChangesOnly: false, descendants: true }, { propertyName: "someDirs", predicate: SomeDirective, emitDistinctChangesOnly: false, descendants: true }], ngImport: i0, template: `
+ViewQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ViewQueryComponent, selector: "view-query-component", viewQueries: [{ propertyName: "someDir", first: true, predicate: SomeDirective, descendants: true }, { propertyName: "someDirs", predicate: SomeDirective, descendants: true }], ngImport: i0, template: `
`, isInline: true, directives: [{ type: i0.forwardRef(function () { return SomeDirective; }), selector: "[someDir]" }] });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ViewQueryComponent, [{
@@ -88,7 +88,7 @@ import * as i0 from "@angular/core";
export class ViewQueryComponent {
}
ViewQueryComponent.ɵfac = function ViewQueryComponent_Factory(t) { return new (t || ViewQueryComponent)(); };
-ViewQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ViewQueryComponent, selector: "view-query-component", viewQueries: [{ propertyName: "myRef", first: true, predicate: ["myRef"], emitDistinctChangesOnly: false, descendants: true }, { propertyName: "myRefs", predicate: ["myRef1, myRef2, myRef3"], emitDistinctChangesOnly: false, descendants: true }], ngImport: i0, template: `
+ViewQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ViewQueryComponent, selector: "view-query-component", viewQueries: [{ propertyName: "myRef", first: true, predicate: ["myRef"], descendants: true }, { propertyName: "myRefs", predicate: ["myRef1, myRef2, myRef3"], descendants: true }], ngImport: i0, template: `
`, isInline: true });
@@ -170,7 +170,7 @@ import * as i0 from "@angular/core";
export class ViewQueryComponent {
}
ViewQueryComponent.ɵfac = function ViewQueryComponent_Factory(t) { return new (t || ViewQueryComponent)(); };
-ViewQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ViewQueryComponent, selector: "view-query-component", viewQueries: [{ propertyName: "someDir", first: true, predicate: SomeDirective, emitDistinctChangesOnly: false, descendants: true, static: true }, { propertyName: "foo", first: true, predicate: ["foo"], emitDistinctChangesOnly: false, descendants: true }], ngImport: i0, template: `
+ViewQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ViewQueryComponent, selector: "view-query-component", viewQueries: [{ propertyName: "someDir", first: true, predicate: SomeDirective, descendants: true, static: true }, { propertyName: "foo", first: true, predicate: ["foo"], descendants: true }], ngImport: i0, template: `
`, isInline: true, directives: [{ type: i0.forwardRef(function () { return SomeDirective; }), selector: "[someDir]" }] });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ViewQueryComponent, [{
@@ -252,7 +252,7 @@ import * as i0 from "@angular/core";
export class ViewQueryComponent {
}
ViewQueryComponent.ɵfac = function ViewQueryComponent_Factory(t) { return new (t || ViewQueryComponent)(); };
-ViewQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ViewQueryComponent, selector: "view-query-component", viewQueries: [{ propertyName: "myRef", first: true, predicate: ["myRef"], emitDistinctChangesOnly: false, descendants: true, read: TemplateRef }, { propertyName: "someDir", first: true, predicate: SomeDirective, emitDistinctChangesOnly: false, descendants: true, read: ElementRef }, { propertyName: "myRefs", predicate: ["myRef1, myRef2, myRef3"], emitDistinctChangesOnly: false, descendants: true, read: ElementRef }, { propertyName: "someDirs", predicate: SomeDirective, emitDistinctChangesOnly: false, descendants: true, read: TemplateRef }], ngImport: i0, template: `
+ViewQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ViewQueryComponent, selector: "view-query-component", viewQueries: [{ propertyName: "myRef", first: true, predicate: ["myRef"], descendants: true, read: TemplateRef }, { propertyName: "someDir", first: true, predicate: SomeDirective, descendants: true, read: ElementRef }, { propertyName: "myRefs", predicate: ["myRef1, myRef2, myRef3"], descendants: true, read: ElementRef }, { propertyName: "someDirs", predicate: SomeDirective, descendants: true, read: TemplateRef }], ngImport: i0, template: `
@@ -344,7 +344,7 @@ import * as i0 from "@angular/core";
export class ContentQueryComponent {
}
ContentQueryComponent.ɵfac = function ContentQueryComponent_Factory(t) { return new (t || ContentQueryComponent)(); };
-ContentQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ContentQueryComponent, selector: "content-query-component", queries: [{ propertyName: "someDir", first: true, predicate: SomeDirective, emitDistinctChangesOnly: false, descendants: true }, { propertyName: "someDirList", predicate: SomeDirective, emitDistinctChangesOnly: false }], ngImport: i0, template: `
+ContentQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ContentQueryComponent, selector: "content-query-component", queries: [{ propertyName: "someDir", first: true, predicate: SomeDirective, descendants: true }, { propertyName: "someDirList", predicate: SomeDirective }], ngImport: i0, template: `
`, isInline: true });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ContentQueryComponent, [{
@@ -423,7 +423,7 @@ import * as i0 from "@angular/core";
export class ContentQueryComponent {
}
ContentQueryComponent.ɵfac = function ContentQueryComponent_Factory(t) { return new (t || ContentQueryComponent)(); };
-ContentQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ContentQueryComponent, selector: "content-query-component", queries: [{ propertyName: "myRef", first: true, predicate: ["myRef"], emitDistinctChangesOnly: false, descendants: true }, { propertyName: "myRefs", predicate: ["myRef1, myRef2, myRef3"], emitDistinctChangesOnly: false }], ngImport: i0, template: `
+ContentQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ContentQueryComponent, selector: "content-query-component", queries: [{ propertyName: "myRef", first: true, predicate: ["myRef"], descendants: true }, { propertyName: "myRefs", predicate: ["myRef1, myRef2, myRef3"] }], ngImport: i0, template: `
`, isInline: true });
@@ -505,7 +505,7 @@ import * as i0 from "@angular/core";
export class ContentQueryComponent {
}
ContentQueryComponent.ɵfac = function ContentQueryComponent_Factory(t) { return new (t || ContentQueryComponent)(); };
-ContentQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ContentQueryComponent, selector: "content-query-component", queries: [{ propertyName: "someDir", first: true, predicate: SomeDirective, emitDistinctChangesOnly: false, descendants: true, static: true }, { propertyName: "foo", first: true, predicate: ["foo"], emitDistinctChangesOnly: false, descendants: true }], ngImport: i0, template: `
+ContentQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ContentQueryComponent, selector: "content-query-component", queries: [{ propertyName: "someDir", first: true, predicate: SomeDirective, descendants: true, static: true }, { propertyName: "foo", first: true, predicate: ["foo"], descendants: true }], ngImport: i0, template: `
`, isInline: true });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ContentQueryComponent, [{
@@ -610,7 +610,7 @@ import * as i0 from "@angular/core";
export class ContentQueryComponent {
}
ContentQueryComponent.ɵfac = function ContentQueryComponent_Factory(t) { return new (t || ContentQueryComponent)(); };
-ContentQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ContentQueryComponent, selector: "content-query-component", queries: [{ propertyName: "myRef", first: true, predicate: ["myRef"], emitDistinctChangesOnly: false, descendants: true, read: TemplateRef }, { propertyName: "someDir", first: true, predicate: SomeDirective, emitDistinctChangesOnly: false, descendants: true, read: ElementRef }, { propertyName: "myRefs", predicate: ["myRef1, myRef2, myRef3"], emitDistinctChangesOnly: false, read: ElementRef }, { propertyName: "someDirs", predicate: SomeDirective, emitDistinctChangesOnly: false, read: TemplateRef }], ngImport: i0, template: `
+ContentQueryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: ContentQueryComponent, selector: "content-query-component", queries: [{ propertyName: "myRef", first: true, predicate: ["myRef"], descendants: true, read: TemplateRef }, { propertyName: "someDir", first: true, predicate: SomeDirective, descendants: true, read: ElementRef }, { propertyName: "myRefs", predicate: ["myRef1, myRef2, myRef3"], read: ElementRef }, { propertyName: "someDirs", predicate: SomeDirective, read: TemplateRef }], ngImport: i0, template: `
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/content_query_for_directive.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/content_query_for_directive.js
index a06fbaeeaf..d0c83d7933 100644
--- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/content_query_for_directive.js
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/content_query_for_directive.js
@@ -3,8 +3,8 @@ ContentQueryComponent.ɵcmp = /*@__PURE__*/ $r3$.ɵɵdefineComponent({
selectors: [["content-query-component"]],
contentQueries: function ContentQueryComponent_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) {
- $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 1);
- $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 0);
+ $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 5);
+ $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 4);
}
if (rf & 2) {
let $tmp$;
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/content_query_for_local_ref.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/content_query_for_local_ref.js
index e4a8fa784f..3a78c30a1b 100644
--- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/content_query_for_local_ref.js
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/content_query_for_local_ref.js
@@ -5,8 +5,8 @@ ContentQueryComponent.ɵcmp = /*@__PURE__*/ $r3$.ɵɵdefineComponent({
// ...
contentQueries: function ContentQueryComponent_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) {
- $r3$.ɵɵcontentQuery(dirIndex, $e0_attrs$, 1);
- $r3$.ɵɵcontentQuery(dirIndex, $e1_attrs$, 0);
+ $r3$.ɵɵcontentQuery(dirIndex, $e0_attrs$, 5);
+ $r3$.ɵɵcontentQuery(dirIndex, $e1_attrs$, 4);
}
if (rf & 2) {
let $tmp$;
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/content_query_read_token.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/content_query_read_token.js
index 654977fd1a..6de5bc94e3 100644
--- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/content_query_read_token.js
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/content_query_read_token.js
@@ -5,10 +5,10 @@ ContentQueryComponent.ɵcmp = /*@__PURE__*/ $r3$.ɵɵdefineComponent({
// ...
contentQueries: function ContentQueryComponent_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) {
- $r3$.ɵɵcontentQuery(dirIndex, $e0_attrs$, 1, TemplateRef);
- $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 1, ElementRef);
- $r3$.ɵɵcontentQuery(dirIndex, $e1_attrs$, 0, ElementRef);
- $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 0, TemplateRef);
+ $r3$.ɵɵcontentQuery(dirIndex, $e0_attrs$, 5, TemplateRef);
+ $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 5, ElementRef);
+ $r3$.ɵɵcontentQuery(dirIndex, $e1_attrs$, 4, ElementRef);
+ $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 4, TemplateRef);
}
if (rf & 2) {
let $tmp$;
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/static_content_query.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/static_content_query.js
index 92e99edfd6..051d73112e 100644
--- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/static_content_query.js
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/static_content_query.js
@@ -4,8 +4,8 @@ ContentQueryComponent.ɵcmp = /*@__PURE__*/ $r3$.ɵɵdefineComponent({
contentQueries: function ContentQueryComponent_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) {
$r3$.ɵɵcontentQuery(
- dirIndex, SomeDirective, __QueryFlags.isStatic__|__QueryFlags.descendants__);
- $r3$.ɵɵcontentQuery(dirIndex, $ref0$, 1);
+ dirIndex, SomeDirective, __QueryFlags.isStatic__|__QueryFlags.descendants__|__QueryFlags.emitDistinctChangesOnly__);
+ $r3$.ɵɵcontentQuery(dirIndex, $ref0$, 5);
}
if (rf & 2) {
let $tmp$;
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/static_view_query.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/static_view_query.js
index 878e33d922..36c7118540 100644
--- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/static_view_query.js
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/static_view_query.js
@@ -5,8 +5,8 @@ ViewQueryComponent.ɵcmp = /*@__PURE__*/ $r3$.ɵɵdefineComponent({
selectors: [["view-query-component"]],
viewQuery: function ViewQueryComponent_Query(rf, ctx) {
if (rf & 1) {
- $r3$.ɵɵviewQuery(SomeDirective, __QueryFlags.isStatic__|__QueryFlags.descendants__);
- $r3$.ɵɵviewQuery($refs$, 1);
+ $r3$.ɵɵviewQuery(SomeDirective, __QueryFlags.isStatic__|__QueryFlags.descendants__|__QueryFlags.emitDistinctChangesOnly__);
+ $r3$.ɵɵviewQuery($refs$, 5);
}
if (rf & 2) {
let $tmp$;
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/view_query_for_directive.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/view_query_for_directive.js
index c674a30fc5..13502a9a5a 100644
--- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/view_query_for_directive.js
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/view_query_for_directive.js
@@ -3,8 +3,8 @@ ViewQueryComponent.ɵcmp = /*@__PURE__*/ $r3$.ɵɵdefineComponent({
selectors: [["view-query-component"]],
viewQuery: function ViewQueryComponent_Query(rf, ctx) {
if (rf & 1) {
- $r3$.ɵɵviewQuery(SomeDirective, 1);
- $r3$.ɵɵviewQuery(SomeDirective, 1);
+ $r3$.ɵɵviewQuery(SomeDirective, 5);
+ $r3$.ɵɵviewQuery(SomeDirective, 5);
}
if (rf & 2) {
let $tmp$;
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/view_query_for_local_ref.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/view_query_for_local_ref.js
index a2b233cf80..d8770b0d9b 100644
--- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/view_query_for_local_ref.js
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/view_query_for_local_ref.js
@@ -5,8 +5,8 @@ ViewQueryComponent.ɵcmp = /*@__PURE__*/ $r3$.ɵɵdefineComponent({
// ...
viewQuery: function ViewQueryComponent_Query(rf, ctx) {
if (rf & 1) {
- $r3$.ɵɵviewQuery($e0_attrs$, 1);
- $r3$.ɵɵviewQuery($e1_attrs$, 1);
+ $r3$.ɵɵviewQuery($e0_attrs$, 5);
+ $r3$.ɵɵviewQuery($e1_attrs$, 5);
}
if (rf & 2) {
let $tmp$;
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/view_query_read_token.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/view_query_read_token.js
index 2e28dd0f0e..247b2fd807 100644
--- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/view_query_read_token.js
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/view_query_read_token.js
@@ -5,10 +5,10 @@ ViewQueryComponent.ɵcmp = /*@__PURE__*/ $r3$.ɵɵdefineComponent({
// ...
viewQuery: function ViewQueryComponent_Query(rf, ctx) {
if (rf & 1) {
- $r3$.ɵɵviewQuery($e0_attrs$, 1, TemplateRef);
- $r3$.ɵɵviewQuery(SomeDirective, 1, ElementRef);
- $r3$.ɵɵviewQuery($e1_attrs$, 1, ElementRef);
- $r3$.ɵɵviewQuery(SomeDirective, 1, TemplateRef);
+ $r3$.ɵɵviewQuery($e0_attrs$, 5, TemplateRef);
+ $r3$.ɵɵviewQuery(SomeDirective, 5, ElementRef);
+ $r3$.ɵɵviewQuery($e1_attrs$, 5, ElementRef);
+ $r3$.ɵɵviewQuery(SomeDirective, 5, TemplateRef);
}
if (rf & 2) {
let $tmp$;
diff --git a/packages/compiler-cli/test/compliance_old/r3_compiler_compliance_spec.ts b/packages/compiler-cli/test/compliance_old/r3_compiler_compliance_spec.ts
index 50f0b4854d..c2d68d83d3 100644
--- a/packages/compiler-cli/test/compliance_old/r3_compiler_compliance_spec.ts
+++ b/packages/compiler-cli/test/compliance_old/r3_compiler_compliance_spec.ts
@@ -1636,8 +1636,8 @@ describe('compiler compliance', () => {
selectors: [["view-query-component"]],
viewQuery: function ViewQueryComponent_Query(rf, ctx) {
if (rf & 1) {
- $r3$.ɵɵviewQuery(SomeDirective, 1);
- $r3$.ɵɵviewQuery(SomeDirective, 1);
+ $r3$.ɵɵviewQuery(SomeDirective, 5);
+ $r3$.ɵɵviewQuery(SomeDirective, 5);
}
if (rf & 2) {
let $tmp$;
@@ -1695,8 +1695,8 @@ describe('compiler compliance', () => {
…
viewQuery: function ViewQueryComponent_Query(rf, ctx) {
if (rf & 1) {
- $r3$.ɵɵviewQuery($e0_attrs$, 1);
- $r3$.ɵɵviewQuery($e1_attrs$, 1);
+ $r3$.ɵɵviewQuery($e0_attrs$, 5);
+ $r3$.ɵɵviewQuery($e1_attrs$, 5);
}
if (rf & 2) {
let $tmp$;
@@ -1746,8 +1746,8 @@ describe('compiler compliance', () => {
selectors: [["view-query-component"]],
viewQuery: function ViewQueryComponent_Query(rf, ctx) {
if (rf & 1) {
- $r3$.ɵɵviewQuery(SomeDirective, 3);
- $r3$.ɵɵviewQuery($refs$, 1);
+ $r3$.ɵɵviewQuery(SomeDirective, 7);
+ $r3$.ɵɵviewQuery($refs$, 5);
}
if (rf & 2) {
let $tmp$;
@@ -1810,10 +1810,10 @@ describe('compiler compliance', () => {
…
viewQuery: function ViewQueryComponent_Query(rf, ctx) {
if (rf & 1) {
- $r3$.ɵɵviewQuery($e0_attrs$, 1, TemplateRef);
- $r3$.ɵɵviewQuery(SomeDirective, 1, ElementRef);
- $r3$.ɵɵviewQuery($e1_attrs$, 1, ElementRef);
- $r3$.ɵɵviewQuery(SomeDirective, 1, TemplateRef);
+ $r3$.ɵɵviewQuery($e0_attrs$, 5, TemplateRef);
+ $r3$.ɵɵviewQuery(SomeDirective, 5, ElementRef);
+ $r3$.ɵɵviewQuery($e1_attrs$, 5, ElementRef);
+ $r3$.ɵɵviewQuery(SomeDirective, 5, TemplateRef);
}
if (rf & 2) {
let $tmp$;
@@ -1873,8 +1873,8 @@ describe('compiler compliance', () => {
selectors: [["content-query-component"]],
contentQueries: function ContentQueryComponent_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) {
- $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 1);
- $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 0);
+ $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 5);
+ $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 4);
}
if (rf & 2) {
let $tmp$;
@@ -1933,8 +1933,8 @@ describe('compiler compliance', () => {
…
contentQueries: function ContentQueryComponent_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) {
- $r3$.ɵɵcontentQuery(dirIndex, $e0_attrs$, 1);
- $r3$.ɵɵcontentQuery(dirIndex, $e1_attrs$, 0);
+ $r3$.ɵɵcontentQuery(dirIndex, $e0_attrs$, 5);
+ $r3$.ɵɵcontentQuery(dirIndex, $e1_attrs$, 4);
}
if (rf & 2) {
let $tmp$;
@@ -1992,8 +1992,8 @@ describe('compiler compliance', () => {
selectors: [["content-query-component"]],
contentQueries: function ContentQueryComponent_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) {
- $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 3);
- $r3$.ɵɵcontentQuery(dirIndex, $ref0$, 1);
+ $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 7);
+ $r3$.ɵɵcontentQuery(dirIndex, $ref0$, 5);
}
if (rf & 2) {
let $tmp$;
@@ -2057,10 +2057,10 @@ describe('compiler compliance', () => {
…
contentQueries: function ContentQueryComponent_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) {
- $r3$.ɵɵcontentQuery(dirIndex, $e0_attrs$, 1, TemplateRef);
- $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 1, ElementRef);
- $r3$.ɵɵcontentQuery(dirIndex, $e1_attrs$, 0, ElementRef);
- $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 0, TemplateRef);
+ $r3$.ɵɵcontentQuery(dirIndex, $e0_attrs$, 5, TemplateRef);
+ $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 5, ElementRef);
+ $r3$.ɵɵcontentQuery(dirIndex, $e1_attrs$, 4, ElementRef);
+ $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, 4, TemplateRef);
}
if (rf & 2) {
let $tmp$;
diff --git a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts
index 8ccdfd27ea..9ad05bbc82 100644
--- a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts
+++ b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts
@@ -3133,10 +3133,10 @@ function allTests(os: string) {
expect(jsContents).toMatch(varRegExp('test1'));
expect(jsContents).toMatch(varRegExp('test2'));
expect(jsContents).toMatch(varRegExp('accessor'));
- // match `i0.ɵɵcontentQuery(dirIndex, _c1, 1, TemplateRef)`
- expect(jsContents).toMatch(contentQueryRegExp('\\w+', 1, 'TemplateRef'));
- // match `i0.ɵɵviewQuery(_c2, 1, null)`
- expect(jsContents).toMatch(viewQueryRegExp('\\w+', 1));
+ // match `i0.ɵɵcontentQuery(dirIndex, _c1, 5, TemplateRef)`
+ expect(jsContents).toMatch(contentQueryRegExp('\\w+', 5, 'TemplateRef'));
+ // match `i0.ɵɵviewQuery(_c2, 5, null)`
+ expect(jsContents).toMatch(viewQueryRegExp('\\w+', 5));
});
it('should generate queries for directives', () => {
@@ -3165,14 +3165,14 @@ function allTests(os: string) {
expect(jsContents).toMatch(varRegExp('test1'));
expect(jsContents).toMatch(varRegExp('test2'));
expect(jsContents).toMatch(varRegExp('accessor'));
- // match `i0.ɵɵcontentQuery(dirIndex, _c1, 1, TemplateRef)`
- expect(jsContents).toMatch(contentQueryRegExp('\\w+', 1, 'TemplateRef'));
+ // match `i0.ɵɵcontentQuery(dirIndex, _c1, 5, TemplateRef)`
+ expect(jsContents).toMatch(contentQueryRegExp('\\w+', 5, 'TemplateRef'));
- // match `i0.ɵɵviewQuery(_c2, 1)`
+ // match `i0.ɵɵviewQuery(_c2, 5)`
// Note that while ViewQuery doesn't necessarily make sense on a directive,
// because it doesn't have a view, we still need to handle it because a component
// could extend the directive.
- expect(jsContents).toMatch(viewQueryRegExp('\\w+', 1));
+ expect(jsContents).toMatch(viewQueryRegExp('\\w+', 5));
});
it('should handle queries that use forwardRef', () => {
@@ -3194,13 +3194,13 @@ function allTests(os: string) {
env.driveMain();
const jsContents = env.getContents('test.js');
- // match `i0.ɵɵcontentQuery(dirIndex, TemplateRef, 1, null)`
- expect(jsContents).toMatch(contentQueryRegExp('TemplateRef', 1));
- // match `i0.ɵɵcontentQuery(dirIndex, ViewContainerRef, 1, null)`
- expect(jsContents).toMatch(contentQueryRegExp('ViewContainerRef', 1));
- // match `i0.ɵɵcontentQuery(dirIndex, _c0, 1, null)`
+ // match `i0.ɵɵcontentQuery(dirIndex, TemplateRef, 5, null)`
+ expect(jsContents).toMatch(contentQueryRegExp('TemplateRef', 5));
+ // match `i0.ɵɵcontentQuery(dirIndex, ViewContainerRef, 5, null)`
+ expect(jsContents).toMatch(contentQueryRegExp('ViewContainerRef', 5));
+ // match `i0.ɵɵcontentQuery(dirIndex, _c0, 5, null)`
expect(jsContents).toContain('_c0 = ["parens"];');
- expect(jsContents).toMatch(contentQueryRegExp('_c0', 1));
+ expect(jsContents).toMatch(contentQueryRegExp('_c0', 5));
});
it('should handle queries that use an InjectionToken', () => {
@@ -3221,10 +3221,10 @@ function allTests(os: string) {
env.driveMain();
const jsContents = env.getContents('test.js');
- // match `i0.ɵɵviewQuery(TOKEN, 1, null)`
- expect(jsContents).toMatch(viewQueryRegExp('TOKEN', 1));
- // match `i0.ɵɵcontentQuery(dirIndex, TOKEN, 1, null)`
- expect(jsContents).toMatch(contentQueryRegExp('TOKEN', 1));
+ // match `i0.ɵɵviewQuery(TOKEN, 5, null)`
+ expect(jsContents).toMatch(viewQueryRegExp('TOKEN', 5));
+ // match `i0.ɵɵcontentQuery(dirIndex, TOKEN, 5, null)`
+ expect(jsContents).toMatch(contentQueryRegExp('TOKEN', 5));
});
it('should compile expressions that write keys', () => {
diff --git a/packages/compiler/src/core.ts b/packages/compiler/src/core.ts
index a588b90165..a0b07718c3 100644
--- a/packages/compiler/src/core.ts
+++ b/packages/compiler/src/core.ts
@@ -28,9 +28,8 @@ export const createAttribute =
makeMetadataFactory('Attribute', (attributeName: string) => ({attributeName}));
// Stores the default value of `emitDistinctChangesOnly` when the `emitDistinctChangesOnly` is not
-// explicitly set. This value will be changed to `true` in v12.
-// TODO(misko): switch the default in v12 to `true`. See: packages/core/src/metadata/di.ts
-export const emitDistinctChangesOnlyDefaultValue = false;
+// explicitly set.
+export const emitDistinctChangesOnlyDefaultValue = true;
export interface Query {
diff --git a/packages/compiler/src/render3/partial/api.ts b/packages/compiler/src/render3/partial/api.ts
index 383827a8e9..d64931985e 100644
--- a/packages/compiler/src/render3/partial/api.ts
+++ b/packages/compiler/src/render3/partial/api.ts
@@ -237,9 +237,6 @@ export interface R3DeclareQueryMetadata {
/**
* True to only fire changes if there are underlying changes to the query.
*/
- // TODO(misko): This will become `true` be default in v12. `QueryList.changes` would fire even if
- // no changes to the query list were detected. This is not ideal, as changes should only fire if
- // the `QueryList` actually materially changed.
emitDistinctChangesOnly?: boolean;
/**
diff --git a/packages/compiler/src/render3/partial/directive.ts b/packages/compiler/src/render3/partial/directive.ts
index 8b5a854585..0947ca46cd 100644
--- a/packages/compiler/src/render3/partial/directive.ts
+++ b/packages/compiler/src/render3/partial/directive.ts
@@ -87,9 +87,11 @@ function compileQuery(query: R3QueryMetadata): o.LiteralMapExpr {
meta.set(
'predicate', Array.isArray(query.predicate) ? asLiteral(query.predicate) : query.predicate);
if (!query.emitDistinctChangesOnly) {
- // `emitDistinctChangesOnly` is special because in future we expect it to be `true`. For this
- // reason the absence should be interpreted as `true`.
+ // `emitDistinctChangesOnly` is special because we expect it to be `true`.
+ // Therefore we explicitly emit the field, and explicitly place it only when it's `false`.
meta.set('emitDistinctChangesOnly', o.literal(false));
+ } else {
+ // The linker will assume that an absent `emitDistinctChangesOnly` flag is by default `true`.
}
if (query.descendants) {
meta.set('descendants', o.literal(true));
diff --git a/packages/core/src/linker/query_list.ts b/packages/core/src/linker/query_list.ts
index c2bdada5ba..26c12e5b24 100644
--- a/packages/core/src/linker/query_list.ts
+++ b/packages/core/src/linker/query_list.ts
@@ -62,8 +62,7 @@ export class QueryList implements Iterable {
/**
* @param emitDistinctChangesOnly Whether `QueryList.changes` should fire only when actual change
* has occurred. Or if it should fire when query is recomputed. (recomputing could resolve in
- * the same result) This is set to `false` for backwards compatibility but will be changed to
- * true in v12.
+ * the same result)
*/
constructor(private _emitDistinctChangesOnly: boolean = false) {
// This function should be declared on the prototype, but doing so there will cause the class
diff --git a/packages/core/src/metadata/di.ts b/packages/core/src/metadata/di.ts
index e33d78f3bf..1a793bbde4 100644
--- a/packages/core/src/metadata/di.ts
+++ b/packages/core/src/metadata/di.ts
@@ -107,9 +107,8 @@ export interface Query {
}
// Stores the default value of `emitDistinctChangesOnly` when the `emitDistinctChangesOnly` is not
-// explicitly set. This value will be changed to `true` in v12.
-// TODO(misko): switch the default in v12 to `true`. See: packages/compiler/src/core.ts
-export const emitDistinctChangesOnlyDefaultValue = false;
+// explicitly set.
+export const emitDistinctChangesOnlyDefaultValue = true;
/**
@@ -148,8 +147,10 @@ export interface ContentChildrenDecorator {
* * **selector** - The directive type or the name used for querying.
* * **descendants** - True to include all descendants, otherwise include only direct children.
* * **emitDistinctChangesOnly** - The ` QueryList#changes` observable will emit new values only
- * if the QueryList result has changed. The default value will change from `false` to `true` in
- * v12. When `false` the `changes` observable might emit even if the QueryList has not changed.
+ * if the QueryList result has changed. When `false` the `changes` observable might emit even
+ * if the QueryList has not changed.
+ * ** Note: *** This config option is **deprecated**, it will be permanently set to `true` and
+ * removed in future versions of Angular.
* * **read** - Used to read a different token from the queried elements.
*
* @usageNotes
@@ -287,8 +288,10 @@ export interface ViewChildrenDecorator {
* * **selector** - The directive type or the name used for querying.
* * **read** - Used to read a different token from the queried elements.
* * **emitDistinctChangesOnly** - The ` QueryList#changes` observable will emit new values only
- * if the QueryList result has changed. The default value will change from `false` to `true` in
- * v12. When `false` the `changes` observable might emit even if the QueryList has not changed.
+ * if the QueryList result has changed. When `false` the `changes` observable might emit even
+ * if the QueryList has not changed.
+ * ** Note: *** This config option is **deprecated**, it will be permanently set to `true` and
+ * removed in future versions of Angular.
*
* @usageNotes
*
diff --git a/packages/core/test/acceptance/query_spec.ts b/packages/core/test/acceptance/query_spec.ts
index 82da5b20e3..97de093d80 100644
--- a/packages/core/test/acceptance/query_spec.ts
+++ b/packages/core/test/acceptance/query_spec.ts
@@ -1257,11 +1257,8 @@ describe('query logic', () => {
* - systematically detach and insert a view - this would result in unnecessary processing
* when the previous and new indexes for the move operation are the same;
* - detect the situation where the indexes are the same and do no processing in such case.
- *
- * This tests asserts on the implementation choices done by the VE (detach and insert) so we
- * can replicate the same behavior in ivy.
*/
- it('should notify on changes when a given view is removed and re-inserted at the same index',
+ it('should NOT notify on changes when a given view is removed and re-inserted at the same index',
() => {
@Component({
selector: 'test-comp',
@@ -1298,7 +1295,7 @@ describe('query logic', () => {
vc.move(viewRef, 0);
fixture.detectChanges();
expect(queryList.length).toBe(1);
- expect(fixture.componentInstance.queryListNotificationCounter).toBe(2);
+ expect(fixture.componentInstance.queryListNotificationCounter).toBe(1);
});
it('should support a mix of content queries from the declaration and embedded view', () => {