Skip to content

Commit e95ef2c

Browse files
feat(core): expose queries as signals (angular#54283)
This commit exposes authoring functions for queries as signals thus making those generally available. PR Close angular#54283
1 parent 0d4e983 commit e95ef2c

File tree

20 files changed

+86
-79
lines changed

20 files changed

+86
-79
lines changed

goldens/circular-deps/packages.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,6 @@
2020
"packages/core/src/change_detection/change_detector_ref.ts",
2121
"packages/core/src/render3/view_ref.ts"
2222
],
23-
[
24-
"packages/core/src/change_detection/change_detector_ref.ts",
25-
"packages/core/src/render3/view_ref.ts",
26-
"packages/core/src/linker/view_ref.ts"
27-
],
2823
[
2924
"packages/core/src/change_detection/differs/default_iterable_differ.ts",
3025
"packages/core/src/change_detection/differs/iterable_differs.ts"

goldens/public-api/core/index.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,9 @@ export type ContentChild = Query;
322322
// @public
323323
export const ContentChild: ContentChildDecorator;
324324

325+
// @public
326+
export const contentChild: ContentChildFunction;
327+
325328
// @public
326329
export interface ContentChildDecorator {
327330
(selector: ProviderToken<unknown> | Function | string, opts?: {
@@ -337,12 +340,44 @@ export interface ContentChildDecorator {
337340
}): ContentChild;
338341
}
339342

343+
// @public
344+
export interface ContentChildFunction {
345+
<LocatorT>(locator: ProviderToken<LocatorT> | string, opts?: {
346+
descendants?: boolean;
347+
}): Signal<LocatorT | undefined>;
348+
// (undocumented)
349+
<LocatorT, ReadT>(locator: ProviderToken<LocatorT> | string, opts: {
350+
descendants?: boolean;
351+
read: ProviderToken<ReadT>;
352+
}): Signal<ReadT | undefined>;
353+
required: {
354+
<LocatorT>(locator: ProviderToken<LocatorT> | string, opts?: {
355+
descendants?: boolean;
356+
}): Signal<LocatorT>;
357+
<LocatorT, ReadT>(locator: ProviderToken<LocatorT> | string, opts: {
358+
descendants?: boolean;
359+
read: ProviderToken<ReadT>;
360+
}): Signal<ReadT>;
361+
};
362+
}
363+
340364
// @public
341365
export type ContentChildren = Query;
342366

343367
// @public
344368
export const ContentChildren: ContentChildrenDecorator;
345369

370+
// @public (undocumented)
371+
export function contentChildren<LocatorT>(locator: ProviderToken<LocatorT> | string, opts?: {
372+
descendants?: boolean;
373+
}): Signal<ReadonlyArray<LocatorT>>;
374+
375+
// @public (undocumented)
376+
export function contentChildren<LocatorT, ReadT>(locator: ProviderToken<LocatorT> | string, opts: {
377+
descendants?: boolean;
378+
read: ProviderToken<ReadT>;
379+
}): Signal<ReadonlyArray<ReadT>>;
380+
346381
// @public
347382
export interface ContentChildrenDecorator {
348383
(selector: ProviderToken<unknown> | Function | string, opts?: {
@@ -1598,6 +1633,9 @@ export type ViewChild = Query;
15981633
// @public
15991634
export const ViewChild: ViewChildDecorator;
16001635

1636+
// @public
1637+
export const viewChild: ViewChildFunction;
1638+
16011639
// @public
16021640
export interface ViewChildDecorator {
16031641
(selector: ProviderToken<unknown> | Function | string, opts?: {
@@ -1611,12 +1649,35 @@ export interface ViewChildDecorator {
16111649
}): ViewChild;
16121650
}
16131651

1652+
// @public
1653+
export interface ViewChildFunction {
1654+
<LocatorT>(locator: ProviderToken<LocatorT> | string): Signal<LocatorT | undefined>;
1655+
// (undocumented)
1656+
<LocatorT, ReadT>(locator: ProviderToken<LocatorT> | string, opts: {
1657+
read: ProviderToken<ReadT>;
1658+
}): Signal<ReadT | undefined>;
1659+
required: {
1660+
<LocatorT>(locator: ProviderToken<LocatorT> | string): Signal<LocatorT>;
1661+
<LocatorT, ReadT>(locator: ProviderToken<LocatorT> | string, opts: {
1662+
read: ProviderToken<ReadT>;
1663+
}): Signal<ReadT>;
1664+
};
1665+
}
1666+
16141667
// @public
16151668
export type ViewChildren = Query;
16161669

16171670
// @public
16181671
export const ViewChildren: ViewChildrenDecorator;
16191672

1673+
// @public (undocumented)
1674+
export function viewChildren<LocatorT>(locator: ProviderToken<LocatorT> | string): Signal<ReadonlyArray<LocatorT>>;
1675+
1676+
// @public (undocumented)
1677+
export function viewChildren<LocatorT, ReadT>(locator: ProviderToken<LocatorT> | string, opts: {
1678+
read: ProviderToken<ReadT>;
1679+
}): Signal<ReadonlyArray<ReadT>>;
1680+
16201681
// @public
16211682
export interface ViewChildrenDecorator {
16221683
(selector: ProviderToken<unknown> | Function | string, opts?: {

packages/core/src/authoring.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ export {InputFunction} from './authoring/input/input';
1313
export {InputOptions, InputOptionsWithoutTransform, InputOptionsWithTransform, InputSignal, InputSignalWithTransform, ɵINPUT_SIGNAL_BRAND_WRITE_TYPE} from './authoring/input/input_signal';
1414
export {ɵUnwrapDirectiveSignalInputs} from './authoring/input/input_type_checking';
1515
export {output as ɵoutput, OutputEmitter as ɵOutputEmitter, OutputOptions as ɵOutputOptions} from './authoring/output';
16+
export {ContentChildFunction, ViewChildFunction} from './authoring/queries';

packages/core/src/authoring/queries.ts

Lines changed: 1 addition & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {ProviderToken} from '../di';
9+
import {ProviderToken} from '../di/provider_token';
1010
import {createMultiResultQuerySignalFn, createSingleResultOptionalQuerySignalFn, createSingleResultRequiredQuerySignalFn} from '../render3/query_reactive';
1111
import {Signal} from '../render3/reactivity/api';
1212

@@ -34,18 +34,6 @@ export interface ViewChildFunction {
3434
* Initializes a view child query. Consider using `viewChild.required` for queries that should
3535
* always match.
3636
*
37-
* @usageNotes
38-
* Create a child query in your component by declaring a
39-
* class field and initializing it with the `viewChild()` function.
40-
*
41-
* ```ts
42-
* @Component({template: '<div #el></div><my-component #cmp />'})
43-
* export class TestComponent {
44-
* divEl = viewChild<ElementRef>('el'); // Signal<ElementRef|undefined>
45-
* cmp = viewChild(MyComponent); // Signal<MyComponent|undefined>
46-
* }
47-
* ```
48-
*
4937
* @developerPreview
5038
*/
5139
<LocatorT>(locator: ProviderToken<LocatorT>|string): Signal<LocatorT|undefined>;
@@ -55,18 +43,6 @@ export interface ViewChildFunction {
5543
/**
5644
* Initializes a view child query that is expected to always match an element.
5745
*
58-
* @usageNotes
59-
* Create a required child query in your component by declaring a
60-
* class field and initializing it with the `viewChild()` function.
61-
*
62-
* ```ts
63-
* @Component({template: '<div #el></div><my-component #cmp />'})
64-
* export class TestComponent {
65-
* divElRequired = viewChild.required<ElementRef>('el'); // Signal<ElementRef>
66-
* cmpRequired = viewChild.required(MyComponent); // Signal<MyComponent>
67-
* }
68-
* ```
69-
*
7046
* @developerPreview
7147
*/
7248
required: {
@@ -160,18 +136,6 @@ export interface ContentChildFunction {
160136
* Initializes a content child query.
161137
*
162138
* Consider using `contentChild.required` for queries that should always match.
163-
*
164-
* @usageNotes
165-
* Create a child query in your component by declaring a
166-
* class field and initializing it with the `contentChild()` function.
167-
*
168-
* ```ts
169-
* @Component({...})
170-
* export class TestComponent {
171-
* headerEl = contentChild<ElementRef>('h'); // Signal<ElementRef|undefined>
172-
* header = contentChild(MyHeader); // Signal<MyHeader|undefined>
173-
* }
174-
* ```
175139
* @developerPreview
176140
*/
177141
<LocatorT>(locator: ProviderToken<LocatorT>|string, opts?: {descendants?: boolean}):
@@ -183,17 +147,6 @@ export interface ContentChildFunction {
183147
/**
184148
* Initializes a content child query that is always expected to match.
185149
*
186-
* @usageNotes
187-
* Create a child query in your component by declaring a
188-
* class field and initializing it with the `contentChild()` function.
189-
*
190-
* ```ts
191-
* @Component({...})
192-
* export class TestComponent {
193-
* headerElElRequired = contentChild.required<ElementRef>('h'); // Signal<ElementRef>
194-
* headerRequired = contentChild.required(MyHeader); // Signal<MyHeader>
195-
* }
196-
* ```
197150
* @developerPreview
198151
*/
199152
required: {

packages/core/src/core.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
*/
1414

1515
export * from './authoring';
16-
// Input is exported separately as this file is exempted from JSCompiler's
17-
// conformance requirement for inferred const exports.
18-
// See: https://docs.google.com/document/d/1RXb1wYwsbJotO1KBgSDsAtKpduGmIHod9ADxuXcAvV4/edit?tab=t.0
16+
// Input and query authoring functions are exported separately as this file is exempted from
17+
// JSCompiler's conformance requirement for inferred const exports. See:
18+
// https://docs.google.com/document/d/1RXb1wYwsbJotO1KBgSDsAtKpduGmIHod9ADxuXcAvV4/edit?tab=t.0
1919
export {input} from './authoring/input/input';
20+
export {contentChild, contentChildren, viewChild, viewChildren} from './authoring/queries';
2021

2122
export * from './metadata';
2223
export * from './version';

packages/core/src/render3/instructions/queries_signals.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99

10-
import {ProviderToken} from '../../di';
10+
import {ProviderToken} from '../../di/provider_token';
1111
import {QueryFlags} from '../interfaces/query';
1212
import {createContentQuery, createViewQuery} from '../query';
1313
import {bindQueryToSignal} from '../query_reactive';

packages/core/test/acceptance/authoring/signal_queries_spec.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,12 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
// TODO: update imports
10-
import {Component, computed} from '@angular/core';
11-
import {viewChild} from '@angular/core/src/authoring/queries';
12-
import {getComponentDef} from '@angular/core/src/render3/definition';
9+
import {Component, computed, viewChild} from '@angular/core';
1310
import {TestBed} from '@angular/core/testing';
1411

1512
describe('queries as signals', () => {
1613
describe('view', () => {
17-
// TODO: Enable when `viewChild` is exposed publicly. Right now, compiler will
18-
// not detect `viewChild` as it does not originate from a `@angular/core` import.
19-
xit('view child', () => {
14+
it('view child', () => {
2015
@Component({
2116
selector: 'test-cmp',
2217
standalone: true,

packages/core/test/acceptance/query_signal_spec.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@
77
*/
88

99

10-
import {Component, computed, ContentChild, ContentChildren, Directive, ElementRef, ViewChild, ViewChildren} from '@angular/core';
11-
// TODO: update imports to the exported authoring functions when those are public
12-
import {contentChild, contentChildren, viewChild, viewChildren} from '@angular/core/src/authoring/queries';
10+
import {Component, computed, ContentChild, contentChild, ContentChildren, contentChildren, Directive, ElementRef, ViewChild, viewChild, ViewChildren, viewChildren} from '@angular/core';
1311
import {TestBed} from '@angular/core/testing';
1412
import {By} from '@angular/platform-browser';
1513

packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@
240240
"name": "GenericBrowserDomAdapter"
241241
},
242242
{
243-
"name": "INJECTOR2"
243+
"name": "INJECTOR"
244244
},
245245
{
246246
"name": "INJECTOR_DEF_TYPES"

packages/core/test/bundling/animations/bundle.golden_symbols.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@
264264
"name": "GenericBrowserDomAdapter"
265265
},
266266
{
267-
"name": "INJECTOR2"
267+
"name": "INJECTOR"
268268
},
269269
{
270270
"name": "INJECTOR_DEF_TYPES"

packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@
168168
"name": "GenericBrowserDomAdapter"
169169
},
170170
{
171-
"name": "INJECTOR2"
171+
"name": "INJECTOR"
172172
},
173173
{
174174
"name": "INJECTOR_DEF_TYPES"

packages/core/test/bundling/defer/bundle.golden_symbols.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@
198198
"name": "GenericBrowserDomAdapter"
199199
},
200200
{
201-
"name": "INJECTOR2"
201+
"name": "INJECTOR"
202202
},
203203
{
204204
"name": "INJECTOR_DEF_TYPES"
@@ -1709,6 +1709,9 @@
17091709
{
17101710
"name": "init_queries"
17111711
},
1712+
{
1713+
"name": "init_queries2"
1714+
},
17121715
{
17131716
"name": "init_queries_signals"
17141717
},

packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@
246246
"name": "GenericBrowserDomAdapter"
247247
},
248248
{
249-
"name": "INJECTOR2"
249+
"name": "INJECTOR"
250250
},
251251
{
252252
"name": "INJECTOR_DEF_TYPES"

packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@
231231
"name": "GenericBrowserDomAdapter"
232232
},
233233
{
234-
"name": "INJECTOR2"
234+
"name": "INJECTOR"
235235
},
236236
{
237237
"name": "INJECTOR_DEF_TYPES"

packages/core/test/bundling/hello_world/bundle.golden_symbols.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@
111111
"name": "HelloWorldModule"
112112
},
113113
{
114-
"name": "INJECTOR2"
114+
"name": "INJECTOR"
115115
},
116116
{
117117
"name": "INJECTOR_DEF_TYPES"

packages/core/test/bundling/hydration/bundle.golden_symbols.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@
195195
"name": "HydrationFeatureKind"
196196
},
197197
{
198-
"name": "INJECTOR2"
198+
"name": "INJECTOR"
199199
},
200200
{
201201
"name": "INJECTOR_DEF_TYPES"

packages/core/test/bundling/injection/bundle.golden_symbols.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"name": "EnvironmentInjector"
1313
},
1414
{
15-
"name": "INJECTOR2"
15+
"name": "INJECTOR"
1616
},
1717
{
1818
"name": "INJECTOR_DEF_TYPES"

packages/core/test/bundling/router/bundle.golden_symbols.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@
255255
"name": "INITIAL_VALUE"
256256
},
257257
{
258-
"name": "INJECTOR2"
258+
"name": "INJECTOR"
259259
},
260260
{
261261
"name": "INJECTOR_DEF_TYPES"

packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@
150150
"name": "GenericBrowserDomAdapter"
151151
},
152152
{
153-
"name": "INJECTOR2"
153+
"name": "INJECTOR"
154154
},
155155
{
156156
"name": "INJECTOR_DEF_TYPES"

packages/core/test/bundling/todo/bundle.golden_symbols.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@
171171
"name": "GenericBrowserDomAdapter"
172172
},
173173
{
174-
"name": "INJECTOR2"
174+
"name": "INJECTOR"
175175
},
176176
{
177177
"name": "INJECTOR_DEF_TYPES"

0 commit comments

Comments
 (0)