MCPcopy Create free account
hub / github.com/angular/angular / get

Function get

packages/forms/signals/src/field/proxy.ts:18–78  ·  view source on GitHub ↗
(getTgt: () => FieldNode, property: string | symbol, receiver: Record<string, unknown>)

Source from the content-addressed store, hash-verified

16 */
17export const FIELD_PROXY_HANDLER: ProxyHandler<() => FieldNode> = {
18 get(getTgt: () => FieldNode, property: string | symbol, receiver: Record<string, unknown>) {
19 if (property === FIELD_TREE) {
20 return true;
21 }
22
23 const tgt = getTgt();
24
25 // First, check whether the requested property is a defined child node of this node.
26 const child = tgt.structure.getChild(property);
27 if (child !== undefined) {
28 // If so, return the child node's `FieldTree` proxy, allowing the developer to continue
29 // navigating the form structure.
30 return child.fieldTree;
31 }
32
33 // Otherwise, we need to consider whether the properties they're accessing are related to array
34 // iteration. We're specifically interested in `length`, but we only want to pass this through
35 // if the value is actually an array.
36 //
37 // We untrack the value here to avoid spurious reactive notifications. In reality, we've already
38 // incurred a dependency on the value via `tgt.getChild()` above.
39 const value = untracked(tgt.value);
40
41 if (isArray(value)) {
42 // Allow access to the length for field arrays, it should be the same as the length of the data.
43 if (property === 'length') {
44 return (tgt.value() as Array<unknown>).length;
45 }
46 // Allow access to the iterator. This allows the user to spread the field array into a
47 // standard array in order to call methods like `filter`, `map`, etc.
48 if (property === Symbol.iterator) {
49 return () => {
50 // When creating an iterator, we need to account for reactivity. The iterator itself will
51 // read things each time `.next()` is called, but that may happen outside of the context
52 // where the iterator was created (e.g. with `@for`, actual diffing happens outside the
53 // reactive context of the template).
54 //
55 // Instead, side-effectfully read the value here to ensure iterator creation is reactive.
56 tgt.value();
57 return Array.prototype[Symbol.iterator].apply(tgt.fieldTree);
58 };
59 }
60 // Note: We can consider supporting additional array methods if we want in the future,
61 // but they should be thoroughly tested. Just forwarding the method directly from the
62 // `Array` prototype results in broken behavior for some methods like `map`.
63 }
64
65 if (isObject(value)) {
66 // For object fields, allow iteration over their entries for convenience of use with `@for`.
67 if (property === Symbol.iterator) {
68 return function* () {
69 for (const key in receiver) {
70 yield [key, receiver[key]];
71 }
72 };
73 }
74 }
75

Callers

nothing calls this directly

Calls 6

untrackedFunction · 0.90
isArrayFunction · 0.90
isObjectFunction · 0.90
getChildMethod · 0.65
valueMethod · 0.65
applyMethod · 0.65

Tested by

no test coverage detected