@angular/forms 21.2.0-next.0 → 21.2.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/_structure-chunk.mjs +149 -27
- package/fesm2022/_structure-chunk.mjs.map +1 -1
- package/fesm2022/forms.mjs +128 -128
- package/fesm2022/forms.mjs.map +1 -1
- package/fesm2022/signals-compat.mjs +389 -47
- package/fesm2022/signals-compat.mjs.map +1 -1
- package/fesm2022/signals.mjs +419 -70
- package/fesm2022/signals.mjs.map +1 -1
- package/package.json +4 -4
- package/resources/code-examples.db +0 -0
- package/types/_structure-chunk.d.ts +415 -1176
- package/types/forms.d.ts +1 -1
- package/types/signals-compat.d.ts +131 -8
- package/types/signals.d.ts +17 -46
package/fesm2022/signals.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v21.2.0-next.
|
|
2
|
+
* @license Angular v21.2.0-next.2
|
|
3
3
|
* (c) 2010-2026 Google LLC. https://angular.dev/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import * as i0 from '@angular/core';
|
|
8
|
-
import { InjectionToken, ɵRuntimeError as _RuntimeError,
|
|
8
|
+
import { InjectionToken, ɵRuntimeError as _RuntimeError, untracked, input, inject, Renderer2, DestroyRef, computed, Injector, ElementRef, signal, afterRenderEffect, effect, Directive, ɵisPromise as _isPromise, resource } from '@angular/core';
|
|
9
9
|
import { Validators, NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
|
|
10
|
-
import { assertPathIsCurrent, FieldPathNode, addDefaultField, metadata, createMetadataKey, MAX, MAX_LENGTH, MIN, MIN_LENGTH, PATTERN, REQUIRED, createManagedMetadataKey, DEBOUNCER } from './_structure-chunk.mjs';
|
|
10
|
+
import { signalErrorsToValidationErrors, assertPathIsCurrent, FieldPathNode, addDefaultField, metadata, createMetadataKey, MAX, MAX_LENGTH, MIN, MIN_LENGTH, PATTERN, REQUIRED, createManagedMetadataKey, DEBOUNCER } from './_structure-chunk.mjs';
|
|
11
11
|
export { MetadataKey, MetadataReducer, apply, applyEach, applyWhen, applyWhenValue, form, schema, submit } from './_structure-chunk.mjs';
|
|
12
12
|
import { httpResource } from '@angular/common/http';
|
|
13
13
|
import '@angular/core/primitives/signals';
|
|
@@ -46,15 +46,7 @@ class InteropNgControl {
|
|
|
46
46
|
return !this.field().disabled();
|
|
47
47
|
}
|
|
48
48
|
get errors() {
|
|
49
|
-
|
|
50
|
-
if (errors.length === 0) {
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
const errObj = {};
|
|
54
|
-
for (const error of errors) {
|
|
55
|
-
errObj[error.kind] = error;
|
|
56
|
-
}
|
|
57
|
-
return errObj;
|
|
49
|
+
return signalErrorsToValidationErrors(this.field().errors());
|
|
58
50
|
}
|
|
59
51
|
get pristine() {
|
|
60
52
|
return !this.field().dirty();
|
|
@@ -93,44 +85,367 @@ class InteropNgControl {
|
|
|
93
85
|
updateValueAndValidity() {}
|
|
94
86
|
}
|
|
95
87
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
88
|
+
function isNativeFormElement(element) {
|
|
89
|
+
return element.tagName === 'INPUT' || element.tagName === 'SELECT' || element.tagName === 'TEXTAREA';
|
|
90
|
+
}
|
|
91
|
+
function isNumericFormElement(element) {
|
|
92
|
+
if (element.tagName !== 'INPUT') {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
const type = element.type;
|
|
96
|
+
return type === 'date' || type === 'datetime-local' || type === 'month' || type === 'number' || type === 'range' || type === 'time' || type === 'week';
|
|
97
|
+
}
|
|
98
|
+
function isTextualFormElement(element) {
|
|
99
|
+
return element.tagName === 'INPUT' || element.tagName === 'TEXTAREA';
|
|
100
|
+
}
|
|
101
|
+
function getNativeControlValue(element, currentValue) {
|
|
102
|
+
switch (element.type) {
|
|
103
|
+
case 'checkbox':
|
|
104
|
+
return element.checked;
|
|
105
|
+
case 'number':
|
|
106
|
+
case 'range':
|
|
107
|
+
case 'datetime-local':
|
|
108
|
+
if (typeof untracked(currentValue) === 'number') {
|
|
109
|
+
return element.valueAsNumber;
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
|
+
case 'date':
|
|
113
|
+
case 'month':
|
|
114
|
+
case 'time':
|
|
115
|
+
case 'week':
|
|
116
|
+
const value = untracked(currentValue);
|
|
117
|
+
if (value === null || value instanceof Date) {
|
|
118
|
+
return element.valueAsDate;
|
|
119
|
+
} else if (typeof value === 'number') {
|
|
120
|
+
return element.valueAsNumber;
|
|
121
|
+
}
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
return element.value;
|
|
125
|
+
}
|
|
126
|
+
function setNativeControlValue(element, value) {
|
|
127
|
+
switch (element.type) {
|
|
128
|
+
case 'checkbox':
|
|
129
|
+
element.checked = value;
|
|
130
|
+
return;
|
|
131
|
+
case 'radio':
|
|
132
|
+
element.checked = value === element.value;
|
|
133
|
+
return;
|
|
134
|
+
case 'number':
|
|
135
|
+
case 'range':
|
|
136
|
+
case 'datetime-local':
|
|
137
|
+
if (typeof value === 'number') {
|
|
138
|
+
setNativeNumberControlValue(element, value);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
break;
|
|
142
|
+
case 'date':
|
|
143
|
+
case 'month':
|
|
144
|
+
case 'time':
|
|
145
|
+
case 'week':
|
|
146
|
+
if (value === null || value instanceof Date) {
|
|
147
|
+
element.valueAsDate = value;
|
|
148
|
+
return;
|
|
149
|
+
} else if (typeof value === 'number') {
|
|
150
|
+
setNativeNumberControlValue(element, value);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
element.value = value;
|
|
155
|
+
}
|
|
156
|
+
function setNativeNumberControlValue(element, value) {
|
|
157
|
+
if (isNaN(value)) {
|
|
158
|
+
element.value = '';
|
|
159
|
+
} else {
|
|
160
|
+
element.valueAsNumber = value;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function setNativeDomProperty(renderer, element, name, value) {
|
|
164
|
+
switch (name) {
|
|
165
|
+
case 'name':
|
|
166
|
+
renderer.setAttribute(element, name, value);
|
|
167
|
+
break;
|
|
168
|
+
case 'disabled':
|
|
169
|
+
case 'readonly':
|
|
170
|
+
case 'required':
|
|
171
|
+
if (value) {
|
|
172
|
+
renderer.setAttribute(element, name, '');
|
|
173
|
+
} else {
|
|
174
|
+
renderer.removeAttribute(element, name);
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
177
|
+
case 'max':
|
|
178
|
+
case 'min':
|
|
179
|
+
case 'minLength':
|
|
180
|
+
case 'maxLength':
|
|
181
|
+
if (value !== undefined) {
|
|
182
|
+
renderer.setAttribute(element, name, value.toString());
|
|
183
|
+
} else {
|
|
184
|
+
renderer.removeAttribute(element, name);
|
|
185
|
+
}
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const FIELD_STATE_KEY_TO_CONTROL_BINDING = {
|
|
191
|
+
disabled: 'disabled',
|
|
192
|
+
disabledReasons: 'disabledReasons',
|
|
193
|
+
dirty: 'dirty',
|
|
194
|
+
errors: 'errors',
|
|
195
|
+
hidden: 'hidden',
|
|
196
|
+
invalid: 'invalid',
|
|
197
|
+
max: 'max',
|
|
198
|
+
maxLength: 'maxLength',
|
|
199
|
+
min: 'min',
|
|
200
|
+
minLength: 'minLength',
|
|
201
|
+
name: 'name',
|
|
202
|
+
pattern: 'pattern',
|
|
203
|
+
pending: 'pending',
|
|
204
|
+
readonly: 'readonly',
|
|
205
|
+
required: 'required',
|
|
206
|
+
touched: 'touched'
|
|
100
207
|
};
|
|
208
|
+
const CONTROL_BINDING_TO_FIELD_STATE_KEY = /* @__PURE__ */(() => {
|
|
209
|
+
const map = {};
|
|
210
|
+
for (const key of Object.keys(FIELD_STATE_KEY_TO_CONTROL_BINDING)) {
|
|
211
|
+
map[FIELD_STATE_KEY_TO_CONTROL_BINDING[key]] = key;
|
|
212
|
+
}
|
|
213
|
+
return map;
|
|
214
|
+
})();
|
|
215
|
+
function readFieldStateBindingValue(fieldState, key) {
|
|
216
|
+
const property = CONTROL_BINDING_TO_FIELD_STATE_KEY[key];
|
|
217
|
+
return fieldState[property]?.();
|
|
218
|
+
}
|
|
219
|
+
const CONTROL_BINDING_NAMES = /* @__PURE__ */(() => Object.values(FIELD_STATE_KEY_TO_CONTROL_BINDING))();
|
|
220
|
+
function createBindings() {
|
|
221
|
+
return {};
|
|
222
|
+
}
|
|
223
|
+
function bindingUpdated(bindings, key, value) {
|
|
224
|
+
if (bindings[key] !== value) {
|
|
225
|
+
bindings[key] = value;
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function cvaControlCreate(host, parent) {
|
|
232
|
+
parent.controlValueAccessor.registerOnChange(value => parent.state().controlValue.set(value));
|
|
233
|
+
parent.controlValueAccessor.registerOnTouched(() => parent.state().markAsTouched());
|
|
234
|
+
parent.registerAsBinding();
|
|
235
|
+
const bindings = createBindings();
|
|
236
|
+
return () => {
|
|
237
|
+
const fieldState = parent.state();
|
|
238
|
+
const value = fieldState.value();
|
|
239
|
+
if (bindingUpdated(bindings, 'controlValue', value)) {
|
|
240
|
+
untracked(() => parent.controlValueAccessor.writeValue(value));
|
|
241
|
+
}
|
|
242
|
+
for (const name of CONTROL_BINDING_NAMES) {
|
|
243
|
+
const value = readFieldStateBindingValue(fieldState, name);
|
|
244
|
+
if (bindingUpdated(bindings, name, value)) {
|
|
245
|
+
const propertyWasSet = host.setInputOnDirectives(name, value);
|
|
246
|
+
if (name === 'disabled' && parent.controlValueAccessor.setDisabledState) {
|
|
247
|
+
untracked(() => parent.controlValueAccessor.setDisabledState(value));
|
|
248
|
+
} else if (!propertyWasSet && parent.elementAcceptsNativeProperty(name)) {
|
|
249
|
+
setNativeDomProperty(parent.renderer, parent.nativeFormElement, name, value);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function customControlCreate(host, parent) {
|
|
257
|
+
host.listenToCustomControlModel(value => parent.state().controlValue.set(value));
|
|
258
|
+
host.listenToCustomControlOutput('touchedChange', () => parent.state().markAsTouched());
|
|
259
|
+
parent.registerAsBinding(host.customControl);
|
|
260
|
+
const bindings = createBindings();
|
|
261
|
+
return () => {
|
|
262
|
+
const state = parent.state();
|
|
263
|
+
const controlValue = state.controlValue();
|
|
264
|
+
if (bindingUpdated(bindings, 'controlValue', controlValue)) {
|
|
265
|
+
host.setCustomControlModelInput(controlValue);
|
|
266
|
+
}
|
|
267
|
+
for (const name of CONTROL_BINDING_NAMES) {
|
|
268
|
+
let value;
|
|
269
|
+
if (name === 'errors') {
|
|
270
|
+
value = parent.errors();
|
|
271
|
+
} else {
|
|
272
|
+
value = readFieldStateBindingValue(state, name);
|
|
273
|
+
}
|
|
274
|
+
if (bindingUpdated(bindings, name, value)) {
|
|
275
|
+
host.setInputOnDirectives(name, value);
|
|
276
|
+
if (parent.elementAcceptsNativeProperty(name) && !host.customControlHasInput(name)) {
|
|
277
|
+
setNativeDomProperty(parent.renderer, parent.nativeFormElement, name, value);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function observeSelectMutations(select, onMutation, destroyRef) {
|
|
285
|
+
if (typeof MutationObserver !== 'function') {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const observer = new MutationObserver(mutations => {
|
|
289
|
+
if (mutations.some(m => isRelevantSelectMutation(m))) {
|
|
290
|
+
onMutation();
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
observer.observe(select, {
|
|
294
|
+
attributes: true,
|
|
295
|
+
attributeFilter: ['value'],
|
|
296
|
+
characterData: true,
|
|
297
|
+
childList: true,
|
|
298
|
+
subtree: true
|
|
299
|
+
});
|
|
300
|
+
destroyRef.onDestroy(() => observer.disconnect());
|
|
301
|
+
}
|
|
302
|
+
function isRelevantSelectMutation(mutation) {
|
|
303
|
+
if (mutation.type === 'childList' || mutation.type === 'characterData') {
|
|
304
|
+
if (mutation.target instanceof Comment) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
for (const node of mutation.addedNodes) {
|
|
308
|
+
if (!(node instanceof Comment)) {
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
for (const node of mutation.removedNodes) {
|
|
313
|
+
if (!(node instanceof Comment)) {
|
|
314
|
+
return true;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
if (mutation.type === 'attributes' && mutation.target instanceof HTMLOptionElement) {
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function nativeControlCreate(host, parent) {
|
|
326
|
+
let updateMode = false;
|
|
327
|
+
const input = parent.nativeFormElement;
|
|
328
|
+
host.listenToDom('input', () => {
|
|
329
|
+
const state = parent.state();
|
|
330
|
+
state.controlValue.set(getNativeControlValue(input, state.value));
|
|
331
|
+
});
|
|
332
|
+
host.listenToDom('blur', () => parent.state().markAsTouched());
|
|
333
|
+
parent.registerAsBinding();
|
|
334
|
+
if (input.tagName === 'SELECT') {
|
|
335
|
+
observeSelectMutations(input, () => {
|
|
336
|
+
if (!updateMode) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
input.value = parent.state().controlValue();
|
|
340
|
+
}, parent.destroyRef);
|
|
341
|
+
}
|
|
342
|
+
const bindings = createBindings();
|
|
343
|
+
return () => {
|
|
344
|
+
const state = parent.state();
|
|
345
|
+
const controlValue = state.controlValue();
|
|
346
|
+
if (bindingUpdated(bindings, 'controlValue', controlValue)) {
|
|
347
|
+
setNativeControlValue(input, controlValue);
|
|
348
|
+
}
|
|
349
|
+
for (const name of CONTROL_BINDING_NAMES) {
|
|
350
|
+
const value = readFieldStateBindingValue(state, name);
|
|
351
|
+
if (bindingUpdated(bindings, name, value)) {
|
|
352
|
+
host.setInputOnDirectives(name, value);
|
|
353
|
+
if (parent.elementAcceptsNativeProperty(name)) {
|
|
354
|
+
setNativeDomProperty(parent.renderer, input, name, value);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
updateMode = true;
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const ɵNgFieldDirective = Symbol();
|
|
363
|
+
const FORM_FIELD = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'FORM_FIELD' : '');
|
|
101
364
|
class FormField {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
365
|
+
fieldTree = input.required({
|
|
366
|
+
...(ngDevMode ? {
|
|
367
|
+
debugName: "fieldTree"
|
|
368
|
+
} : {}),
|
|
369
|
+
alias: 'formField'
|
|
370
|
+
});
|
|
371
|
+
renderer = inject(Renderer2);
|
|
372
|
+
destroyRef = inject(DestroyRef);
|
|
373
|
+
state = computed(() => this.fieldTree()(), ...(ngDevMode ? [{
|
|
108
374
|
debugName: "state"
|
|
109
375
|
}] : []));
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
classes = Object.entries(this.config?.classes ?? {}).map(([className, computation]) => [className, computed(() => computation(this))]);
|
|
376
|
+
injector = inject(Injector);
|
|
377
|
+
element = inject(ElementRef).nativeElement;
|
|
378
|
+
elementIsNativeFormElement = isNativeFormElement(this.element);
|
|
379
|
+
elementAcceptsNumericValues = isNumericFormElement(this.element);
|
|
380
|
+
elementAcceptsTextualValues = isTextualFormElement(this.element);
|
|
381
|
+
nativeFormElement = this.elementIsNativeFormElement ? this.element : undefined;
|
|
382
|
+
focuser = options => this.element.focus(options);
|
|
118
383
|
controlValueAccessors = inject(NG_VALUE_ACCESSOR, {
|
|
119
384
|
optional: true,
|
|
120
385
|
self: true
|
|
121
386
|
});
|
|
122
|
-
|
|
123
|
-
|
|
387
|
+
config = inject(SIGNAL_FORMS_CONFIG, {
|
|
388
|
+
optional: true
|
|
389
|
+
});
|
|
390
|
+
parseErrorsSource = signal(undefined, ...(ngDevMode ? [{
|
|
391
|
+
debugName: "parseErrorsSource"
|
|
392
|
+
}] : []));
|
|
393
|
+
_interopNgControl;
|
|
394
|
+
get interopNgControl() {
|
|
395
|
+
return this._interopNgControl ??= new InteropNgControl(this.state);
|
|
396
|
+
}
|
|
397
|
+
parseErrors = computed(() => this.parseErrorsSource()?.().map(err => ({
|
|
398
|
+
...err,
|
|
399
|
+
fieldTree: untracked(this.fieldTree),
|
|
400
|
+
formField: this
|
|
401
|
+
})) ?? [], ...(ngDevMode ? [{
|
|
402
|
+
debugName: "parseErrors"
|
|
403
|
+
}] : []));
|
|
404
|
+
errors = computed(() => this.state().errors().filter(err => !err.formField || err.formField === this), ...(ngDevMode ? [{
|
|
405
|
+
debugName: "errors"
|
|
406
|
+
}] : []));
|
|
407
|
+
isFieldBinding = false;
|
|
408
|
+
get controlValueAccessor() {
|
|
124
409
|
return this.controlValueAccessors?.[0] ?? this.interopNgControl?.valueAccessor ?? undefined;
|
|
125
410
|
}
|
|
126
|
-
|
|
127
|
-
|
|
411
|
+
installClassBindingEffect() {
|
|
412
|
+
const classes = Object.entries(this.config?.classes ?? {}).map(([className, computation]) => [className, computed(() => computation(this))]);
|
|
413
|
+
if (classes.length === 0) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
const bindings = createBindings();
|
|
417
|
+
afterRenderEffect({
|
|
418
|
+
write: () => {
|
|
419
|
+
for (const [className, computation] of classes) {
|
|
420
|
+
const active = computation();
|
|
421
|
+
if (bindingUpdated(bindings, className, active)) {
|
|
422
|
+
if (active) {
|
|
423
|
+
this.renderer.addClass(this.element, className);
|
|
424
|
+
} else {
|
|
425
|
+
this.renderer.removeClass(this.element, className);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}, {
|
|
431
|
+
injector: this.injector
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
focus(options) {
|
|
435
|
+
this.focuser(options);
|
|
128
436
|
}
|
|
129
437
|
registerAsBinding(bindingOptions) {
|
|
130
|
-
if (
|
|
438
|
+
if (this.isFieldBinding) {
|
|
131
439
|
throw new _RuntimeError(1913, ngDevMode && 'FormField already registered as a binding');
|
|
132
440
|
}
|
|
133
|
-
this.
|
|
441
|
+
this.isFieldBinding = true;
|
|
442
|
+
this.installClassBindingEffect();
|
|
443
|
+
if (bindingOptions?.focus) {
|
|
444
|
+
this.focuser = bindingOptions.focus;
|
|
445
|
+
}
|
|
446
|
+
if (bindingOptions?.parseErrors) {
|
|
447
|
+
this.parseErrorsSource.set(bindingOptions.parseErrors);
|
|
448
|
+
}
|
|
134
449
|
effect(onCleanup => {
|
|
135
450
|
const fieldNode = this.state();
|
|
136
451
|
fieldNode.nodeState.formFieldBindings.update(controls => [...controls, this]);
|
|
@@ -141,17 +456,45 @@ class FormField {
|
|
|
141
456
|
injector: this.injector
|
|
142
457
|
});
|
|
143
458
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (
|
|
147
|
-
|
|
459
|
+
[ɵNgFieldDirective];
|
|
460
|
+
ɵngControlCreate(host) {
|
|
461
|
+
if (host.hasPassThrough) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
if (this.controlValueAccessor) {
|
|
465
|
+
this.ɵngControlUpdate = cvaControlCreate(host, this);
|
|
466
|
+
} else if (host.customControl) {
|
|
467
|
+
this.ɵngControlUpdate = customControlCreate(host, this);
|
|
468
|
+
} else if (this.elementIsNativeFormElement) {
|
|
469
|
+
this.ɵngControlUpdate = nativeControlCreate(host, this);
|
|
148
470
|
} else {
|
|
149
|
-
|
|
471
|
+
throw new _RuntimeError(1914, ngDevMode && `${host.descriptor} is an invalid [formField] directive host. The host must be a native form control ` + `(such as <input>', '<select>', or '<textarea>') or a custom form control with a 'value' or ` + `'checked' model.`);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
ɵngControlUpdate;
|
|
475
|
+
elementAcceptsNativeProperty(key) {
|
|
476
|
+
if (!this.elementIsNativeFormElement) {
|
|
477
|
+
return false;
|
|
478
|
+
}
|
|
479
|
+
switch (key) {
|
|
480
|
+
case 'min':
|
|
481
|
+
case 'max':
|
|
482
|
+
return this.elementAcceptsNumericValues;
|
|
483
|
+
case 'minLength':
|
|
484
|
+
case 'maxLength':
|
|
485
|
+
return this.elementAcceptsTextualValues;
|
|
486
|
+
case 'disabled':
|
|
487
|
+
case 'required':
|
|
488
|
+
case 'readonly':
|
|
489
|
+
case 'name':
|
|
490
|
+
return true;
|
|
491
|
+
default:
|
|
492
|
+
return false;
|
|
150
493
|
}
|
|
151
494
|
}
|
|
152
495
|
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
153
496
|
minVersion: "12.0.0",
|
|
154
|
-
version: "21.2.0-next.
|
|
497
|
+
version: "21.2.0-next.2",
|
|
155
498
|
ngImport: i0,
|
|
156
499
|
type: FormField,
|
|
157
500
|
deps: [],
|
|
@@ -159,13 +502,13 @@ class FormField {
|
|
|
159
502
|
});
|
|
160
503
|
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
161
504
|
minVersion: "17.1.0",
|
|
162
|
-
version: "21.2.0-next.
|
|
505
|
+
version: "21.2.0-next.2",
|
|
163
506
|
type: FormField,
|
|
164
507
|
isStandalone: true,
|
|
165
508
|
selector: "[formField]",
|
|
166
509
|
inputs: {
|
|
167
|
-
|
|
168
|
-
classPropertyName: "
|
|
510
|
+
fieldTree: {
|
|
511
|
+
classPropertyName: "fieldTree",
|
|
169
512
|
publicName: "formField",
|
|
170
513
|
isSignal: true,
|
|
171
514
|
isRequired: true,
|
|
@@ -177,31 +520,36 @@ class FormField {
|
|
|
177
520
|
useExisting: FormField
|
|
178
521
|
}, {
|
|
179
522
|
provide: NgControl,
|
|
180
|
-
useFactory: () => inject(FormField).
|
|
523
|
+
useFactory: () => inject(FormField).interopNgControl
|
|
181
524
|
}],
|
|
525
|
+
exportAs: ["formField"],
|
|
526
|
+
controlCreate: {
|
|
527
|
+
passThroughInput: "formField"
|
|
528
|
+
},
|
|
182
529
|
ngImport: i0
|
|
183
530
|
});
|
|
184
531
|
}
|
|
185
532
|
i0.ɵɵngDeclareClassMetadata({
|
|
186
533
|
minVersion: "12.0.0",
|
|
187
|
-
version: "21.2.0-next.
|
|
534
|
+
version: "21.2.0-next.2",
|
|
188
535
|
ngImport: i0,
|
|
189
536
|
type: FormField,
|
|
190
537
|
decorators: [{
|
|
191
538
|
type: Directive,
|
|
192
539
|
args: [{
|
|
193
540
|
selector: '[formField]',
|
|
541
|
+
exportAs: 'formField',
|
|
194
542
|
providers: [{
|
|
195
543
|
provide: FORM_FIELD,
|
|
196
544
|
useExisting: FormField
|
|
197
545
|
}, {
|
|
198
546
|
provide: NgControl,
|
|
199
|
-
useFactory: () => inject(FormField).
|
|
547
|
+
useFactory: () => inject(FormField).interopNgControl
|
|
200
548
|
}]
|
|
201
549
|
}]
|
|
202
550
|
}],
|
|
203
551
|
propDecorators: {
|
|
204
|
-
|
|
552
|
+
fieldTree: [{
|
|
205
553
|
type: i0.Input,
|
|
206
554
|
args: [{
|
|
207
555
|
isSignal: true,
|
|
@@ -289,10 +637,7 @@ function patternError(pattern, options) {
|
|
|
289
637
|
function emailError(options) {
|
|
290
638
|
return new EmailValidationError(options);
|
|
291
639
|
}
|
|
292
|
-
|
|
293
|
-
return new StandardSchemaValidationError(issue, options);
|
|
294
|
-
}
|
|
295
|
-
class _NgValidationError {
|
|
640
|
+
class BaseNgValidationError {
|
|
296
641
|
__brand = undefined;
|
|
297
642
|
kind = '';
|
|
298
643
|
fieldTree;
|
|
@@ -303,10 +648,10 @@ class _NgValidationError {
|
|
|
303
648
|
}
|
|
304
649
|
}
|
|
305
650
|
}
|
|
306
|
-
class RequiredValidationError extends
|
|
651
|
+
class RequiredValidationError extends BaseNgValidationError {
|
|
307
652
|
kind = 'required';
|
|
308
653
|
}
|
|
309
|
-
class MinValidationError extends
|
|
654
|
+
class MinValidationError extends BaseNgValidationError {
|
|
310
655
|
min;
|
|
311
656
|
kind = 'min';
|
|
312
657
|
constructor(min, options) {
|
|
@@ -314,7 +659,7 @@ class MinValidationError extends _NgValidationError {
|
|
|
314
659
|
this.min = min;
|
|
315
660
|
}
|
|
316
661
|
}
|
|
317
|
-
class MaxValidationError extends
|
|
662
|
+
class MaxValidationError extends BaseNgValidationError {
|
|
318
663
|
max;
|
|
319
664
|
kind = 'max';
|
|
320
665
|
constructor(max, options) {
|
|
@@ -322,7 +667,7 @@ class MaxValidationError extends _NgValidationError {
|
|
|
322
667
|
this.max = max;
|
|
323
668
|
}
|
|
324
669
|
}
|
|
325
|
-
class MinLengthValidationError extends
|
|
670
|
+
class MinLengthValidationError extends BaseNgValidationError {
|
|
326
671
|
minLength;
|
|
327
672
|
kind = 'minLength';
|
|
328
673
|
constructor(minLength, options) {
|
|
@@ -330,7 +675,7 @@ class MinLengthValidationError extends _NgValidationError {
|
|
|
330
675
|
this.minLength = minLength;
|
|
331
676
|
}
|
|
332
677
|
}
|
|
333
|
-
class MaxLengthValidationError extends
|
|
678
|
+
class MaxLengthValidationError extends BaseNgValidationError {
|
|
334
679
|
maxLength;
|
|
335
680
|
kind = 'maxLength';
|
|
336
681
|
constructor(maxLength, options) {
|
|
@@ -338,7 +683,7 @@ class MaxLengthValidationError extends _NgValidationError {
|
|
|
338
683
|
this.maxLength = maxLength;
|
|
339
684
|
}
|
|
340
685
|
}
|
|
341
|
-
class PatternValidationError extends
|
|
686
|
+
class PatternValidationError extends BaseNgValidationError {
|
|
342
687
|
pattern;
|
|
343
688
|
kind = 'pattern';
|
|
344
689
|
constructor(pattern, options) {
|
|
@@ -346,18 +691,10 @@ class PatternValidationError extends _NgValidationError {
|
|
|
346
691
|
this.pattern = pattern;
|
|
347
692
|
}
|
|
348
693
|
}
|
|
349
|
-
class EmailValidationError extends
|
|
694
|
+
class EmailValidationError extends BaseNgValidationError {
|
|
350
695
|
kind = 'email';
|
|
351
696
|
}
|
|
352
|
-
|
|
353
|
-
issue;
|
|
354
|
-
kind = 'standardSchema';
|
|
355
|
-
constructor(issue, options) {
|
|
356
|
-
super(options);
|
|
357
|
-
this.issue = issue;
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
const NgValidationError = _NgValidationError;
|
|
697
|
+
const NgValidationError = BaseNgValidationError;
|
|
361
698
|
|
|
362
699
|
const EMAIL_REGEXP = /^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
363
700
|
function email(path, config) {
|
|
@@ -611,6 +948,9 @@ function validateStandardSchema(path, schema) {
|
|
|
611
948
|
onError: () => {}
|
|
612
949
|
});
|
|
613
950
|
}
|
|
951
|
+
function standardSchemaError(issue, options) {
|
|
952
|
+
return new StandardSchemaValidationError(issue, options);
|
|
953
|
+
}
|
|
614
954
|
function standardIssueToFormTreeError(fieldTree, issue) {
|
|
615
955
|
let target = fieldTree;
|
|
616
956
|
for (const pathPart of issue.path ?? []) {
|
|
@@ -621,6 +961,14 @@ function standardIssueToFormTreeError(fieldTree, issue) {
|
|
|
621
961
|
message: issue.message
|
|
622
962
|
}), target);
|
|
623
963
|
}
|
|
964
|
+
class StandardSchemaValidationError extends BaseNgValidationError {
|
|
965
|
+
issue;
|
|
966
|
+
kind = 'standardSchema';
|
|
967
|
+
constructor(issue, options) {
|
|
968
|
+
super(options);
|
|
969
|
+
this.issue = issue;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
624
972
|
|
|
625
973
|
function validateHttp(path, opts) {
|
|
626
974
|
validateAsync(path, {
|
|
@@ -643,6 +991,7 @@ function debounceForDuration(durationInMilliseconds) {
|
|
|
643
991
|
let timeoutId;
|
|
644
992
|
const onAbort = () => {
|
|
645
993
|
clearTimeout(timeoutId);
|
|
994
|
+
resolve();
|
|
646
995
|
};
|
|
647
996
|
timeoutId = setTimeout(() => {
|
|
648
997
|
abortSignal.removeEventListener('abort', onAbort);
|
|
@@ -656,5 +1005,5 @@ function debounceForDuration(durationInMilliseconds) {
|
|
|
656
1005
|
}
|
|
657
1006
|
function immediate() {}
|
|
658
1007
|
|
|
659
|
-
export { EmailValidationError, FORM_FIELD, FormField, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MaxLengthValidationError, MaxValidationError, MinLengthValidationError, MinValidationError, NgValidationError, PATTERN, PatternValidationError, REQUIRED, RequiredValidationError, StandardSchemaValidationError, createManagedMetadataKey, createMetadataKey, debounce, disabled, email, emailError, hidden, max, maxError, maxLength, maxLengthError, metadata, min, minError, minLength, minLengthError, pattern, patternError, provideSignalFormsConfig, readonly, required, requiredError, standardSchemaError, validate, validateAsync, validateHttp, validateStandardSchema, validateTree };
|
|
1008
|
+
export { BaseNgValidationError, EmailValidationError, FORM_FIELD, FormField, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MaxLengthValidationError, MaxValidationError, MinLengthValidationError, MinValidationError, NgValidationError, PATTERN, PatternValidationError, REQUIRED, RequiredValidationError, StandardSchemaValidationError, createManagedMetadataKey, createMetadataKey, debounce, disabled, email, emailError, hidden, max, maxError, maxLength, maxLengthError, metadata, min, minError, minLength, minLengthError, pattern, patternError, provideSignalFormsConfig, readonly, required, requiredError, standardSchemaError, validate, validateAsync, validateHttp, validateStandardSchema, validateTree, ɵNgFieldDirective };
|
|
660
1009
|
//# sourceMappingURL=signals.mjs.map
|