@angular/forms 21.2.0-next.1 → 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 +116 -26
- 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 +386 -47
- package/fesm2022/signals-compat.mjs.map +1 -1
- package/fesm2022/signals.mjs +402 -68
- 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 +253 -1039
- package/types/forms.d.ts +1 -1
- package/types/signals-compat.d.ts +131 -8
- package/types/signals.d.ts +6 -41
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,29 +85,318 @@ 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
|
-
element = inject(ElementRef).nativeElement;
|
|
103
|
-
injector = inject(Injector);
|
|
104
365
|
fieldTree = input.required({
|
|
105
366
|
...(ngDevMode ? {
|
|
106
367
|
debugName: "fieldTree"
|
|
107
368
|
} : {}),
|
|
108
369
|
alias: 'formField'
|
|
109
370
|
});
|
|
371
|
+
renderer = inject(Renderer2);
|
|
372
|
+
destroyRef = inject(DestroyRef);
|
|
110
373
|
state = computed(() => this.fieldTree()(), ...(ngDevMode ? [{
|
|
111
374
|
debugName: "state"
|
|
112
375
|
}] : []));
|
|
113
|
-
|
|
114
|
-
|
|
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);
|
|
383
|
+
controlValueAccessors = inject(NG_VALUE_ACCESSOR, {
|
|
384
|
+
optional: true,
|
|
385
|
+
self: true
|
|
386
|
+
});
|
|
387
|
+
config = inject(SIGNAL_FORMS_CONFIG, {
|
|
388
|
+
optional: true
|
|
389
|
+
});
|
|
390
|
+
parseErrorsSource = signal(undefined, ...(ngDevMode ? [{
|
|
391
|
+
debugName: "parseErrorsSource"
|
|
115
392
|
}] : []));
|
|
116
|
-
|
|
393
|
+
_interopNgControl;
|
|
394
|
+
get interopNgControl() {
|
|
395
|
+
return this._interopNgControl ??= new InteropNgControl(this.state);
|
|
396
|
+
}
|
|
397
|
+
parseErrors = computed(() => this.parseErrorsSource()?.().map(err => ({
|
|
117
398
|
...err,
|
|
118
|
-
fieldTree: this.fieldTree
|
|
399
|
+
fieldTree: untracked(this.fieldTree),
|
|
119
400
|
formField: this
|
|
120
401
|
})) ?? [], ...(ngDevMode ? [{
|
|
121
402
|
debugName: "parseErrors"
|
|
@@ -123,27 +404,48 @@ class FormField {
|
|
|
123
404
|
errors = computed(() => this.state().errors().filter(err => !err.formField || err.formField === this), ...(ngDevMode ? [{
|
|
124
405
|
debugName: "errors"
|
|
125
406
|
}] : []));
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
optional: true
|
|
129
|
-
});
|
|
130
|
-
classes = Object.entries(this.config?.classes ?? {}).map(([className, computation]) => [className, computed(() => computation(this))]);
|
|
131
|
-
controlValueAccessors = inject(NG_VALUE_ACCESSOR, {
|
|
132
|
-
optional: true,
|
|
133
|
-
self: true
|
|
134
|
-
});
|
|
135
|
-
interopNgControl;
|
|
136
|
-
get ɵinteropControl() {
|
|
407
|
+
isFieldBinding = false;
|
|
408
|
+
get controlValueAccessor() {
|
|
137
409
|
return this.controlValueAccessors?.[0] ?? this.interopNgControl?.valueAccessor ?? undefined;
|
|
138
410
|
}
|
|
139
|
-
|
|
140
|
-
|
|
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);
|
|
141
436
|
}
|
|
142
437
|
registerAsBinding(bindingOptions) {
|
|
143
|
-
if (
|
|
438
|
+
if (this.isFieldBinding) {
|
|
144
439
|
throw new _RuntimeError(1913, ngDevMode && 'FormField already registered as a binding');
|
|
145
440
|
}
|
|
146
|
-
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
|
+
}
|
|
147
449
|
effect(onCleanup => {
|
|
148
450
|
const fieldNode = this.state();
|
|
149
451
|
fieldNode.nodeState.formFieldBindings.update(controls => [...controls, this]);
|
|
@@ -154,17 +456,45 @@ class FormField {
|
|
|
154
456
|
injector: this.injector
|
|
155
457
|
});
|
|
156
458
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (
|
|
160
|
-
|
|
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);
|
|
161
470
|
} else {
|
|
162
|
-
|
|
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;
|
|
163
493
|
}
|
|
164
494
|
}
|
|
165
495
|
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
166
496
|
minVersion: "12.0.0",
|
|
167
|
-
version: "21.2.0-next.
|
|
497
|
+
version: "21.2.0-next.2",
|
|
168
498
|
ngImport: i0,
|
|
169
499
|
type: FormField,
|
|
170
500
|
deps: [],
|
|
@@ -172,7 +502,7 @@ class FormField {
|
|
|
172
502
|
});
|
|
173
503
|
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
174
504
|
minVersion: "17.1.0",
|
|
175
|
-
version: "21.2.0-next.
|
|
505
|
+
version: "21.2.0-next.2",
|
|
176
506
|
type: FormField,
|
|
177
507
|
isStandalone: true,
|
|
178
508
|
selector: "[formField]",
|
|
@@ -190,15 +520,18 @@ class FormField {
|
|
|
190
520
|
useExisting: FormField
|
|
191
521
|
}, {
|
|
192
522
|
provide: NgControl,
|
|
193
|
-
useFactory: () => inject(FormField).
|
|
523
|
+
useFactory: () => inject(FormField).interopNgControl
|
|
194
524
|
}],
|
|
195
525
|
exportAs: ["formField"],
|
|
526
|
+
controlCreate: {
|
|
527
|
+
passThroughInput: "formField"
|
|
528
|
+
},
|
|
196
529
|
ngImport: i0
|
|
197
530
|
});
|
|
198
531
|
}
|
|
199
532
|
i0.ɵɵngDeclareClassMetadata({
|
|
200
533
|
minVersion: "12.0.0",
|
|
201
|
-
version: "21.2.0-next.
|
|
534
|
+
version: "21.2.0-next.2",
|
|
202
535
|
ngImport: i0,
|
|
203
536
|
type: FormField,
|
|
204
537
|
decorators: [{
|
|
@@ -211,7 +544,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
211
544
|
useExisting: FormField
|
|
212
545
|
}, {
|
|
213
546
|
provide: NgControl,
|
|
214
|
-
useFactory: () => inject(FormField).
|
|
547
|
+
useFactory: () => inject(FormField).interopNgControl
|
|
215
548
|
}]
|
|
216
549
|
}]
|
|
217
550
|
}],
|
|
@@ -304,10 +637,7 @@ function patternError(pattern, options) {
|
|
|
304
637
|
function emailError(options) {
|
|
305
638
|
return new EmailValidationError(options);
|
|
306
639
|
}
|
|
307
|
-
|
|
308
|
-
return new StandardSchemaValidationError(issue, options);
|
|
309
|
-
}
|
|
310
|
-
class _NgValidationError {
|
|
640
|
+
class BaseNgValidationError {
|
|
311
641
|
__brand = undefined;
|
|
312
642
|
kind = '';
|
|
313
643
|
fieldTree;
|
|
@@ -318,10 +648,10 @@ class _NgValidationError {
|
|
|
318
648
|
}
|
|
319
649
|
}
|
|
320
650
|
}
|
|
321
|
-
class RequiredValidationError extends
|
|
651
|
+
class RequiredValidationError extends BaseNgValidationError {
|
|
322
652
|
kind = 'required';
|
|
323
653
|
}
|
|
324
|
-
class MinValidationError extends
|
|
654
|
+
class MinValidationError extends BaseNgValidationError {
|
|
325
655
|
min;
|
|
326
656
|
kind = 'min';
|
|
327
657
|
constructor(min, options) {
|
|
@@ -329,7 +659,7 @@ class MinValidationError extends _NgValidationError {
|
|
|
329
659
|
this.min = min;
|
|
330
660
|
}
|
|
331
661
|
}
|
|
332
|
-
class MaxValidationError extends
|
|
662
|
+
class MaxValidationError extends BaseNgValidationError {
|
|
333
663
|
max;
|
|
334
664
|
kind = 'max';
|
|
335
665
|
constructor(max, options) {
|
|
@@ -337,7 +667,7 @@ class MaxValidationError extends _NgValidationError {
|
|
|
337
667
|
this.max = max;
|
|
338
668
|
}
|
|
339
669
|
}
|
|
340
|
-
class MinLengthValidationError extends
|
|
670
|
+
class MinLengthValidationError extends BaseNgValidationError {
|
|
341
671
|
minLength;
|
|
342
672
|
kind = 'minLength';
|
|
343
673
|
constructor(minLength, options) {
|
|
@@ -345,7 +675,7 @@ class MinLengthValidationError extends _NgValidationError {
|
|
|
345
675
|
this.minLength = minLength;
|
|
346
676
|
}
|
|
347
677
|
}
|
|
348
|
-
class MaxLengthValidationError extends
|
|
678
|
+
class MaxLengthValidationError extends BaseNgValidationError {
|
|
349
679
|
maxLength;
|
|
350
680
|
kind = 'maxLength';
|
|
351
681
|
constructor(maxLength, options) {
|
|
@@ -353,7 +683,7 @@ class MaxLengthValidationError extends _NgValidationError {
|
|
|
353
683
|
this.maxLength = maxLength;
|
|
354
684
|
}
|
|
355
685
|
}
|
|
356
|
-
class PatternValidationError extends
|
|
686
|
+
class PatternValidationError extends BaseNgValidationError {
|
|
357
687
|
pattern;
|
|
358
688
|
kind = 'pattern';
|
|
359
689
|
constructor(pattern, options) {
|
|
@@ -361,18 +691,10 @@ class PatternValidationError extends _NgValidationError {
|
|
|
361
691
|
this.pattern = pattern;
|
|
362
692
|
}
|
|
363
693
|
}
|
|
364
|
-
class EmailValidationError extends
|
|
694
|
+
class EmailValidationError extends BaseNgValidationError {
|
|
365
695
|
kind = 'email';
|
|
366
696
|
}
|
|
367
|
-
|
|
368
|
-
issue;
|
|
369
|
-
kind = 'standardSchema';
|
|
370
|
-
constructor(issue, options) {
|
|
371
|
-
super(options);
|
|
372
|
-
this.issue = issue;
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
const NgValidationError = _NgValidationError;
|
|
697
|
+
const NgValidationError = BaseNgValidationError;
|
|
376
698
|
|
|
377
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])?)*$/;
|
|
378
700
|
function email(path, config) {
|
|
@@ -626,6 +948,9 @@ function validateStandardSchema(path, schema) {
|
|
|
626
948
|
onError: () => {}
|
|
627
949
|
});
|
|
628
950
|
}
|
|
951
|
+
function standardSchemaError(issue, options) {
|
|
952
|
+
return new StandardSchemaValidationError(issue, options);
|
|
953
|
+
}
|
|
629
954
|
function standardIssueToFormTreeError(fieldTree, issue) {
|
|
630
955
|
let target = fieldTree;
|
|
631
956
|
for (const pathPart of issue.path ?? []) {
|
|
@@ -636,6 +961,14 @@ function standardIssueToFormTreeError(fieldTree, issue) {
|
|
|
636
961
|
message: issue.message
|
|
637
962
|
}), target);
|
|
638
963
|
}
|
|
964
|
+
class StandardSchemaValidationError extends BaseNgValidationError {
|
|
965
|
+
issue;
|
|
966
|
+
kind = 'standardSchema';
|
|
967
|
+
constructor(issue, options) {
|
|
968
|
+
super(options);
|
|
969
|
+
this.issue = issue;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
639
972
|
|
|
640
973
|
function validateHttp(path, opts) {
|
|
641
974
|
validateAsync(path, {
|
|
@@ -658,6 +991,7 @@ function debounceForDuration(durationInMilliseconds) {
|
|
|
658
991
|
let timeoutId;
|
|
659
992
|
const onAbort = () => {
|
|
660
993
|
clearTimeout(timeoutId);
|
|
994
|
+
resolve();
|
|
661
995
|
};
|
|
662
996
|
timeoutId = setTimeout(() => {
|
|
663
997
|
abortSignal.removeEventListener('abort', onAbort);
|
|
@@ -671,5 +1005,5 @@ function debounceForDuration(durationInMilliseconds) {
|
|
|
671
1005
|
}
|
|
672
1006
|
function immediate() {}
|
|
673
1007
|
|
|
674
|
-
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 };
|
|
675
1009
|
//# sourceMappingURL=signals.mjs.map
|