@ngx-formly/core 6.3.12 → 7.0.0-alpha.1
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/README.md +1 -0
- package/esm2022/json-schema/formly-json-schema.service.mjs +628 -0
- package/esm2022/lib/components/formly.field.mjs +292 -0
- package/esm2022/lib/components/formly.form.mjs +164 -0
- package/{esm2020 → esm2022}/lib/components/formly.template.mjs +8 -8
- package/esm2022/lib/core.config.mjs +36 -0
- package/esm2022/lib/core.mjs +20 -0
- package/esm2022/lib/core.module.mjs +74 -0
- package/esm2022/lib/extensions/core/core.mjs +148 -0
- package/esm2022/lib/extensions/field-expression/field-expression.mjs +250 -0
- package/esm2022/lib/extensions/field-expression/utils.mjs +17 -0
- package/esm2022/lib/extensions/field-form/field-form.mjs +141 -0
- package/esm2022/lib/extensions/field-form/utils.mjs +100 -0
- package/esm2022/lib/extensions/field-validation/field-validation.mjs +135 -0
- package/esm2022/lib/extensions/index.mjs +2 -0
- package/esm2022/lib/models/fieldconfig.cache.mjs +2 -0
- package/esm2022/lib/models/fieldconfig.mjs +2 -0
- package/esm2022/lib/services/formly.builder.mjs +100 -0
- package/esm2022/lib/services/formly.config.mjs +229 -0
- package/esm2022/lib/templates/field-array.type.mjs +84 -0
- package/esm2022/lib/templates/field-template.type.mjs +34 -0
- package/esm2022/lib/templates/field.type.mjs +57 -0
- package/{esm2020 → esm2022}/lib/templates/field.wrapper.mjs +4 -4
- package/esm2022/lib/templates/formly.attributes.mjs +187 -0
- package/{esm2020 → esm2022}/lib/templates/formly.group.mjs +8 -8
- package/esm2022/lib/templates/formly.validation-message.mjs +69 -0
- package/esm2022/lib/utils.mjs +312 -0
- package/esm2022/preset/preset-substitution.extension.mjs +30 -0
- package/esm2022/preset/preset.config.mjs +11 -0
- package/esm2022/preset/preset.module.mjs +18 -0
- package/esm2022/select/select-options.pipe.mjs +100 -0
- package/{esm2020 → esm2022}/select/select.module.mjs +5 -5
- package/esm2022/testing/component-factory.mjs +86 -0
- package/{fesm2020 → fesm2022}/ngx-formly-core-json-schema.mjs +16 -16
- package/fesm2022/ngx-formly-core-json-schema.mjs.map +1 -0
- package/fesm2022/ngx-formly-core-preset.mjs +62 -0
- package/fesm2022/ngx-formly-core-preset.mjs.map +1 -0
- package/{fesm2020 → fesm2022}/ngx-formly-core-select.mjs +7 -7
- package/{fesm2020 → fesm2022}/ngx-formly-core-select.mjs.map +1 -1
- package/{fesm2020 → fesm2022}/ngx-formly-core-testing.mjs +5 -4
- package/fesm2022/ngx-formly-core-testing.mjs.map +1 -0
- package/{fesm2020 → fesm2022}/ngx-formly-core.mjs +1747 -1702
- package/fesm2022/ngx-formly-core.mjs.map +1 -0
- package/lib/components/formly.field.d.ts +5 -1
- package/lib/components/formly.form.d.ts +8 -4
- package/lib/components/formly.template.d.ts +1 -1
- package/lib/core.config.d.ts +10 -0
- package/lib/core.d.ts +4 -3
- package/lib/core.module.d.ts +2 -5
- package/lib/extensions/field-expression/utils.d.ts +1 -1
- package/lib/extensions/index.d.ts +1 -0
- package/lib/models/config.d.ts +1 -1
- package/lib/models/fieldconfig.cache.d.ts +3 -3
- package/lib/models/fieldconfig.d.ts +8 -7
- package/lib/services/formly.builder.d.ts +5 -5
- package/lib/services/formly.config.d.ts +3 -9
- package/lib/templates/field-array.type.d.ts +3 -3
- package/lib/templates/field-template.type.d.ts +1 -1
- package/lib/templates/field.type.d.ts +5 -5
- package/lib/templates/field.wrapper.d.ts +1 -1
- package/lib/templates/formly.attributes.d.ts +1 -1
- package/lib/templates/formly.group.d.ts +1 -1
- package/lib/templates/formly.validation-message.d.ts +1 -1
- package/lib/utils.d.ts +5 -5
- package/package.json +23 -37
- package/preset/preset.config.d.ts +2 -0
- package/select/select-options.pipe.d.ts +1 -1
- package/testing/component-factory.d.ts +2 -2
- package/esm2020/json-schema/formly-json-schema.service.mjs +0 -628
- package/esm2020/lib/components/formly.field.mjs +0 -284
- package/esm2020/lib/components/formly.form.mjs +0 -147
- package/esm2020/lib/core.mjs +0 -19
- package/esm2020/lib/core.module.mjs +0 -91
- package/esm2020/lib/extensions/core/core.mjs +0 -148
- package/esm2020/lib/extensions/field-expression/field-expression.mjs +0 -250
- package/esm2020/lib/extensions/field-expression/utils.mjs +0 -17
- package/esm2020/lib/extensions/field-form/field-form.mjs +0 -141
- package/esm2020/lib/extensions/field-form/utils.mjs +0 -100
- package/esm2020/lib/extensions/field-validation/field-validation.mjs +0 -135
- package/esm2020/lib/models/fieldconfig.cache.mjs +0 -2
- package/esm2020/lib/models/fieldconfig.mjs +0 -2
- package/esm2020/lib/services/formly.builder.mjs +0 -93
- package/esm2020/lib/services/formly.config.mjs +0 -229
- package/esm2020/lib/templates/field-array.type.mjs +0 -84
- package/esm2020/lib/templates/field-template.type.mjs +0 -34
- package/esm2020/lib/templates/field.type.mjs +0 -57
- package/esm2020/lib/templates/formly.attributes.mjs +0 -187
- package/esm2020/lib/templates/formly.validation-message.mjs +0 -69
- package/esm2020/lib/utils.mjs +0 -312
- package/esm2020/preset/preset-substitution.extension.mjs +0 -30
- package/esm2020/preset/preset.module.mjs +0 -32
- package/esm2020/select/select-options.pipe.mjs +0 -100
- package/esm2020/testing/component-factory.mjs +0 -85
- package/fesm2015/ngx-formly-core-json-schema.mjs +0 -615
- package/fesm2015/ngx-formly-core-json-schema.mjs.map +0 -1
- package/fesm2015/ngx-formly-core-preset.mjs +0 -69
- package/fesm2015/ngx-formly-core-preset.mjs.map +0 -1
- package/fesm2015/ngx-formly-core-select.mjs +0 -120
- package/fesm2015/ngx-formly-core-select.mjs.map +0 -1
- package/fesm2015/ngx-formly-core-testing.mjs +0 -87
- package/fesm2015/ngx-formly-core-testing.mjs.map +0 -1
- package/fesm2015/ngx-formly-core.mjs +0 -2417
- package/fesm2015/ngx-formly-core.mjs.map +0 -1
- package/fesm2020/ngx-formly-core-json-schema.mjs.map +0 -1
- package/fesm2020/ngx-formly-core-preset.mjs +0 -67
- package/fesm2020/ngx-formly-core-preset.mjs.map +0 -1
- package/fesm2020/ngx-formly-core-testing.mjs.map +0 -1
- package/fesm2020/ngx-formly-core.mjs.map +0 -1
- package/json-schema/package.json +0 -10
- package/preset/package.json +0 -10
- package/select/package.json +0 -10
- package/testing/package.json +0 -10
- /package/{esm2020 → esm2022}/json-schema/ngx-formly-core-json-schema.mjs +0 -0
- /package/{esm2020 → esm2022}/json-schema/public_api.mjs +0 -0
- /package/{esm2020 → esm2022}/lib/models/config.mjs +0 -0
- /package/{esm2020 → esm2022}/lib/models/index.mjs +0 -0
- /package/{esm2020 → esm2022}/ngx-formly-core.mjs +0 -0
- /package/{esm2020 → esm2022}/preset/ngx-formly-core-preset.mjs +0 -0
- /package/{esm2020 → esm2022}/preset/public_api.mjs +0 -0
- /package/{esm2020 → esm2022}/public_api.mjs +0 -0
- /package/{esm2020 → esm2022}/select/ngx-formly-core-select.mjs +0 -0
- /package/{esm2020 → esm2022}/select/public_api.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/ngx-formly-core-testing.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/public_api.mjs +0 -0
- /package/{ngx-formly-core.d.ts → index.d.ts} +0 -0
- /package/json-schema/{ngx-formly-core-json-schema.d.ts → index.d.ts} +0 -0
- /package/preset/{ngx-formly-core-preset.d.ts → index.d.ts} +0 -0
- /package/select/{ngx-formly-core-select.d.ts → index.d.ts} +0 -0
- /package/testing/{ngx-formly-core-testing.d.ts → index.d.ts} +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Type, TemplateRef, ComponentRef, ChangeDetectorRef, ɵNoopNgZone, VERSION,
|
|
2
|
+
import { Type, TemplateRef, ComponentRef, ChangeDetectorRef, ɵNoopNgZone as _NoopNgZone, VERSION, Input, ViewChildren, Directive, ChangeDetectionStrategy, Component, Injectable, ViewContainerRef, ViewChild, Optional, InjectionToken, Inject, EventEmitter, ContentChildren, Output, NgModule } from '@angular/core';
|
|
3
|
+
import { isObservable, Observable, Subject, of, merge } from 'rxjs';
|
|
3
4
|
import * as i2 from '@angular/forms';
|
|
4
|
-
import { AbstractControl,
|
|
5
|
-
import {
|
|
6
|
-
import { map, distinctUntilChanged, startWith, debounceTime, filter, switchMap, take, tap } from 'rxjs/operators';
|
|
7
|
-
import * as i2$1 from '@angular/common';
|
|
8
|
-
import { DOCUMENT, CommonModule } from '@angular/common';
|
|
5
|
+
import { AbstractControl, UntypedFormArray, UntypedFormGroup, FormControl, UntypedFormControl, Validators, NgControl } from '@angular/forms';
|
|
6
|
+
import { tap, map, distinctUntilChanged, startWith, debounceTime, filter, switchMap, take } from 'rxjs/operators';
|
|
9
7
|
import * as i1 from '@angular/platform-browser';
|
|
8
|
+
import * as i1$1 from '@angular/common';
|
|
9
|
+
import { DOCUMENT, CommonModule } from '@angular/common';
|
|
10
10
|
|
|
11
11
|
function disableTreeValidityCall(form, callback) {
|
|
12
12
|
const _updateTreeValidity = form._updateTreeValidity.bind(form);
|
|
@@ -299,7 +299,7 @@ function markFieldForCheck(field) {
|
|
|
299
299
|
});
|
|
300
300
|
}
|
|
301
301
|
function isNoopNgZone(ngZone) {
|
|
302
|
-
return ngZone instanceof
|
|
302
|
+
return ngZone instanceof _NoopNgZone;
|
|
303
303
|
}
|
|
304
304
|
function isHiddenField(field) {
|
|
305
305
|
const isHidden = (f) => f.hide || f.expressions?.hide || f.hideExpression;
|
|
@@ -314,392 +314,96 @@ function isHiddenField(field) {
|
|
|
314
314
|
return !setDefaultValue;
|
|
315
315
|
}
|
|
316
316
|
function isSignalRequired() {
|
|
317
|
-
return +VERSION.major
|
|
317
|
+
return +VERSION.major >= 18 && +VERSION.minor >= 1;
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
const FORMLY_CONFIG = new InjectionToken('FORMLY_CONFIG');
|
|
324
|
-
/**
|
|
325
|
-
* Maintains list of formly config options. This can be used to register new field type.
|
|
326
|
-
*/
|
|
327
|
-
class FormlyConfig {
|
|
328
|
-
constructor() {
|
|
329
|
-
this.types = {};
|
|
330
|
-
this.validators = {};
|
|
331
|
-
this.wrappers = {};
|
|
332
|
-
this.messages = {};
|
|
333
|
-
this.extras = {
|
|
334
|
-
checkExpressionOn: 'modelChange',
|
|
335
|
-
lazyRender: true,
|
|
336
|
-
resetFieldOnHide: true,
|
|
337
|
-
renderFormlyFieldElement: true,
|
|
338
|
-
showError(field) {
|
|
339
|
-
return (field.formControl?.invalid &&
|
|
340
|
-
(field.formControl?.touched || field.options.parentForm?.submitted || !!field.field.validation?.show));
|
|
341
|
-
},
|
|
342
|
-
};
|
|
343
|
-
this.extensions = {};
|
|
344
|
-
this.presets = {};
|
|
345
|
-
this.extensionsByPriority = {};
|
|
320
|
+
function evalStringExpression(expression, argNames) {
|
|
321
|
+
try {
|
|
322
|
+
return Function(...argNames, `return ${expression};`);
|
|
346
323
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
config.types.forEach((type) => this.setType(type));
|
|
350
|
-
}
|
|
351
|
-
if (config.validators) {
|
|
352
|
-
config.validators.forEach((validator) => this.setValidator(validator));
|
|
353
|
-
}
|
|
354
|
-
if (config.wrappers) {
|
|
355
|
-
config.wrappers.forEach((wrapper) => this.setWrapper(wrapper));
|
|
356
|
-
}
|
|
357
|
-
if (config.validationMessages) {
|
|
358
|
-
config.validationMessages.forEach((validation) => this.addValidatorMessage(validation.name, validation.message));
|
|
359
|
-
}
|
|
360
|
-
if (config.extensions) {
|
|
361
|
-
this.setSortedExtensions(config.extensions);
|
|
362
|
-
}
|
|
363
|
-
if (config.extras) {
|
|
364
|
-
this.extras = { ...this.extras, ...config.extras };
|
|
365
|
-
}
|
|
366
|
-
if (config.presets) {
|
|
367
|
-
this.presets = {
|
|
368
|
-
...this.presets,
|
|
369
|
-
...config.presets.reduce((acc, curr) => ({ ...acc, [curr.name]: curr.config }), {}),
|
|
370
|
-
};
|
|
371
|
-
}
|
|
324
|
+
catch (error) {
|
|
325
|
+
console.error(error);
|
|
372
326
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
setType(options) {
|
|
378
|
-
if (Array.isArray(options)) {
|
|
379
|
-
options.forEach((option) => this.setType(option));
|
|
380
|
-
}
|
|
381
|
-
else {
|
|
382
|
-
if (!this.types[options.name]) {
|
|
383
|
-
this.types[options.name] = { name: options.name };
|
|
384
|
-
}
|
|
385
|
-
['component', 'extends', 'defaultOptions', 'wrappers'].forEach((prop) => {
|
|
386
|
-
if (options.hasOwnProperty(prop)) {
|
|
387
|
-
this.types[options.name][prop] = options[prop];
|
|
388
|
-
}
|
|
389
|
-
});
|
|
390
|
-
}
|
|
327
|
+
}
|
|
328
|
+
function evalExpression(expression, thisArg, argVal) {
|
|
329
|
+
if (typeof expression === 'function') {
|
|
330
|
+
return expression.apply(thisArg, argVal);
|
|
391
331
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
return { component: name, name: name.prototype.constructor.name };
|
|
395
|
-
}
|
|
396
|
-
if (!this.types[name]) {
|
|
397
|
-
if (throwIfNotFound) {
|
|
398
|
-
throw new Error(`[Formly Error] The type "${name}" could not be found. Please make sure that is registered through the FormlyModule declaration.`);
|
|
399
|
-
}
|
|
400
|
-
return null;
|
|
401
|
-
}
|
|
402
|
-
this.mergeExtendedType(name);
|
|
403
|
-
return this.types[name];
|
|
332
|
+
else {
|
|
333
|
+
return expression ? true : false;
|
|
404
334
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
reverseDeepMerge(field, type.defaultOptions);
|
|
413
|
-
}
|
|
414
|
-
const extendDefaults = type.extends && this.getType(type.extends).defaultOptions;
|
|
415
|
-
if (extendDefaults) {
|
|
416
|
-
reverseDeepMerge(field, extendDefaults);
|
|
417
|
-
}
|
|
418
|
-
if (field?.optionsTypes) {
|
|
419
|
-
field.optionsTypes.forEach((option) => {
|
|
420
|
-
const defaultOptions = this.getType(option).defaultOptions;
|
|
421
|
-
if (defaultOptions) {
|
|
422
|
-
reverseDeepMerge(field, defaultOptions);
|
|
423
|
-
}
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
const componentRef = this.resolveFieldTypeRef(field);
|
|
427
|
-
if (componentRef?.instance?.defaultOptions) {
|
|
428
|
-
reverseDeepMerge(field, componentRef.instance.defaultOptions);
|
|
429
|
-
}
|
|
430
|
-
if (!field.wrappers && type.wrappers) {
|
|
431
|
-
field.wrappers = [...type.wrappers];
|
|
432
|
-
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function unregisterControl(field, emitEvent = false) {
|
|
338
|
+
const control = field.formControl;
|
|
339
|
+
const fieldIndex = control._fields ? control._fields.indexOf(field) : -1;
|
|
340
|
+
if (fieldIndex !== -1) {
|
|
341
|
+
control._fields.splice(fieldIndex, 1);
|
|
433
342
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
if (!type) {
|
|
438
|
-
return null;
|
|
439
|
-
}
|
|
440
|
-
if (!type.component || type._componentRef) {
|
|
441
|
-
return type._componentRef;
|
|
442
|
-
}
|
|
443
|
-
const { _viewContainerRef, _injector } = field.options;
|
|
444
|
-
if (!_viewContainerRef || !_injector) {
|
|
445
|
-
return null;
|
|
446
|
-
}
|
|
447
|
-
const componentRef = _viewContainerRef.createComponent(type.component, { injector: _injector });
|
|
448
|
-
defineHiddenProp(type, '_componentRef', componentRef);
|
|
449
|
-
try {
|
|
450
|
-
componentRef.destroy();
|
|
451
|
-
}
|
|
452
|
-
catch (e) {
|
|
453
|
-
console.error(`An error occurred while destroying the Formly component type "${field.type}"`, e);
|
|
454
|
-
}
|
|
455
|
-
return type._componentRef;
|
|
343
|
+
const form = control.parent;
|
|
344
|
+
if (!form) {
|
|
345
|
+
return;
|
|
456
346
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
});
|
|
347
|
+
const opts = { emitEvent };
|
|
348
|
+
if (form instanceof UntypedFormArray) {
|
|
349
|
+
const key = form.controls.findIndex((c) => c === control);
|
|
350
|
+
if (key !== -1) {
|
|
351
|
+
form.removeAt(key, opts);
|
|
463
352
|
}
|
|
464
353
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
throw new Error(`[Formly Error] The wrapper "${name}" could not be found. Please make sure that is registered through the FormlyModule declaration.`);
|
|
354
|
+
else if (form instanceof UntypedFormGroup) {
|
|
355
|
+
const paths = getKeyPath(field);
|
|
356
|
+
const key = paths[paths.length - 1];
|
|
357
|
+
if (form.get([key]) === control) {
|
|
358
|
+
form.removeControl(key, opts);
|
|
471
359
|
}
|
|
472
|
-
return this.wrappers[name];
|
|
473
360
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
if (!this.types[type].wrappers) {
|
|
480
|
-
this.types[type].wrappers = [];
|
|
481
|
-
}
|
|
482
|
-
if (this.types[type].wrappers.indexOf(name) === -1) {
|
|
483
|
-
this.types[type].wrappers.push(name);
|
|
484
|
-
}
|
|
361
|
+
control.setParent(null);
|
|
362
|
+
}
|
|
363
|
+
function findControl(field) {
|
|
364
|
+
if (field.formControl) {
|
|
365
|
+
return field.formControl;
|
|
485
366
|
}
|
|
486
|
-
|
|
487
|
-
|
|
367
|
+
if (field.shareFormControl === false) {
|
|
368
|
+
return null;
|
|
488
369
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
370
|
+
return field.form?.get(getKeyPath(field));
|
|
371
|
+
}
|
|
372
|
+
function registerControl(field, control, emitEvent = false) {
|
|
373
|
+
control = control || field.formControl;
|
|
374
|
+
if (!control._fields) {
|
|
375
|
+
defineHiddenProp(control, '_fields', []);
|
|
494
376
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
377
|
+
if (control._fields.indexOf(field) === -1) {
|
|
378
|
+
control._fields.push(field);
|
|
379
|
+
}
|
|
380
|
+
if (!field.formControl && control) {
|
|
381
|
+
defineHiddenProp(field, 'formControl', control);
|
|
382
|
+
control.setValidators(null);
|
|
383
|
+
control.setAsyncValidators(null);
|
|
384
|
+
field.props.disabled = !!field.props.disabled;
|
|
385
|
+
const disabledObserver = observe(field, ['props', 'disabled'], ({ firstChange, currentValue }) => {
|
|
386
|
+
if (!firstChange) {
|
|
387
|
+
currentValue ? field.formControl.disable() : field.formControl.enable();
|
|
502
388
|
}
|
|
389
|
+
});
|
|
390
|
+
if (control instanceof FormControl) {
|
|
391
|
+
control.registerOnDisabledChange(disabledObserver.setValue);
|
|
503
392
|
}
|
|
504
393
|
}
|
|
505
|
-
|
|
506
|
-
return
|
|
394
|
+
if (!field.form || !hasKey(field)) {
|
|
395
|
+
return;
|
|
507
396
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
...this.extensionsByPriority[priority],
|
|
514
|
-
[extensionOption.name]: extensionOption.extension,
|
|
515
|
-
};
|
|
516
|
-
});
|
|
517
|
-
// flatten extensions object with sorted keys
|
|
518
|
-
this.extensions = Object.keys(this.extensionsByPriority)
|
|
519
|
-
.map(Number)
|
|
520
|
-
.sort((a, b) => a - b)
|
|
521
|
-
.reduce((acc, prio) => ({
|
|
522
|
-
...acc,
|
|
523
|
-
...this.extensionsByPriority[prio],
|
|
524
|
-
}), {});
|
|
525
|
-
}
|
|
526
|
-
mergeExtendedType(name) {
|
|
527
|
-
if (!this.types[name].extends) {
|
|
528
|
-
return;
|
|
529
|
-
}
|
|
530
|
-
const extendedType = this.getType(this.types[name].extends);
|
|
531
|
-
if (!this.types[name].component) {
|
|
532
|
-
this.types[name].component = extendedType.component;
|
|
533
|
-
}
|
|
534
|
-
if (!this.types[name].wrappers) {
|
|
535
|
-
this.types[name].wrappers = extendedType.wrappers;
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
FormlyConfig.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
540
|
-
FormlyConfig.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyConfig, providedIn: 'root' });
|
|
541
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyConfig, decorators: [{
|
|
542
|
-
type: Injectable,
|
|
543
|
-
args: [{ providedIn: 'root' }]
|
|
544
|
-
}] });
|
|
545
|
-
|
|
546
|
-
class FormlyFormBuilder {
|
|
547
|
-
constructor(config, injector, viewContainerRef, parentForm) {
|
|
548
|
-
this.config = config;
|
|
549
|
-
this.injector = injector;
|
|
550
|
-
this.viewContainerRef = viewContainerRef;
|
|
551
|
-
this.parentForm = parentForm;
|
|
552
|
-
}
|
|
553
|
-
buildForm(form, fieldGroup = [], model, options) {
|
|
554
|
-
this.build({ fieldGroup, model, form, options });
|
|
555
|
-
}
|
|
556
|
-
build(field) {
|
|
557
|
-
if (!this.config.extensions.core) {
|
|
558
|
-
throw new Error('NgxFormly: missing `forRoot()` call. use `forRoot()` when registering the `FormlyModule`.');
|
|
559
|
-
}
|
|
560
|
-
if (!field.parent) {
|
|
561
|
-
this._setOptions(field);
|
|
562
|
-
}
|
|
563
|
-
disableTreeValidityCall(field.form, () => {
|
|
564
|
-
this._build(field);
|
|
565
|
-
// TODO: add test for https://github.com/ngx-formly/ngx-formly/issues/3910
|
|
566
|
-
if (!field.parent || field.fieldArray) {
|
|
567
|
-
// detect changes early to avoid reset value by hidden fields
|
|
568
|
-
const options = field.options;
|
|
569
|
-
if (field.parent && isHiddenField(field)) {
|
|
570
|
-
// when hide is used in expression set defaul value will not be set until detect hide changes
|
|
571
|
-
// which causes default value not set on new item is added
|
|
572
|
-
options._hiddenFieldsForCheck?.push({ field, default: false });
|
|
573
|
-
}
|
|
574
|
-
options.checkExpressions?.(field, true);
|
|
575
|
-
options._detectChanges?.(field);
|
|
576
|
-
}
|
|
577
|
-
});
|
|
578
|
-
}
|
|
579
|
-
_build(field) {
|
|
580
|
-
if (!field) {
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
583
|
-
const extensions = Object.values(this.config.extensions);
|
|
584
|
-
extensions.forEach((extension) => extension.prePopulate?.(field));
|
|
585
|
-
extensions.forEach((extension) => extension.onPopulate?.(field));
|
|
586
|
-
field.fieldGroup?.forEach((f) => this._build(f));
|
|
587
|
-
extensions.forEach((extension) => extension.postPopulate?.(field));
|
|
588
|
-
}
|
|
589
|
-
_setOptions(field) {
|
|
590
|
-
field.form = field.form || new FormGroup({});
|
|
591
|
-
field.model = field.model || {};
|
|
592
|
-
field.options = field.options || {};
|
|
593
|
-
const options = field.options;
|
|
594
|
-
if (!options._viewContainerRef) {
|
|
595
|
-
defineHiddenProp(options, '_viewContainerRef', this.viewContainerRef);
|
|
596
|
-
}
|
|
597
|
-
if (!options._injector) {
|
|
598
|
-
defineHiddenProp(options, '_injector', this.injector);
|
|
599
|
-
}
|
|
600
|
-
if (!options.build) {
|
|
601
|
-
options._buildForm = () => {
|
|
602
|
-
console.warn(`Formly: 'options._buildForm' is deprecated since v6.0, use 'options.build' instead.`);
|
|
603
|
-
this.build(field);
|
|
604
|
-
};
|
|
605
|
-
options.build = (f = field) => {
|
|
606
|
-
this.build(f);
|
|
607
|
-
return f;
|
|
608
|
-
};
|
|
609
|
-
}
|
|
610
|
-
if (!options.parentForm && this.parentForm) {
|
|
611
|
-
defineHiddenProp(options, 'parentForm', this.parentForm);
|
|
612
|
-
if (!isSignalRequired()) {
|
|
613
|
-
observe(options, ['parentForm', 'submitted'], ({ firstChange }) => {
|
|
614
|
-
if (!firstChange) {
|
|
615
|
-
options.detectChanges(field);
|
|
616
|
-
}
|
|
617
|
-
});
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
FormlyFormBuilder.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyFormBuilder, deps: [{ token: FormlyConfig }, { token: i0.Injector }, { token: i0.ViewContainerRef, optional: true }, { token: i2.FormGroupDirective, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
623
|
-
FormlyFormBuilder.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyFormBuilder, providedIn: 'root' });
|
|
624
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyFormBuilder, decorators: [{
|
|
625
|
-
type: Injectable,
|
|
626
|
-
args: [{ providedIn: 'root' }]
|
|
627
|
-
}], ctorParameters: function () { return [{ type: FormlyConfig }, { type: i0.Injector }, { type: i0.ViewContainerRef, decorators: [{
|
|
628
|
-
type: Optional
|
|
629
|
-
}] }, { type: i2.FormGroupDirective, decorators: [{
|
|
630
|
-
type: Optional
|
|
631
|
-
}] }]; } });
|
|
632
|
-
|
|
633
|
-
function unregisterControl(field, emitEvent = false) {
|
|
634
|
-
const control = field.formControl;
|
|
635
|
-
const fieldIndex = control._fields ? control._fields.indexOf(field) : -1;
|
|
636
|
-
if (fieldIndex !== -1) {
|
|
637
|
-
control._fields.splice(fieldIndex, 1);
|
|
638
|
-
}
|
|
639
|
-
const form = control.parent;
|
|
640
|
-
if (!form) {
|
|
641
|
-
return;
|
|
642
|
-
}
|
|
643
|
-
const opts = { emitEvent };
|
|
644
|
-
if (form instanceof FormArray) {
|
|
645
|
-
const key = form.controls.findIndex((c) => c === control);
|
|
646
|
-
if (key !== -1) {
|
|
647
|
-
form.removeAt(key, opts);
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
else if (form instanceof FormGroup) {
|
|
651
|
-
const paths = getKeyPath(field);
|
|
652
|
-
const key = paths[paths.length - 1];
|
|
653
|
-
if (form.get([key]) === control) {
|
|
654
|
-
form.removeControl(key, opts);
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
control.setParent(null);
|
|
658
|
-
}
|
|
659
|
-
function findControl(field) {
|
|
660
|
-
if (field.formControl) {
|
|
661
|
-
return field.formControl;
|
|
662
|
-
}
|
|
663
|
-
if (field.shareFormControl === false) {
|
|
664
|
-
return null;
|
|
665
|
-
}
|
|
666
|
-
return field.form?.get(getKeyPath(field));
|
|
667
|
-
}
|
|
668
|
-
function registerControl(field, control, emitEvent = false) {
|
|
669
|
-
control = control || field.formControl;
|
|
670
|
-
if (!control._fields) {
|
|
671
|
-
defineHiddenProp(control, '_fields', []);
|
|
672
|
-
}
|
|
673
|
-
if (control._fields.indexOf(field) === -1) {
|
|
674
|
-
control._fields.push(field);
|
|
675
|
-
}
|
|
676
|
-
if (!field.formControl && control) {
|
|
677
|
-
defineHiddenProp(field, 'formControl', control);
|
|
678
|
-
control.setValidators(null);
|
|
679
|
-
control.setAsyncValidators(null);
|
|
680
|
-
field.props.disabled = !!field.props.disabled;
|
|
681
|
-
const disabledObserver = observe(field, ['props', 'disabled'], ({ firstChange, currentValue }) => {
|
|
682
|
-
if (!firstChange) {
|
|
683
|
-
currentValue ? field.formControl.disable() : field.formControl.enable();
|
|
684
|
-
}
|
|
685
|
-
});
|
|
686
|
-
if (control instanceof FormControl) {
|
|
687
|
-
control.registerOnDisabledChange(disabledObserver.setValue);
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
if (!field.form || !hasKey(field)) {
|
|
691
|
-
return;
|
|
692
|
-
}
|
|
693
|
-
let form = field.form;
|
|
694
|
-
const paths = getKeyPath(field);
|
|
695
|
-
const value = getFieldValue(field);
|
|
696
|
-
if (!(isNil(control.value) && isNil(value)) && control.value !== value && control instanceof FormControl) {
|
|
697
|
-
control.patchValue(value);
|
|
397
|
+
let form = field.form;
|
|
398
|
+
const paths = getKeyPath(field);
|
|
399
|
+
const value = getFieldValue(field);
|
|
400
|
+
if (!(isNil(control.value) && isNil(value)) && control.value !== value && control instanceof FormControl) {
|
|
401
|
+
control.patchValue(value);
|
|
698
402
|
}
|
|
699
403
|
for (let i = 0; i < paths.length - 1; i++) {
|
|
700
404
|
const path = paths[i];
|
|
701
405
|
if (!form.get([path])) {
|
|
702
|
-
form.setControl(path, new
|
|
406
|
+
form.setControl(path, new UntypedFormGroup({}), { emitEvent });
|
|
703
407
|
}
|
|
704
408
|
form = form.get([path]);
|
|
705
409
|
}
|
|
@@ -723,630 +427,666 @@ function clearControl(form) {
|
|
|
723
427
|
delete form?._fields;
|
|
724
428
|
form.setValidators(null);
|
|
725
429
|
form.setAsyncValidators(null);
|
|
726
|
-
if (form instanceof
|
|
430
|
+
if (form instanceof UntypedFormGroup || form instanceof UntypedFormArray) {
|
|
727
431
|
Object.values(form.controls).forEach((c) => clearControl(c));
|
|
728
432
|
}
|
|
729
433
|
}
|
|
730
434
|
|
|
731
|
-
class
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
ngOnChanges() {
|
|
736
|
-
this.name = this.name || 'formly-group';
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
FormlyTemplate.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyTemplate, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
740
|
-
FormlyTemplate.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: FormlyTemplate, selector: "[formlyTemplate]", inputs: { name: ["formlyTemplate", "name"] }, usesOnChanges: true, ngImport: i0 });
|
|
741
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyTemplate, decorators: [{
|
|
742
|
-
type: Directive,
|
|
743
|
-
args: [{ selector: '[formlyTemplate]' }]
|
|
744
|
-
}], ctorParameters: function () { return [{ type: i0.TemplateRef }]; }, propDecorators: { name: [{
|
|
745
|
-
type: Input,
|
|
746
|
-
args: ['formlyTemplate']
|
|
747
|
-
}] } });
|
|
748
|
-
// workarround for https://github.com/angular/angular/issues/43227#issuecomment-904173738
|
|
749
|
-
class FormlyFieldTemplates {
|
|
750
|
-
}
|
|
751
|
-
FormlyFieldTemplates.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyFieldTemplates, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
752
|
-
FormlyFieldTemplates.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyFieldTemplates });
|
|
753
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyFieldTemplates, decorators: [{
|
|
754
|
-
type: Injectable
|
|
755
|
-
}] });
|
|
756
|
-
|
|
757
|
-
/**
|
|
758
|
-
* The `<formly-field>` component is used to render the UI widget (layout + type) of a given `field`.
|
|
759
|
-
*/
|
|
760
|
-
class FormlyField {
|
|
761
|
-
constructor(config, renderer, _elementRef, hostContainerRef, form) {
|
|
762
|
-
this.config = config;
|
|
763
|
-
this.renderer = renderer;
|
|
764
|
-
this._elementRef = _elementRef;
|
|
765
|
-
this.hostContainerRef = hostContainerRef;
|
|
766
|
-
this.form = form;
|
|
767
|
-
this.hostObservers = [];
|
|
768
|
-
this.componentRefs = [];
|
|
769
|
-
this.hooksObservers = [];
|
|
770
|
-
this.detectFieldBuild = false;
|
|
771
|
-
this.valueChangesUnsubscribe = () => { };
|
|
772
|
-
}
|
|
773
|
-
get containerRef() {
|
|
774
|
-
return this.config.extras.renderFormlyFieldElement ? this.viewContainerRef : this.hostContainerRef;
|
|
775
|
-
}
|
|
776
|
-
get elementRef() {
|
|
777
|
-
if (this.config.extras.renderFormlyFieldElement) {
|
|
778
|
-
return this._elementRef;
|
|
435
|
+
class FieldExpressionExtension {
|
|
436
|
+
onPopulate(field) {
|
|
437
|
+
if (field._expressions) {
|
|
438
|
+
return;
|
|
779
439
|
}
|
|
780
|
-
|
|
781
|
-
|
|
440
|
+
// cache built expression
|
|
441
|
+
defineHiddenProp(field, '_expressions', {});
|
|
442
|
+
observe(field, ['hide'], ({ currentValue, firstChange }) => {
|
|
443
|
+
defineHiddenProp(field, '_hide', !!currentValue);
|
|
444
|
+
if (!firstChange || (firstChange && currentValue === true)) {
|
|
445
|
+
field.props.hidden = currentValue;
|
|
446
|
+
field.options._hiddenFieldsForCheck.push({ field });
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
if (field.hideExpression) {
|
|
450
|
+
observe(field, ['hideExpression'], ({ currentValue: expr }) => {
|
|
451
|
+
field._expressions.hide = this.parseExpressions(field, 'hide', typeof expr === 'boolean' ? () => expr : expr);
|
|
452
|
+
});
|
|
782
453
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
454
|
+
const evalExpr = (key, expr) => {
|
|
455
|
+
if (typeof expr === 'string' || isFunction(expr)) {
|
|
456
|
+
field._expressions[key] = this.parseExpressions(field, key, expr);
|
|
457
|
+
}
|
|
458
|
+
else if (expr instanceof Observable) {
|
|
459
|
+
field._expressions[key] = {
|
|
460
|
+
value$: expr.pipe(tap((v) => {
|
|
461
|
+
this.evalExpr(field, key, v);
|
|
462
|
+
field.options._detectChanges(field);
|
|
463
|
+
})),
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
field.expressions = field.expressions || {};
|
|
468
|
+
for (const key of Object.keys(field.expressions)) {
|
|
469
|
+
observe(field, ['expressions', key], ({ currentValue: expr }) => {
|
|
470
|
+
evalExpr(key, isFunction(expr) ? (...args) => expr(field, args[3]) : expr);
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
field.expressionProperties = field.expressionProperties || {};
|
|
474
|
+
for (const key of Object.keys(field.expressionProperties)) {
|
|
475
|
+
observe(field, ['expressionProperties', key], ({ currentValue }) => evalExpr(key, currentValue));
|
|
794
476
|
}
|
|
795
477
|
}
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
ngOnChanges(changes) {
|
|
800
|
-
this.triggerHook('onChanges', changes);
|
|
801
|
-
}
|
|
802
|
-
ngOnDestroy() {
|
|
803
|
-
this.resetRefs(this.field);
|
|
804
|
-
this.hostObservers.forEach((hostObserver) => hostObserver.unsubscribe());
|
|
805
|
-
this.hooksObservers.forEach((unsubscribe) => unsubscribe());
|
|
806
|
-
this.valueChangesUnsubscribe();
|
|
807
|
-
this.triggerHook('onDestroy');
|
|
808
|
-
}
|
|
809
|
-
renderField(containerRef, f, wrappers = []) {
|
|
810
|
-
if (this.containerRef === containerRef) {
|
|
811
|
-
this.resetRefs(this.field);
|
|
812
|
-
this.containerRef.clear();
|
|
813
|
-
wrappers = this.field?.wrappers;
|
|
478
|
+
postPopulate(field) {
|
|
479
|
+
if (field.parent) {
|
|
480
|
+
return;
|
|
814
481
|
}
|
|
815
|
-
if (
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
observe(ref.instance, ['fieldComponent'], ({ currentValue, previousValue, firstChange }) => {
|
|
821
|
-
if (currentValue) {
|
|
822
|
-
if (previousValue && previousValue._lContainer === currentValue._lContainer) {
|
|
823
|
-
return;
|
|
824
|
-
}
|
|
825
|
-
const viewRef = previousValue ? previousValue.detach() : null;
|
|
826
|
-
if (viewRef && !viewRef.destroyed) {
|
|
827
|
-
currentValue.insert(viewRef);
|
|
828
|
-
}
|
|
829
|
-
else {
|
|
830
|
-
this.renderField(currentValue, f, wps);
|
|
831
|
-
}
|
|
832
|
-
!firstChange && ref.changeDetectorRef.detectChanges();
|
|
482
|
+
if (!field.options.checkExpressions) {
|
|
483
|
+
let checkLocked = false;
|
|
484
|
+
field.options.checkExpressions = (f, ignoreCache) => {
|
|
485
|
+
if (checkLocked) {
|
|
486
|
+
return;
|
|
833
487
|
}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
}
|
|
846
|
-
|
|
488
|
+
checkLocked = true;
|
|
489
|
+
const fieldChanged = this.checkExpressions(f, ignoreCache);
|
|
490
|
+
const options = field.options;
|
|
491
|
+
options._hiddenFieldsForCheck
|
|
492
|
+
.sort((f) => (f.field.hide ? -1 : 1))
|
|
493
|
+
.forEach((f) => this.changeHideState(f.field, f.field.hide ?? f.default, !ignoreCache));
|
|
494
|
+
options._hiddenFieldsForCheck = [];
|
|
495
|
+
if (fieldChanged) {
|
|
496
|
+
this.checkExpressions(field);
|
|
497
|
+
}
|
|
498
|
+
checkLocked = false;
|
|
499
|
+
};
|
|
500
|
+
field.options._checkField = (f, ignoreCache) => {
|
|
501
|
+
console.warn(`Formly: 'options._checkField' is deprecated since v6.0, use 'options.checkExpressions' instead.`);
|
|
502
|
+
field.options.checkExpressions(f, ignoreCache);
|
|
503
|
+
};
|
|
847
504
|
}
|
|
848
505
|
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
this.hooksObservers.push(() => sub.unsubscribe());
|
|
506
|
+
parseExpressions(field, path, expr) {
|
|
507
|
+
let parentExpression;
|
|
508
|
+
if (field.parent && ['hide', 'props.disabled'].includes(path)) {
|
|
509
|
+
const rootValue = (f) => {
|
|
510
|
+
return path === 'hide' ? f.hide : f.props.disabled;
|
|
511
|
+
};
|
|
512
|
+
parentExpression = () => {
|
|
513
|
+
let root = field.parent;
|
|
514
|
+
while (root.parent && !rootValue(root)) {
|
|
515
|
+
root = root.parent;
|
|
860
516
|
}
|
|
861
|
-
|
|
517
|
+
return rootValue(root);
|
|
518
|
+
};
|
|
862
519
|
}
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
520
|
+
expr = expr || (() => false);
|
|
521
|
+
if (typeof expr === 'string') {
|
|
522
|
+
expr = evalStringExpression(expr, ['model', 'formState', 'field']);
|
|
866
523
|
}
|
|
524
|
+
let currentValue;
|
|
525
|
+
return {
|
|
526
|
+
callback: (ignoreCache) => {
|
|
527
|
+
try {
|
|
528
|
+
const exprValue = evalExpression(parentExpression ? (...args) => parentExpression(field) || expr(...args) : expr, { field }, [field.model, field.options.formState, field, ignoreCache]);
|
|
529
|
+
if (ignoreCache ||
|
|
530
|
+
(currentValue !== exprValue &&
|
|
531
|
+
(!isObject(exprValue) ||
|
|
532
|
+
isObservable(exprValue) ||
|
|
533
|
+
JSON.stringify(exprValue) !== JSON.stringify(currentValue)))) {
|
|
534
|
+
currentValue = exprValue;
|
|
535
|
+
this.evalExpr(field, path, exprValue);
|
|
536
|
+
return true;
|
|
537
|
+
}
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
catch (error) {
|
|
541
|
+
error.message = `[Formly Error] [Expression "${path}"] ${error.message}`;
|
|
542
|
+
throw error;
|
|
543
|
+
}
|
|
544
|
+
},
|
|
545
|
+
};
|
|
867
546
|
}
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
if (ref instanceof ComponentRef) {
|
|
872
|
-
Object.assign(ref.instance, { field });
|
|
547
|
+
checkExpressions(field, ignoreCache = false) {
|
|
548
|
+
if (!field) {
|
|
549
|
+
return false;
|
|
873
550
|
}
|
|
551
|
+
let fieldChanged = false;
|
|
552
|
+
if (field._expressions) {
|
|
553
|
+
for (const key of Object.keys(field._expressions)) {
|
|
554
|
+
field._expressions[key].callback?.(ignoreCache) && (fieldChanged = true);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
field.fieldGroup?.forEach((f) => this.checkExpressions(f, ignoreCache) && (fieldChanged = true));
|
|
558
|
+
return fieldChanged;
|
|
874
559
|
}
|
|
875
|
-
|
|
876
|
-
if (
|
|
877
|
-
|
|
560
|
+
changeDisabledState(field, value) {
|
|
561
|
+
if (field.fieldGroup) {
|
|
562
|
+
field.fieldGroup
|
|
563
|
+
.filter((f) => !f._expressions.hasOwnProperty('props.disabled'))
|
|
564
|
+
.forEach((f) => this.changeDisabledState(f, value));
|
|
878
565
|
}
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
this.detectFieldBuild = true;
|
|
882
|
-
return;
|
|
566
|
+
if (hasKey(field) && field.props.disabled !== value) {
|
|
567
|
+
field.props.disabled = value;
|
|
883
568
|
}
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
569
|
+
}
|
|
570
|
+
changeHideState(field, hide, resetOnHide) {
|
|
571
|
+
if (field.fieldGroup) {
|
|
572
|
+
field.fieldGroup
|
|
573
|
+
.filter((f) => f && !f._expressions.hide)
|
|
574
|
+
.forEach((f) => this.changeHideState(f, hide, resetOnHide));
|
|
575
|
+
}
|
|
576
|
+
if (field.formControl && hasKey(field)) {
|
|
577
|
+
defineHiddenProp(field, '_hide', !!(hide || field.hide));
|
|
578
|
+
const c = field.formControl;
|
|
579
|
+
if (c._fields?.length > 1) {
|
|
580
|
+
updateValidity(c);
|
|
581
|
+
}
|
|
582
|
+
if (hide === true && (!c._fields || c._fields.every((f) => !!f._hide))) {
|
|
583
|
+
unregisterControl(field, true);
|
|
584
|
+
if (resetOnHide && field.resetOnHide) {
|
|
585
|
+
assignFieldValue(field, undefined);
|
|
586
|
+
field.formControl.reset({ value: undefined, disabled: field.formControl.disabled });
|
|
587
|
+
field.options.fieldChanges.next({ value: undefined, field, type: 'valueChanges' });
|
|
588
|
+
if (field.fieldGroup && field.formControl instanceof UntypedFormArray) {
|
|
589
|
+
field.fieldGroup.length = 0;
|
|
894
590
|
}
|
|
895
591
|
}
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
this.renderer.removeAttribute(this.elementRef.nativeElement, 'class');
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
else {
|
|
904
|
-
this.renderField(containerRef, this.field);
|
|
905
|
-
if (this.field.className) {
|
|
906
|
-
this.renderer.setAttribute(this.elementRef.nativeElement, 'class', this.field.className);
|
|
907
|
-
}
|
|
908
|
-
}
|
|
592
|
+
}
|
|
593
|
+
else if (hide === false) {
|
|
594
|
+
if (field.resetOnHide && !isUndefined(field.defaultValue) && isUndefined(getFieldValue(field))) {
|
|
595
|
+
assignFieldValue(field, field.defaultValue);
|
|
909
596
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
if ((!firstChange || (firstChange && currentValue)) &&
|
|
914
|
-
(!this.config.extras.lazyRender || this.field.hide !== true)) {
|
|
915
|
-
this.elementRef && this.renderer.setAttribute(this.elementRef.nativeElement, 'class', currentValue);
|
|
597
|
+
registerControl(field, undefined, true);
|
|
598
|
+
if (field.resetOnHide && field.fieldArray && field.fieldGroup?.length !== field.model?.length) {
|
|
599
|
+
field.options.build(field);
|
|
916
600
|
}
|
|
917
|
-
}
|
|
918
|
-
];
|
|
919
|
-
if (!isSignalRequired()) {
|
|
920
|
-
['touched', 'pristine', 'status'].forEach((prop) => this.hostObservers.push(observe(this.field, ['formControl', prop], ({ firstChange }) => !firstChange && markFieldForCheck(this.field))));
|
|
601
|
+
}
|
|
921
602
|
}
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
this.hostObservers.push(events);
|
|
603
|
+
if (field.options.fieldChanges) {
|
|
604
|
+
field.options.fieldChanges.next({ field, type: 'hidden', value: hide });
|
|
925
605
|
}
|
|
926
606
|
}
|
|
927
|
-
|
|
928
|
-
if (
|
|
929
|
-
|
|
930
|
-
|
|
607
|
+
evalExpr(field, prop, value) {
|
|
608
|
+
if (prop.indexOf('model.') === 0) {
|
|
609
|
+
const key = prop.replace(/^model\./, ''), parent = field.fieldGroup ? field : field.parent;
|
|
610
|
+
let control = field?.key === key ? field.formControl : field.form.get(key);
|
|
611
|
+
if (!control && field.get(key)) {
|
|
612
|
+
control = field.get(key).formControl;
|
|
931
613
|
}
|
|
932
|
-
|
|
933
|
-
|
|
614
|
+
assignFieldValue({ key, parent, model: field.model }, value);
|
|
615
|
+
if (control && !(isNil(control.value) && isNil(value)) && control.value !== value) {
|
|
616
|
+
control.patchValue(value);
|
|
934
617
|
}
|
|
935
|
-
|
|
936
|
-
|
|
618
|
+
}
|
|
619
|
+
else {
|
|
620
|
+
try {
|
|
621
|
+
let target = field;
|
|
622
|
+
const paths = this._evalExpressionPath(field, prop);
|
|
623
|
+
const lastIndex = paths.length - 1;
|
|
624
|
+
for (let i = 0; i < lastIndex; i++) {
|
|
625
|
+
target = target[paths[i]];
|
|
626
|
+
}
|
|
627
|
+
target[paths[lastIndex]] = value;
|
|
937
628
|
}
|
|
938
|
-
|
|
939
|
-
|
|
629
|
+
catch (error) {
|
|
630
|
+
error.message = `[Formly Error] [Expression "${prop}"] ${error.message}`;
|
|
631
|
+
throw error;
|
|
632
|
+
}
|
|
633
|
+
if (['templateOptions.disabled', 'props.disabled'].includes(prop) && hasKey(field)) {
|
|
634
|
+
this.changeDisabledState(field, value);
|
|
940
635
|
}
|
|
941
636
|
}
|
|
942
|
-
this.
|
|
637
|
+
this.emitExpressionChanges(field, prop, value);
|
|
943
638
|
}
|
|
944
|
-
|
|
945
|
-
if (!field) {
|
|
946
|
-
return
|
|
639
|
+
emitExpressionChanges(field, property, value) {
|
|
640
|
+
if (!field.options.fieldChanges) {
|
|
641
|
+
return;
|
|
947
642
|
}
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
previousValue.subscription = null;
|
|
959
|
-
}
|
|
960
|
-
if (isObservable(currentValue.value$)) {
|
|
961
|
-
currentValue.subscription = currentValue.value$.subscribe();
|
|
962
|
-
}
|
|
963
|
-
});
|
|
964
|
-
subscribes.push(() => {
|
|
965
|
-
if (field._expressions[key]?.subscription) {
|
|
966
|
-
field._expressions[key].subscription.unsubscribe();
|
|
967
|
-
}
|
|
968
|
-
expressionObserver.unsubscribe();
|
|
969
|
-
});
|
|
643
|
+
field.options.fieldChanges.next({
|
|
644
|
+
field,
|
|
645
|
+
type: 'expressionChanges',
|
|
646
|
+
property,
|
|
647
|
+
value,
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
_evalExpressionPath(field, prop) {
|
|
651
|
+
if (field._expressions[prop] && field._expressions[prop].paths) {
|
|
652
|
+
return field._expressions[prop].paths;
|
|
970
653
|
}
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
654
|
+
let paths = [];
|
|
655
|
+
if (prop.indexOf('[') === -1) {
|
|
656
|
+
paths = prop.split('.');
|
|
974
657
|
}
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
}), distinctUntilChanged((x, y) => {
|
|
984
|
-
if (x !== y || Array.isArray(x) || isObject(x)) {
|
|
985
|
-
return false;
|
|
986
|
-
}
|
|
987
|
-
return true;
|
|
988
|
-
}));
|
|
989
|
-
if (control.value !== getFieldValue(field)) {
|
|
990
|
-
valueChanges = valueChanges.pipe(startWith(control.value));
|
|
991
|
-
}
|
|
992
|
-
const { updateOn, debounce } = field.modelOptions;
|
|
993
|
-
if ((!updateOn || updateOn === 'change') && debounce?.default > 0) {
|
|
994
|
-
valueChanges = control.valueChanges.pipe(debounceTime(debounce.default));
|
|
995
|
-
}
|
|
996
|
-
const sub = valueChanges.subscribe((value) => {
|
|
997
|
-
// workaround for https://github.com/angular/angular/issues/13792
|
|
998
|
-
if (control._fields?.length > 1 && control instanceof FormControl) {
|
|
999
|
-
control.patchValue(value, { emitEvent: false, onlySelf: true });
|
|
658
|
+
else {
|
|
659
|
+
prop
|
|
660
|
+
.split(/[[\]]{1,2}/) // https://stackoverflow.com/a/20198206
|
|
661
|
+
.filter((p) => p)
|
|
662
|
+
.forEach((path) => {
|
|
663
|
+
const arrayPath = path.match(/['|"](.*?)['|"]/);
|
|
664
|
+
if (arrayPath) {
|
|
665
|
+
paths.push(arrayPath[1]);
|
|
1000
666
|
}
|
|
1001
|
-
|
|
1002
|
-
|
|
667
|
+
else {
|
|
668
|
+
paths.push(...path.split('.').filter((p) => p));
|
|
1003
669
|
}
|
|
1004
|
-
field.options.fieldChanges.next({ value, field, type: 'valueChanges' });
|
|
1005
670
|
});
|
|
1006
|
-
subscribes.push(() => sub.unsubscribe());
|
|
1007
671
|
}
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
});
|
|
1013
|
-
return () => {
|
|
1014
|
-
subscribes.forEach((unsubscribe) => unsubscribe());
|
|
1015
|
-
templateFieldsSubs.forEach((unsubscribe) => unsubscribe());
|
|
1016
|
-
};
|
|
672
|
+
if (field._expressions[prop]) {
|
|
673
|
+
field._expressions[prop].paths = paths;
|
|
674
|
+
}
|
|
675
|
+
return paths;
|
|
1017
676
|
}
|
|
1018
677
|
}
|
|
1019
|
-
FormlyField.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyField, deps: [{ token: FormlyConfig }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: FormlyFieldTemplates, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
1020
|
-
FormlyField.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: FormlyField, selector: "formly-field", inputs: { field: "field" }, viewQueries: [{ propertyName: "viewContainerRef", first: true, predicate: ["container"], descendants: true, read: ViewContainerRef, static: true }], usesOnChanges: true, ngImport: i0, template: '<ng-template #container></ng-template>', isInline: true, styles: [":host:empty{display:none}\n"] });
|
|
1021
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyField, decorators: [{
|
|
1022
|
-
type: Component,
|
|
1023
|
-
args: [{ selector: 'formly-field', template: '<ng-template #container></ng-template>', styles: [":host:empty{display:none}\n"] }]
|
|
1024
|
-
}], ctorParameters: function () { return [{ type: FormlyConfig }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: FormlyFieldTemplates, decorators: [{
|
|
1025
|
-
type: Optional
|
|
1026
|
-
}] }]; }, propDecorators: { field: [{
|
|
1027
|
-
type: Input
|
|
1028
|
-
}], viewContainerRef: [{
|
|
1029
|
-
type: ViewChild,
|
|
1030
|
-
args: ['container', { read: ViewContainerRef, static: true }]
|
|
1031
|
-
}] } });
|
|
1032
678
|
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
* which takes care of managing the form state
|
|
1036
|
-
* and delegates the rendering of each field to `<formly-field>` component.
|
|
1037
|
-
*/
|
|
1038
|
-
class FormlyForm {
|
|
1039
|
-
constructor(builder, config, ngZone, fieldTemplates) {
|
|
1040
|
-
this.builder = builder;
|
|
679
|
+
class CoreExtension {
|
|
680
|
+
constructor(config) {
|
|
1041
681
|
this.config = config;
|
|
1042
|
-
this.
|
|
1043
|
-
this.fieldTemplates = fieldTemplates;
|
|
1044
|
-
/** Event that is emitted when the model value is changed */
|
|
1045
|
-
this.modelChange = new EventEmitter();
|
|
1046
|
-
this.field = { type: 'formly-group' };
|
|
1047
|
-
this._modelChangeValue = {};
|
|
1048
|
-
this.valueChangesUnsubscribe = () => { };
|
|
1049
|
-
}
|
|
1050
|
-
/** The form instance which allow to track model value and validation status. */
|
|
1051
|
-
set form(form) {
|
|
1052
|
-
this.field.form = form;
|
|
1053
|
-
}
|
|
1054
|
-
get form() {
|
|
1055
|
-
return this.field.form;
|
|
682
|
+
this.formId = 0;
|
|
1056
683
|
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
684
|
+
prePopulate(field) {
|
|
685
|
+
const root = field.parent;
|
|
686
|
+
this.initRootOptions(field);
|
|
687
|
+
this.initFieldProps(field);
|
|
688
|
+
if (root) {
|
|
689
|
+
Object.defineProperty(field, 'options', { get: () => root.options, configurable: true });
|
|
690
|
+
Object.defineProperty(field, 'model', {
|
|
691
|
+
get: () => (hasKey(field) && field.fieldGroup ? getFieldValue(field) : root.model),
|
|
692
|
+
configurable: true,
|
|
693
|
+
});
|
|
1061
694
|
}
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
/** The field configurations for building the form. */
|
|
1068
|
-
set fields(fieldGroup) {
|
|
1069
|
-
this.setField({ fieldGroup });
|
|
1070
|
-
}
|
|
1071
|
-
get fields() {
|
|
1072
|
-
return this.field.fieldGroup;
|
|
695
|
+
Object.defineProperty(field, 'get', {
|
|
696
|
+
value: (key) => getField(field, key),
|
|
697
|
+
configurable: true,
|
|
698
|
+
});
|
|
699
|
+
this.getFieldComponentInstance(field).prePopulate?.(field);
|
|
1073
700
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
this.
|
|
701
|
+
onPopulate(field) {
|
|
702
|
+
this.initFieldOptions(field);
|
|
703
|
+
this.getFieldComponentInstance(field).onPopulate?.(field);
|
|
704
|
+
if (field.fieldGroup) {
|
|
705
|
+
field.fieldGroup.forEach((f, index) => {
|
|
706
|
+
if (f) {
|
|
707
|
+
Object.defineProperty(f, 'parent', { get: () => field, configurable: true });
|
|
708
|
+
Object.defineProperty(f, 'index', { get: () => index, configurable: true });
|
|
709
|
+
}
|
|
710
|
+
this.formId++;
|
|
711
|
+
});
|
|
712
|
+
}
|
|
1077
713
|
}
|
|
1078
|
-
|
|
1079
|
-
|
|
714
|
+
postPopulate(field) {
|
|
715
|
+
this.getFieldComponentInstance(field).postPopulate?.(field);
|
|
1080
716
|
}
|
|
1081
|
-
|
|
1082
|
-
|
|
717
|
+
initFieldProps(field) {
|
|
718
|
+
field.props ??= field.templateOptions;
|
|
719
|
+
Object.defineProperty(field, 'templateOptions', {
|
|
720
|
+
get: () => field.props,
|
|
721
|
+
set: (props) => (field.props = props),
|
|
722
|
+
configurable: true,
|
|
723
|
+
});
|
|
1083
724
|
}
|
|
1084
|
-
|
|
1085
|
-
if (
|
|
1086
|
-
|
|
725
|
+
initRootOptions(field) {
|
|
726
|
+
if (field.parent) {
|
|
727
|
+
return;
|
|
1087
728
|
}
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
if (
|
|
1091
|
-
|
|
729
|
+
const options = field.options;
|
|
730
|
+
field.options.formState = field.options.formState || {};
|
|
731
|
+
if (!options.showError) {
|
|
732
|
+
options.showError = this.config.extras.showError;
|
|
1092
733
|
}
|
|
1093
|
-
if (
|
|
1094
|
-
|
|
1095
|
-
this.builder.build(this.field);
|
|
1096
|
-
this.valueChangesUnsubscribe = this.valueChanges();
|
|
734
|
+
if (!options.fieldChanges) {
|
|
735
|
+
defineHiddenProp(options, 'fieldChanges', new Subject());
|
|
1097
736
|
}
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
this.valueChangesUnsubscribe();
|
|
1101
|
-
}
|
|
1102
|
-
checkExpressionChange() {
|
|
1103
|
-
this.field.options.checkExpressions?.(this.field);
|
|
1104
|
-
}
|
|
1105
|
-
valueChanges() {
|
|
1106
|
-
this.valueChangesUnsubscribe();
|
|
1107
|
-
let formEvents = null;
|
|
1108
|
-
if (isSignalRequired()) {
|
|
1109
|
-
let submitted = this.options?.parentForm?.submitted;
|
|
1110
|
-
formEvents = this.form.events.subscribe(() => {
|
|
1111
|
-
if (submitted !== this.options?.parentForm?.submitted) {
|
|
1112
|
-
this.options.detectChanges(this.field);
|
|
1113
|
-
submitted = this.options?.parentForm?.submitted;
|
|
1114
|
-
}
|
|
1115
|
-
});
|
|
737
|
+
if (!options._hiddenFieldsForCheck) {
|
|
738
|
+
options._hiddenFieldsForCheck = [];
|
|
1116
739
|
}
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
const valueChanges = this.field.options.fieldChanges
|
|
1121
|
-
.pipe(filter(({ field, type }) => hasKey(field) && type === 'valueChanges'), switchMap(() => (isNoopNgZone(this.ngZone) ? of(null) : this.ngZone.onStable.asObservable().pipe(take(1)))))
|
|
1122
|
-
.subscribe(() => this.ngZone.runGuarded(() => {
|
|
1123
|
-
// runGuarded is used to keep in sync the expression changes
|
|
1124
|
-
// https://github.com/ngx-formly/ngx-formly/issues/2095
|
|
1125
|
-
this.checkExpressionChange();
|
|
1126
|
-
this.modelChange.emit((this._modelChangeValue = clone(this.model)));
|
|
1127
|
-
}));
|
|
1128
|
-
return () => {
|
|
1129
|
-
fieldChangesDetection.forEach((fnc) => fnc());
|
|
1130
|
-
formEvents?.unsubscribe();
|
|
1131
|
-
valueChanges.unsubscribe();
|
|
740
|
+
options._markForCheck = (f) => {
|
|
741
|
+
console.warn(`Formly: 'options._markForCheck' is deprecated since v6.0, use 'options.detectChanges' instead.`);
|
|
742
|
+
options.detectChanges(f);
|
|
1132
743
|
};
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
else {
|
|
1139
|
-
Object.keys(field).forEach((p) => (this.field[p] = field[p]));
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
FormlyForm.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyForm, deps: [{ token: FormlyFormBuilder }, { token: FormlyConfig }, { token: i0.NgZone }, { token: FormlyFieldTemplates }], target: i0.ɵɵFactoryTarget.Component });
|
|
1144
|
-
FormlyForm.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: FormlyForm, selector: "formly-form", inputs: { form: "form", model: "model", fields: "fields", options: "options" }, outputs: { modelChange: "modelChange" }, providers: [FormlyFormBuilder, FormlyFieldTemplates], queries: [{ propertyName: "templates", predicate: FormlyTemplate }], usesOnChanges: true, ngImport: i0, template: '<formly-field [field]="field"></formly-field>', isInline: true, components: [{ type: FormlyField, selector: "formly-field", inputs: ["field"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1145
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyForm, decorators: [{
|
|
1146
|
-
type: Component,
|
|
1147
|
-
args: [{
|
|
1148
|
-
selector: 'formly-form',
|
|
1149
|
-
template: '<formly-field [field]="field"></formly-field>',
|
|
1150
|
-
providers: [FormlyFormBuilder, FormlyFieldTemplates],
|
|
1151
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1152
|
-
}]
|
|
1153
|
-
}], ctorParameters: function () { return [{ type: FormlyFormBuilder }, { type: FormlyConfig }, { type: i0.NgZone }, { type: FormlyFieldTemplates }]; }, propDecorators: { form: [{
|
|
1154
|
-
type: Input
|
|
1155
|
-
}], model: [{
|
|
1156
|
-
type: Input
|
|
1157
|
-
}], fields: [{
|
|
1158
|
-
type: Input
|
|
1159
|
-
}], options: [{
|
|
1160
|
-
type: Input
|
|
1161
|
-
}], modelChange: [{
|
|
1162
|
-
type: Output
|
|
1163
|
-
}], templates: [{
|
|
1164
|
-
type: ContentChildren,
|
|
1165
|
-
args: [FormlyTemplate]
|
|
1166
|
-
}] } });
|
|
1167
|
-
|
|
1168
|
-
/**
|
|
1169
|
-
* Allow to link the `field` HTML attributes (`id`, `name` ...) and Event attributes (`focus`, `blur` ...) to an element in the DOM.
|
|
1170
|
-
*/
|
|
1171
|
-
class FormlyAttributes {
|
|
1172
|
-
constructor(renderer, elementRef, _document) {
|
|
1173
|
-
this.renderer = renderer;
|
|
1174
|
-
this.elementRef = elementRef;
|
|
1175
|
-
this.uiAttributesCache = {};
|
|
1176
|
-
/**
|
|
1177
|
-
* HostBinding doesn't register listeners conditionally which may produce some perf issues.
|
|
1178
|
-
*
|
|
1179
|
-
* Formly issue: https://github.com/ngx-formly/ngx-formly/issues/1991
|
|
1180
|
-
*/
|
|
1181
|
-
this.uiEvents = {
|
|
1182
|
-
listeners: [],
|
|
1183
|
-
events: ['click', 'keyup', 'keydown', 'keypress', 'focus', 'blur', 'change'],
|
|
1184
|
-
callback: (eventName, $event) => {
|
|
1185
|
-
switch (eventName) {
|
|
1186
|
-
case 'focus':
|
|
1187
|
-
return this.onFocus($event);
|
|
1188
|
-
case 'blur':
|
|
1189
|
-
return this.onBlur($event);
|
|
1190
|
-
case 'change':
|
|
1191
|
-
return this.onChange($event);
|
|
1192
|
-
default:
|
|
1193
|
-
return this.props[eventName](this.field, $event);
|
|
1194
|
-
}
|
|
1195
|
-
},
|
|
744
|
+
options._detectChanges = (f) => {
|
|
745
|
+
if (f._componentRefs) {
|
|
746
|
+
markFieldForCheck(f);
|
|
747
|
+
}
|
|
748
|
+
f.fieldGroup?.forEach((f) => f && options._detectChanges(f));
|
|
1196
749
|
};
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
if (changes.field) {
|
|
1207
|
-
this.field.name && this.setAttribute('name', this.field.name);
|
|
1208
|
-
this.uiEvents.listeners.forEach((listener) => listener());
|
|
1209
|
-
this.uiEvents.events.forEach((eventName) => {
|
|
1210
|
-
if (this.props?.[eventName] || ['focus', 'blur', 'change'].indexOf(eventName) !== -1) {
|
|
1211
|
-
this.uiEvents.listeners.push(this.renderer.listen(this.elementRef.nativeElement, eventName, (e) => this.uiEvents.callback(eventName, e)));
|
|
1212
|
-
}
|
|
1213
|
-
});
|
|
1214
|
-
if (this.props?.attributes) {
|
|
1215
|
-
observe(this.field, ['props', 'attributes'], ({ currentValue, previousValue }) => {
|
|
1216
|
-
if (previousValue) {
|
|
1217
|
-
Object.keys(previousValue).forEach((attr) => this.removeAttribute(attr));
|
|
1218
|
-
}
|
|
1219
|
-
if (currentValue) {
|
|
1220
|
-
Object.keys(currentValue).forEach((attr) => {
|
|
1221
|
-
if (currentValue[attr] != null) {
|
|
1222
|
-
this.setAttribute(attr, currentValue[attr]);
|
|
1223
|
-
}
|
|
1224
|
-
});
|
|
1225
|
-
}
|
|
1226
|
-
});
|
|
750
|
+
options.detectChanges = (f) => {
|
|
751
|
+
f.options.checkExpressions?.(f);
|
|
752
|
+
options._detectChanges(f);
|
|
753
|
+
};
|
|
754
|
+
options.resetModel = (model) => {
|
|
755
|
+
model = clone(model ?? options._initialModel);
|
|
756
|
+
if (field.model) {
|
|
757
|
+
Object.keys(field.model).forEach((k) => delete field.model[k]);
|
|
758
|
+
Object.assign(field.model, model || {});
|
|
1227
759
|
}
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
if (this.fieldAttrElements.length === 1) {
|
|
1231
|
-
!this.id && this.field.id && this.setAttribute('id', this.field.id);
|
|
1232
|
-
this.focusObserver = observe(this.field, ['focus'], ({ currentValue }) => {
|
|
1233
|
-
this.toggleFocus(currentValue);
|
|
1234
|
-
});
|
|
760
|
+
if (!isSignalRequired()) {
|
|
761
|
+
observe(options, ['parentForm', 'submitted']).setValue(false, false);
|
|
1235
762
|
}
|
|
763
|
+
options.build(field);
|
|
764
|
+
field.form.reset(field.model);
|
|
765
|
+
};
|
|
766
|
+
options.updateInitialValue = (model) => (options._initialModel = clone(model ?? field.model));
|
|
767
|
+
field.options.updateInitialValue();
|
|
768
|
+
}
|
|
769
|
+
initFieldOptions(field) {
|
|
770
|
+
reverseDeepMerge(field, {
|
|
771
|
+
id: getFieldId(`formly_${this.formId}`, field, field.index),
|
|
772
|
+
hooks: {},
|
|
773
|
+
modelOptions: {},
|
|
774
|
+
validation: { messages: {} },
|
|
775
|
+
props: !field.type || !hasKey(field)
|
|
776
|
+
? {}
|
|
777
|
+
: {
|
|
778
|
+
label: '',
|
|
779
|
+
placeholder: '',
|
|
780
|
+
disabled: false,
|
|
781
|
+
},
|
|
782
|
+
});
|
|
783
|
+
if (this.config.extras.resetFieldOnHide && field.resetOnHide !== false) {
|
|
784
|
+
field.resetOnHide = true;
|
|
1236
785
|
}
|
|
1237
|
-
if (
|
|
1238
|
-
|
|
786
|
+
if (field.type !== 'formly-template' &&
|
|
787
|
+
(field.template || field.expressions?.template || field.expressionProperties?.template)) {
|
|
788
|
+
field.type = 'formly-template';
|
|
1239
789
|
}
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
* We need to re-evaluate all the attributes on every change detection cycle, because
|
|
1243
|
-
* by using a HostBinding we run into certain edge cases. This means that whatever logic
|
|
1244
|
-
* is in here has to be super lean or we risk seriously damaging or destroying the performance.
|
|
1245
|
-
*
|
|
1246
|
-
* Formly issue: https://github.com/ngx-formly/ngx-formly/issues/1317
|
|
1247
|
-
* Material issue: https://github.com/angular/components/issues/14024
|
|
1248
|
-
*/
|
|
1249
|
-
ngDoCheck() {
|
|
1250
|
-
if (!this.uiAttributes) {
|
|
1251
|
-
const element = this.elementRef.nativeElement;
|
|
1252
|
-
this.uiAttributes = [...FORMLY_VALIDATORS, 'tabindex', 'placeholder', 'readonly', 'disabled', 'step'].filter((attr) => !element.hasAttribute || !element.hasAttribute(attr));
|
|
790
|
+
if (!field.type && field.fieldGroup) {
|
|
791
|
+
field.type = 'formly-group';
|
|
1253
792
|
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
const value = this.props[attr];
|
|
1257
|
-
if (this.uiAttributesCache[attr] !== value &&
|
|
1258
|
-
(!this.props.attributes || !this.props.attributes.hasOwnProperty(attr.toLowerCase()))) {
|
|
1259
|
-
this.uiAttributesCache[attr] = value;
|
|
1260
|
-
if (value || value === 0) {
|
|
1261
|
-
this.setAttribute(attr, value === true ? attr : `${value}`);
|
|
1262
|
-
}
|
|
1263
|
-
else {
|
|
1264
|
-
this.removeAttribute(attr);
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
793
|
+
if (field.type) {
|
|
794
|
+
this.config.getMergedField(field);
|
|
1267
795
|
}
|
|
796
|
+
if (hasKey(field) &&
|
|
797
|
+
!isUndefined(field.defaultValue) &&
|
|
798
|
+
isUndefined(getFieldValue(field)) &&
|
|
799
|
+
!isHiddenField(field)) {
|
|
800
|
+
assignFieldValue(field, field.defaultValue);
|
|
801
|
+
}
|
|
802
|
+
field.wrappers = field.wrappers || [];
|
|
1268
803
|
}
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
return;
|
|
804
|
+
getFieldComponentInstance(field) {
|
|
805
|
+
const componentRefInstance = () => {
|
|
806
|
+
let componentRef = this.config.resolveFieldTypeRef(field);
|
|
807
|
+
const fieldComponentRef = field._componentRefs?.slice(-1)[0];
|
|
808
|
+
if (fieldComponentRef instanceof ComponentRef &&
|
|
809
|
+
fieldComponentRef?.componentType === componentRef?.componentType) {
|
|
810
|
+
componentRef = fieldComponentRef;
|
|
811
|
+
}
|
|
812
|
+
return componentRef?.instance;
|
|
813
|
+
};
|
|
814
|
+
if (!field._proxyInstance) {
|
|
815
|
+
defineHiddenProp(field, '_proxyInstance', new Proxy({}, {
|
|
816
|
+
get: (_, prop) => componentRefInstance()?.[prop],
|
|
817
|
+
set: (_, prop, value) => (componentRefInstance()[prop] = value),
|
|
818
|
+
}));
|
|
1278
819
|
}
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
820
|
+
return field._proxyInstance;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
class FieldFormExtension {
|
|
825
|
+
prePopulate(field) {
|
|
826
|
+
if (!this.root) {
|
|
827
|
+
this.root = field;
|
|
1283
828
|
}
|
|
1284
|
-
|
|
1285
|
-
|
|
829
|
+
if (field.parent) {
|
|
830
|
+
Object.defineProperty(field, 'form', {
|
|
831
|
+
get: () => field.parent.formControl,
|
|
832
|
+
configurable: true,
|
|
833
|
+
});
|
|
1286
834
|
}
|
|
1287
835
|
}
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
836
|
+
onPopulate(field) {
|
|
837
|
+
if (field.hasOwnProperty('fieldGroup') && !hasKey(field)) {
|
|
838
|
+
defineHiddenProp(field, 'formControl', field.form);
|
|
839
|
+
}
|
|
840
|
+
else {
|
|
841
|
+
this.addFormControl(field);
|
|
842
|
+
}
|
|
1295
843
|
}
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
if ($event instanceof Event) {
|
|
844
|
+
postPopulate(field) {
|
|
845
|
+
if (this.root !== field) {
|
|
1299
846
|
return;
|
|
1300
847
|
}
|
|
1301
|
-
this.
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
848
|
+
this.root = null;
|
|
849
|
+
const markForCheck = this.setValidators(field);
|
|
850
|
+
if (markForCheck && field.parent) {
|
|
851
|
+
let parent = field.parent;
|
|
852
|
+
while (parent) {
|
|
853
|
+
if (hasKey(parent) || !parent.parent) {
|
|
854
|
+
updateValidity(parent.formControl, true);
|
|
855
|
+
}
|
|
856
|
+
parent = parent.parent;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
1306
859
|
}
|
|
1307
|
-
|
|
1308
|
-
|
|
860
|
+
addFormControl(field) {
|
|
861
|
+
let control = findControl(field);
|
|
862
|
+
if (field.fieldArray) {
|
|
1309
863
|
return;
|
|
1310
864
|
}
|
|
1311
|
-
if (
|
|
1312
|
-
|
|
865
|
+
if (!control) {
|
|
866
|
+
const controlOptions = { updateOn: field.modelOptions.updateOn };
|
|
867
|
+
if (field.fieldGroup) {
|
|
868
|
+
control = new UntypedFormGroup({}, controlOptions);
|
|
869
|
+
}
|
|
870
|
+
else {
|
|
871
|
+
const value = hasKey(field) ? getFieldValue(field) : field.defaultValue;
|
|
872
|
+
control = new UntypedFormControl({ value, disabled: !!field.props.disabled }, { ...controlOptions, initialValueIsDefault: true });
|
|
873
|
+
}
|
|
1313
874
|
}
|
|
1314
875
|
else {
|
|
1315
|
-
|
|
876
|
+
if (control instanceof FormControl) {
|
|
877
|
+
const value = hasKey(field) ? getFieldValue(field) : field.defaultValue;
|
|
878
|
+
control.defaultValue = value;
|
|
879
|
+
}
|
|
1316
880
|
}
|
|
881
|
+
registerControl(field, control);
|
|
1317
882
|
}
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
883
|
+
setValidators(field, disabled = false) {
|
|
884
|
+
if (disabled === false && hasKey(field) && field.props?.disabled) {
|
|
885
|
+
disabled = true;
|
|
886
|
+
}
|
|
887
|
+
let markForCheck = false;
|
|
888
|
+
field.fieldGroup?.forEach((f) => f && this.setValidators(f, disabled) && (markForCheck = true));
|
|
889
|
+
if (hasKey(field) || !field.parent || (!hasKey(field) && !field.fieldGroup)) {
|
|
890
|
+
const { formControl: c } = field;
|
|
891
|
+
if (c) {
|
|
892
|
+
if (hasKey(field) && c instanceof FormControl) {
|
|
893
|
+
if (disabled && c.enabled) {
|
|
894
|
+
c.disable({ emitEvent: false, onlySelf: true });
|
|
895
|
+
markForCheck = true;
|
|
896
|
+
}
|
|
897
|
+
if (!disabled && c.disabled) {
|
|
898
|
+
c.enable({ emitEvent: false, onlySelf: true });
|
|
899
|
+
markForCheck = true;
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
if (null === c.validator && this.hasValidators(field, '_validators')) {
|
|
903
|
+
c.setValidators(() => {
|
|
904
|
+
const v = Validators.compose(this.mergeValidators(field, '_validators'));
|
|
905
|
+
return v ? v(c) : null;
|
|
906
|
+
});
|
|
907
|
+
markForCheck = true;
|
|
908
|
+
}
|
|
909
|
+
if (null === c.asyncValidator && this.hasValidators(field, '_asyncValidators')) {
|
|
910
|
+
c.setAsyncValidators(() => {
|
|
911
|
+
const v = Validators.composeAsync(this.mergeValidators(field, '_asyncValidators'));
|
|
912
|
+
return v ? v(c) : of(null);
|
|
913
|
+
});
|
|
914
|
+
markForCheck = true;
|
|
915
|
+
}
|
|
916
|
+
if (markForCheck) {
|
|
917
|
+
updateValidity(c, true);
|
|
918
|
+
// update validity of `FormGroup` instance created by field with nested key.
|
|
919
|
+
let parent = c.parent;
|
|
920
|
+
for (let i = 1; i < getKeyPath(field).length; i++) {
|
|
921
|
+
if (parent) {
|
|
922
|
+
updateValidity(parent, true);
|
|
923
|
+
parent = parent.parent;
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
}
|
|
1322
928
|
}
|
|
929
|
+
return markForCheck;
|
|
1323
930
|
}
|
|
1324
|
-
|
|
1325
|
-
|
|
931
|
+
hasValidators(field, type) {
|
|
932
|
+
const c = field.formControl;
|
|
933
|
+
if (c?._fields?.length > 1 && c._fields.some((f) => f[type].length > 0)) {
|
|
934
|
+
return true;
|
|
935
|
+
}
|
|
936
|
+
else if (field[type].length > 0) {
|
|
937
|
+
return true;
|
|
938
|
+
}
|
|
939
|
+
return field.fieldGroup?.some((f) => f?.fieldGroup && !hasKey(f) && this.hasValidators(f, type));
|
|
1326
940
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
941
|
+
mergeValidators(field, type) {
|
|
942
|
+
const validators = [];
|
|
943
|
+
const c = field.formControl;
|
|
944
|
+
if (c?._fields?.length > 1) {
|
|
945
|
+
c._fields
|
|
946
|
+
.filter((f) => !f._hide)
|
|
947
|
+
.forEach((f) => validators.push(...f[type]));
|
|
948
|
+
}
|
|
949
|
+
else if (field[type]) {
|
|
950
|
+
validators.push(...field[type]);
|
|
951
|
+
}
|
|
952
|
+
if (field.fieldGroup) {
|
|
953
|
+
field.fieldGroup
|
|
954
|
+
.filter((f) => f?.fieldGroup && !hasKey(f))
|
|
955
|
+
.forEach((f) => validators.push(...this.mergeValidators(f, type)));
|
|
956
|
+
}
|
|
957
|
+
return validators;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
class FieldValidationExtension {
|
|
962
|
+
constructor(config) {
|
|
963
|
+
this.config = config;
|
|
964
|
+
}
|
|
965
|
+
onPopulate(field) {
|
|
966
|
+
this.initFieldValidation(field, 'validators');
|
|
967
|
+
this.initFieldValidation(field, 'asyncValidators');
|
|
968
|
+
}
|
|
969
|
+
initFieldValidation(field, type) {
|
|
970
|
+
const validators = [];
|
|
971
|
+
if (type === 'validators' && !(field.hasOwnProperty('fieldGroup') && !hasKey(field))) {
|
|
972
|
+
validators.push(this.getPredefinedFieldValidation(field));
|
|
973
|
+
}
|
|
974
|
+
if (field[type]) {
|
|
975
|
+
for (const validatorName of Object.keys(field[type])) {
|
|
976
|
+
validatorName === 'validation'
|
|
977
|
+
? validators.push(...field[type].validation.map((v) => this.wrapNgValidatorFn(field, v)))
|
|
978
|
+
: validators.push(this.wrapNgValidatorFn(field, field[type][validatorName], validatorName));
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
defineHiddenProp(field, '_' + type, validators);
|
|
982
|
+
}
|
|
983
|
+
getPredefinedFieldValidation(field) {
|
|
984
|
+
let VALIDATORS = [];
|
|
985
|
+
FORMLY_VALIDATORS.forEach((opt) => observe(field, ['props', opt], ({ currentValue, firstChange }) => {
|
|
986
|
+
VALIDATORS = VALIDATORS.filter((o) => o !== opt);
|
|
987
|
+
if (opt === 'required' && currentValue != null && typeof currentValue !== 'boolean') {
|
|
988
|
+
console.warn(`Formly: Invalid prop 'required' of type '${typeof currentValue}', expected 'boolean' (Field:${field.key}).`);
|
|
989
|
+
}
|
|
990
|
+
if (currentValue != null && currentValue !== false) {
|
|
991
|
+
VALIDATORS.push(opt);
|
|
992
|
+
}
|
|
993
|
+
if (!firstChange && field.formControl) {
|
|
994
|
+
updateValidity(field.formControl);
|
|
995
|
+
}
|
|
996
|
+
}));
|
|
997
|
+
return (control) => {
|
|
998
|
+
if (VALIDATORS.length === 0) {
|
|
999
|
+
return null;
|
|
1000
|
+
}
|
|
1001
|
+
return Validators.compose(VALIDATORS.map((opt) => () => {
|
|
1002
|
+
const value = field.props[opt];
|
|
1003
|
+
switch (opt) {
|
|
1004
|
+
case 'required':
|
|
1005
|
+
return Validators.required(control);
|
|
1006
|
+
case 'pattern':
|
|
1007
|
+
return Validators.pattern(value)(control);
|
|
1008
|
+
case 'minLength':
|
|
1009
|
+
const minLengthResult = Validators.minLength(value)(control);
|
|
1010
|
+
const minLengthKey = this.config.getValidatorMessage('minlength') || field.validation?.messages?.minlength
|
|
1011
|
+
? 'minlength'
|
|
1012
|
+
: 'minLength';
|
|
1013
|
+
return minLengthResult ? { [minLengthKey]: minLengthResult.minlength } : null;
|
|
1014
|
+
case 'maxLength':
|
|
1015
|
+
const maxLengthResult = Validators.maxLength(value)(control);
|
|
1016
|
+
const maxLengthKey = this.config.getValidatorMessage('maxlength') || field.validation?.messages?.maxlength
|
|
1017
|
+
? 'maxlength'
|
|
1018
|
+
: 'maxLength';
|
|
1019
|
+
return maxLengthResult ? { [maxLengthKey]: maxLengthResult.maxlength } : null;
|
|
1020
|
+
case 'min':
|
|
1021
|
+
return Validators.min(value)(control);
|
|
1022
|
+
case 'max':
|
|
1023
|
+
return Validators.max(value)(control);
|
|
1024
|
+
default:
|
|
1025
|
+
return null;
|
|
1026
|
+
}
|
|
1027
|
+
}))(control);
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
1030
|
+
wrapNgValidatorFn(field, validator, validatorName) {
|
|
1031
|
+
let validatorOption;
|
|
1032
|
+
if (typeof validator === 'string') {
|
|
1033
|
+
validatorOption = clone(this.config.getValidator(validator));
|
|
1034
|
+
}
|
|
1035
|
+
if (typeof validator === 'object' && validator.name) {
|
|
1036
|
+
validatorOption = clone(this.config.getValidator(validator.name));
|
|
1037
|
+
if (validator.options) {
|
|
1038
|
+
validatorOption.options = validator.options;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
if (typeof validator === 'object' && validator.expression) {
|
|
1042
|
+
const { expression, ...options } = validator;
|
|
1043
|
+
validatorOption = {
|
|
1044
|
+
name: validatorName,
|
|
1045
|
+
validation: expression,
|
|
1046
|
+
options: Object.keys(options).length > 0 ? options : null,
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
if (typeof validator === 'function') {
|
|
1050
|
+
validatorOption = {
|
|
1051
|
+
name: validatorName,
|
|
1052
|
+
validation: validator,
|
|
1053
|
+
};
|
|
1054
|
+
}
|
|
1055
|
+
return (control) => {
|
|
1056
|
+
const errors = validatorOption.validation(control, field, validatorOption.options);
|
|
1057
|
+
if (isPromise(errors)) {
|
|
1058
|
+
return errors.then((v) => this.handleResult(field, validatorName ? !!v : v, validatorOption));
|
|
1059
|
+
}
|
|
1060
|
+
if (isObservable(errors)) {
|
|
1061
|
+
return errors.pipe(map((v) => this.handleResult(field, validatorName ? !!v : v, validatorOption)));
|
|
1062
|
+
}
|
|
1063
|
+
return this.handleResult(field, validatorName ? !!errors : errors, validatorOption);
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
1066
|
+
handleResult(field, errors, { name, options }) {
|
|
1067
|
+
if (typeof errors === 'boolean') {
|
|
1068
|
+
errors = errors ? null : { [name]: options ? options : true };
|
|
1069
|
+
}
|
|
1070
|
+
const ctrl = field.formControl;
|
|
1071
|
+
ctrl?._childrenErrors?.[name]?.();
|
|
1072
|
+
if (isObject(errors)) {
|
|
1073
|
+
Object.keys(errors).forEach((name) => {
|
|
1074
|
+
const errorPath = errors[name].errorPath ? errors[name].errorPath : options?.errorPath;
|
|
1075
|
+
const childCtrl = errorPath ? field.formControl.get(errorPath) : null;
|
|
1076
|
+
if (childCtrl) {
|
|
1077
|
+
const { errorPath: _errorPath, ...opts } = errors[name];
|
|
1078
|
+
childCtrl.setErrors({ ...(childCtrl.errors || {}), [name]: opts });
|
|
1079
|
+
!ctrl._childrenErrors && defineHiddenProp(ctrl, '_childrenErrors', {});
|
|
1080
|
+
ctrl._childrenErrors[name] = () => {
|
|
1081
|
+
const { [name]: _toDelete, ...childErrors } = childCtrl.errors || {};
|
|
1082
|
+
childCtrl.setErrors(Object.keys(childErrors).length === 0 ? null : childErrors);
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
return errors;
|
|
1329
1088
|
}
|
|
1330
1089
|
}
|
|
1331
|
-
FormlyAttributes.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyAttributes, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Directive });
|
|
1332
|
-
FormlyAttributes.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: FormlyAttributes, selector: "[formlyAttributes]", inputs: { field: ["formlyAttributes", "field"], id: "id" }, host: { listeners: { "change": "onHostChange($event)" } }, usesOnChanges: true, ngImport: i0 });
|
|
1333
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyAttributes, decorators: [{
|
|
1334
|
-
type: Directive,
|
|
1335
|
-
args: [{
|
|
1336
|
-
selector: '[formlyAttributes]',
|
|
1337
|
-
host: {
|
|
1338
|
-
'(change)': 'onHostChange($event)',
|
|
1339
|
-
},
|
|
1340
|
-
}]
|
|
1341
|
-
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: undefined, decorators: [{
|
|
1342
|
-
type: Inject,
|
|
1343
|
-
args: [DOCUMENT]
|
|
1344
|
-
}] }]; }, propDecorators: { field: [{
|
|
1345
|
-
type: Input,
|
|
1346
|
-
args: ['formlyAttributes']
|
|
1347
|
-
}], id: [{
|
|
1348
|
-
type: Input
|
|
1349
|
-
}] } });
|
|
1350
1090
|
|
|
1351
1091
|
class FieldType {
|
|
1352
1092
|
constructor() {
|
|
@@ -1390,10 +1130,10 @@ class FieldType {
|
|
|
1390
1130
|
get formState() {
|
|
1391
1131
|
return this.options?.formState || {};
|
|
1392
1132
|
}
|
|
1133
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FieldType, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1134
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: FieldType, inputs: { field: "field" }, viewQueries: [{ propertyName: "_formlyControls", predicate: NgControl, descendants: true }], ngImport: i0 }); }
|
|
1393
1135
|
}
|
|
1394
|
-
|
|
1395
|
-
FieldType.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: FieldType, inputs: { field: "field" }, viewQueries: [{ propertyName: "_formlyControls", predicate: NgControl, descendants: true }], ngImport: i0 });
|
|
1396
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FieldType, decorators: [{
|
|
1136
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FieldType, decorators: [{
|
|
1397
1137
|
type: Directive
|
|
1398
1138
|
}], propDecorators: { _formlyControls: [{
|
|
1399
1139
|
type: ViewChildren,
|
|
@@ -1403,914 +1143,1212 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
|
|
|
1403
1143
|
}] } });
|
|
1404
1144
|
|
|
1405
1145
|
/** @ignore */
|
|
1406
|
-
class
|
|
1146
|
+
class FormlyTemplateType extends FieldType {
|
|
1147
|
+
get template() {
|
|
1148
|
+
if (this.field && this.field.template !== this.innerHtml.template) {
|
|
1149
|
+
this.innerHtml = {
|
|
1150
|
+
template: this.field.template,
|
|
1151
|
+
content: this.props.safeHtml
|
|
1152
|
+
? this.sanitizer.bypassSecurityTrustHtml(this.field.template)
|
|
1153
|
+
: this.field.template,
|
|
1154
|
+
};
|
|
1155
|
+
}
|
|
1156
|
+
return this.innerHtml.content;
|
|
1157
|
+
}
|
|
1158
|
+
constructor(sanitizer) {
|
|
1159
|
+
super();
|
|
1160
|
+
this.sanitizer = sanitizer;
|
|
1161
|
+
this.innerHtml = {};
|
|
1162
|
+
}
|
|
1163
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyTemplateType, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1164
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: FormlyTemplateType, selector: "formly-template", usesInheritance: true, ngImport: i0, template: `<div [innerHtml]="template"></div>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1407
1165
|
}
|
|
1408
|
-
|
|
1409
|
-
FormlyGroup.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: FormlyGroup, selector: "formly-group", host: { properties: { "class": "field.fieldGroupClassName || \"\"" } }, usesInheritance: true, ngImport: i0, template: `
|
|
1410
|
-
<formly-field *ngFor="let f of field.fieldGroup" [field]="f"></formly-field>
|
|
1411
|
-
<ng-content></ng-content>
|
|
1412
|
-
`, isInline: true, components: [{ type: FormlyField, selector: "formly-field", inputs: ["field"] }], directives: [{ type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1413
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyGroup, decorators: [{
|
|
1166
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyTemplateType, decorators: [{
|
|
1414
1167
|
type: Component,
|
|
1415
1168
|
args: [{
|
|
1416
|
-
selector: 'formly-
|
|
1417
|
-
template:
|
|
1418
|
-
<formly-field *ngFor="let f of field.fieldGroup" [field]="f"></formly-field>
|
|
1419
|
-
<ng-content></ng-content>
|
|
1420
|
-
`,
|
|
1421
|
-
host: {
|
|
1422
|
-
'[class]': 'field.fieldGroupClassName || ""',
|
|
1423
|
-
},
|
|
1169
|
+
selector: 'formly-template',
|
|
1170
|
+
template: `<div [innerHtml]="template"></div>`,
|
|
1424
1171
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1425
1172
|
}]
|
|
1426
|
-
}] });
|
|
1173
|
+
}], ctorParameters: () => [{ type: i1.DomSanitizer }] });
|
|
1427
1174
|
|
|
1428
1175
|
/**
|
|
1429
|
-
*
|
|
1176
|
+
* Maintains list of formly config options. This can be used to register new field type.
|
|
1430
1177
|
*/
|
|
1431
|
-
class
|
|
1432
|
-
constructor(
|
|
1433
|
-
this.
|
|
1178
|
+
class FormlyConfig {
|
|
1179
|
+
constructor() {
|
|
1180
|
+
this.types = {};
|
|
1181
|
+
this.validators = {};
|
|
1182
|
+
this.wrappers = {};
|
|
1183
|
+
this.messages = {};
|
|
1184
|
+
this.extras = {
|
|
1185
|
+
checkExpressionOn: 'modelChange',
|
|
1186
|
+
lazyRender: true,
|
|
1187
|
+
resetFieldOnHide: true,
|
|
1188
|
+
renderFormlyFieldElement: true,
|
|
1189
|
+
showError(field) {
|
|
1190
|
+
return (field.formControl?.invalid &&
|
|
1191
|
+
(field.formControl?.touched || field.options.parentForm?.submitted || !!field.field.validation?.show));
|
|
1192
|
+
},
|
|
1193
|
+
};
|
|
1194
|
+
this.extensions = {};
|
|
1195
|
+
this.presets = {};
|
|
1196
|
+
this.extensionsByPriority = {};
|
|
1434
1197
|
}
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1198
|
+
addConfig(config) {
|
|
1199
|
+
if (Array.isArray(config)) {
|
|
1200
|
+
config.forEach((c) => this.addConfig(c));
|
|
1201
|
+
return;
|
|
1202
|
+
}
|
|
1203
|
+
if (config.types) {
|
|
1204
|
+
config.types.forEach((type) => this.setType(type));
|
|
1205
|
+
}
|
|
1206
|
+
if (config.validators) {
|
|
1207
|
+
config.validators.forEach((validator) => this.setValidator(validator));
|
|
1208
|
+
}
|
|
1209
|
+
if (config.wrappers) {
|
|
1210
|
+
config.wrappers.forEach((wrapper) => this.setWrapper(wrapper));
|
|
1211
|
+
}
|
|
1212
|
+
if (config.validationMessages) {
|
|
1213
|
+
config.validationMessages.forEach((validation) => this.addValidatorMessage(validation.name, validation.message));
|
|
1214
|
+
}
|
|
1215
|
+
if (config.extensions) {
|
|
1216
|
+
this.setSortedExtensions(config.extensions);
|
|
1217
|
+
}
|
|
1218
|
+
if (config.extras) {
|
|
1219
|
+
this.extras = { ...this.extras, ...config.extras };
|
|
1220
|
+
}
|
|
1221
|
+
if (config.presets) {
|
|
1222
|
+
this.presets = {
|
|
1223
|
+
...this.presets,
|
|
1224
|
+
...config.presets.reduce((acc, curr) => ({ ...acc, [curr.name]: curr.config }), {}),
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1444
1227
|
}
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
}
|
|
1457
|
-
}
|
|
1458
|
-
if (this.field.validation?.messages?.[error]) {
|
|
1459
|
-
message = this.field.validation.messages[error];
|
|
1460
|
-
}
|
|
1461
|
-
if (this.field.validators?.[error]?.message) {
|
|
1462
|
-
message = this.field.validators[error].message;
|
|
1463
|
-
}
|
|
1464
|
-
if (this.field.asyncValidators?.[error]?.message) {
|
|
1465
|
-
message = this.field.asyncValidators[error].message;
|
|
1466
|
-
}
|
|
1467
|
-
if (typeof message === 'function') {
|
|
1468
|
-
return message(fieldForm.errors[error], this.field);
|
|
1469
|
-
}
|
|
1470
|
-
return message;
|
|
1228
|
+
/**
|
|
1229
|
+
* Allows you to specify a custom type which you can use in your field configuration.
|
|
1230
|
+
* You can pass an object of options, or an array of objects of options.
|
|
1231
|
+
*/
|
|
1232
|
+
setType(options) {
|
|
1233
|
+
if (Array.isArray(options)) {
|
|
1234
|
+
options.forEach((option) => this.setType(option));
|
|
1235
|
+
}
|
|
1236
|
+
else {
|
|
1237
|
+
if (!this.types[options.name]) {
|
|
1238
|
+
this.types[options.name] = { name: options.name };
|
|
1471
1239
|
}
|
|
1240
|
+
['component', 'extends', 'defaultOptions', 'wrappers'].forEach((prop) => {
|
|
1241
|
+
if (options.hasOwnProperty(prop)) {
|
|
1242
|
+
this.types[options.name][prop] = options[prop];
|
|
1243
|
+
}
|
|
1244
|
+
});
|
|
1472
1245
|
}
|
|
1473
|
-
return undefined;
|
|
1474
1246
|
}
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyValidationMessage, decorators: [{
|
|
1479
|
-
type: Component,
|
|
1480
|
-
args: [{
|
|
1481
|
-
selector: 'formly-validation-message',
|
|
1482
|
-
template: '{{ errorMessage$ | async }}',
|
|
1483
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1484
|
-
}]
|
|
1485
|
-
}], ctorParameters: function () { return [{ type: FormlyConfig }]; }, propDecorators: { field: [{
|
|
1486
|
-
type: Input
|
|
1487
|
-
}] } });
|
|
1488
|
-
|
|
1489
|
-
class FieldArrayType extends FieldType {
|
|
1490
|
-
onPopulate(field) {
|
|
1491
|
-
if (hasKey(field)) {
|
|
1492
|
-
const control = findControl(field);
|
|
1493
|
-
registerControl(field, control ? control : new FormArray([], { updateOn: field.modelOptions.updateOn }));
|
|
1247
|
+
getType(name, throwIfNotFound = false) {
|
|
1248
|
+
if (name instanceof Type) {
|
|
1249
|
+
return { component: name, name: name.prototype.constructor.name };
|
|
1494
1250
|
}
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
for (let i = field.fieldGroup.length - 1; i >= length; --i) {
|
|
1499
|
-
unregisterControl(field.fieldGroup[i], true);
|
|
1500
|
-
field.fieldGroup.splice(i, 1);
|
|
1251
|
+
if (!this.types[name]) {
|
|
1252
|
+
if (throwIfNotFound) {
|
|
1253
|
+
throw new Error(`[Formly Error] The type "${name}" could not be found. Please make sure that is registered through the FormlyModule declaration.`);
|
|
1501
1254
|
}
|
|
1255
|
+
return null;
|
|
1502
1256
|
}
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1257
|
+
this.mergeExtendedType(name);
|
|
1258
|
+
return this.types[name];
|
|
1259
|
+
}
|
|
1260
|
+
/** @ignore */
|
|
1261
|
+
getMergedField(field = {}) {
|
|
1262
|
+
const type = this.getType(field.type);
|
|
1263
|
+
if (!type) {
|
|
1264
|
+
return;
|
|
1265
|
+
}
|
|
1266
|
+
if (type.defaultOptions) {
|
|
1267
|
+
reverseDeepMerge(field, type.defaultOptions);
|
|
1268
|
+
}
|
|
1269
|
+
const extendDefaults = type.extends && this.getType(type.extends).defaultOptions;
|
|
1270
|
+
if (extendDefaults) {
|
|
1271
|
+
reverseDeepMerge(field, extendDefaults);
|
|
1272
|
+
}
|
|
1273
|
+
if (field?.optionsTypes) {
|
|
1274
|
+
field.optionsTypes.forEach((option) => {
|
|
1275
|
+
const defaultOptions = this.getType(option).defaultOptions;
|
|
1276
|
+
if (defaultOptions) {
|
|
1277
|
+
reverseDeepMerge(field, defaultOptions);
|
|
1278
|
+
}
|
|
1279
|
+
});
|
|
1280
|
+
}
|
|
1281
|
+
const componentRef = this.resolveFieldTypeRef(field);
|
|
1282
|
+
if (componentRef?.instance?.defaultOptions) {
|
|
1283
|
+
reverseDeepMerge(field, componentRef.instance.defaultOptions);
|
|
1284
|
+
}
|
|
1285
|
+
if (!field.wrappers && type.wrappers) {
|
|
1286
|
+
field.wrappers = [...type.wrappers];
|
|
1509
1287
|
}
|
|
1510
1288
|
}
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
if (!
|
|
1515
|
-
|
|
1289
|
+
/** @ignore @internal */
|
|
1290
|
+
resolveFieldTypeRef(field = {}) {
|
|
1291
|
+
const type = this.getType(field.type);
|
|
1292
|
+
if (!type) {
|
|
1293
|
+
return null;
|
|
1516
1294
|
}
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1295
|
+
if (!type.component || type._componentRef) {
|
|
1296
|
+
return type._componentRef;
|
|
1297
|
+
}
|
|
1298
|
+
const { _viewContainerRef, _injector } = field.options;
|
|
1299
|
+
if (!_viewContainerRef || !_injector) {
|
|
1300
|
+
return null;
|
|
1301
|
+
}
|
|
1302
|
+
const componentRef = _viewContainerRef.createComponent(type.component, { injector: _injector });
|
|
1303
|
+
defineHiddenProp(type, '_componentRef', componentRef);
|
|
1304
|
+
try {
|
|
1305
|
+
componentRef.destroy();
|
|
1306
|
+
}
|
|
1307
|
+
catch (e) {
|
|
1308
|
+
console.error(`An error occurred while destroying the Formly component type "${field.type}"`, e);
|
|
1309
|
+
}
|
|
1310
|
+
return type._componentRef;
|
|
1520
1311
|
}
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
this._build();
|
|
1312
|
+
setWrapper(options) {
|
|
1313
|
+
this.wrappers[options.name] = options;
|
|
1314
|
+
if (options.types) {
|
|
1315
|
+
options.types.forEach((type) => {
|
|
1316
|
+
this.setTypeWrapper(type, options.name);
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1529
1319
|
}
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1320
|
+
getWrapper(name) {
|
|
1321
|
+
if (name instanceof Type) {
|
|
1322
|
+
return { component: name, name: name.prototype.constructor.name };
|
|
1323
|
+
}
|
|
1324
|
+
if (!this.wrappers[name]) {
|
|
1325
|
+
throw new Error(`[Formly Error] The wrapper "${name}" could not be found. Please make sure that is registered through the FormlyModule declaration.`);
|
|
1326
|
+
}
|
|
1327
|
+
return this.wrappers[name];
|
|
1538
1328
|
}
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1329
|
+
/** @ignore */
|
|
1330
|
+
setTypeWrapper(type, name) {
|
|
1331
|
+
if (!this.types[type]) {
|
|
1332
|
+
this.types[type] = {};
|
|
1543
1333
|
}
|
|
1544
|
-
if (!
|
|
1545
|
-
|
|
1334
|
+
if (!this.types[type].wrappers) {
|
|
1335
|
+
this.types[type].wrappers = [];
|
|
1546
1336
|
}
|
|
1547
|
-
|
|
1548
|
-
this.
|
|
1337
|
+
if (this.types[type].wrappers.indexOf(name) === -1) {
|
|
1338
|
+
this.types[type].wrappers.push(name);
|
|
1549
1339
|
}
|
|
1550
1340
|
}
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
this.options._hiddenFieldsForCheck.push({ field: f });
|
|
1341
|
+
setValidator(options) {
|
|
1342
|
+
this.validators[options.name] = options;
|
|
1343
|
+
}
|
|
1344
|
+
getValidator(name) {
|
|
1345
|
+
if (!this.validators[name]) {
|
|
1346
|
+
throw new Error(`[Formly Error] The validator "${name}" could not be found. Please make sure that is registered through the FormlyModule declaration.`);
|
|
1558
1347
|
}
|
|
1348
|
+
return this.validators[name];
|
|
1559
1349
|
}
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1350
|
+
addValidatorMessage(name, message) {
|
|
1351
|
+
this.messages[name] = message;
|
|
1352
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
1353
|
+
const deprecated = { minlength: 'minLength', maxlength: 'maxLength' };
|
|
1354
|
+
if (deprecated[name]) {
|
|
1355
|
+
console.warn(`Formly deprecation: passing validation messages key '${name}' is deprecated since v6.0, use '${deprecated[name]}' instead.`);
|
|
1356
|
+
this.messages[deprecated[name]] = message;
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
getValidatorMessage(name) {
|
|
1361
|
+
return this.messages[name];
|
|
1362
|
+
}
|
|
1363
|
+
setSortedExtensions(extensionOptions) {
|
|
1364
|
+
// insert new extensions, grouped by priority
|
|
1365
|
+
extensionOptions.forEach((extensionOption) => {
|
|
1366
|
+
const priority = extensionOption.priority ?? 1;
|
|
1367
|
+
this.extensionsByPriority[priority] = {
|
|
1368
|
+
...this.extensionsByPriority[priority],
|
|
1369
|
+
[extensionOption.name]: extensionOption.extension,
|
|
1370
|
+
};
|
|
1371
|
+
});
|
|
1372
|
+
// flatten extensions object with sorted keys
|
|
1373
|
+
this.extensions = Object.keys(this.extensionsByPriority)
|
|
1374
|
+
.map(Number)
|
|
1375
|
+
.sort((a, b) => a - b)
|
|
1376
|
+
.reduce((acc, prio) => ({
|
|
1377
|
+
...acc,
|
|
1378
|
+
...this.extensionsByPriority[prio],
|
|
1379
|
+
}), {});
|
|
1380
|
+
}
|
|
1381
|
+
mergeExtendedType(name) {
|
|
1382
|
+
if (!this.types[name].extends) {
|
|
1383
|
+
return;
|
|
1384
|
+
}
|
|
1385
|
+
const extendedType = this.getType(this.types[name].extends);
|
|
1386
|
+
if (!this.types[name].component) {
|
|
1387
|
+
this.types[name].component = extendedType.component;
|
|
1388
|
+
}
|
|
1389
|
+
if (!this.types[name].wrappers) {
|
|
1390
|
+
this.types[name].wrappers = extendedType.wrappers;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1394
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyConfig, providedIn: 'root' }); }
|
|
1395
|
+
}
|
|
1396
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyConfig, decorators: [{
|
|
1397
|
+
type: Injectable,
|
|
1398
|
+
args: [{ providedIn: 'root' }]
|
|
1565
1399
|
}] });
|
|
1566
1400
|
|
|
1567
|
-
class
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1401
|
+
class FormlyTemplate {
|
|
1402
|
+
constructor(ref) {
|
|
1403
|
+
this.ref = ref;
|
|
1404
|
+
}
|
|
1405
|
+
ngOnChanges() {
|
|
1406
|
+
this.name = this.name || 'formly-group';
|
|
1571
1407
|
}
|
|
1408
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyTemplate, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1409
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: FormlyTemplate, selector: "[formlyTemplate]", inputs: { name: ["formlyTemplate", "name"] }, usesOnChanges: true, ngImport: i0 }); }
|
|
1572
1410
|
}
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
args: ['fieldComponent', { read: ViewContainerRef }]
|
|
1580
|
-
}], _staticContent: [{
|
|
1581
|
-
type: ViewChild,
|
|
1582
|
-
args: ['fieldComponent', { read: ViewContainerRef, static: true }]
|
|
1411
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyTemplate, decorators: [{
|
|
1412
|
+
type: Directive,
|
|
1413
|
+
args: [{ selector: '[formlyTemplate]' }]
|
|
1414
|
+
}], ctorParameters: () => [{ type: i0.TemplateRef }], propDecorators: { name: [{
|
|
1415
|
+
type: Input,
|
|
1416
|
+
args: ['formlyTemplate']
|
|
1583
1417
|
}] } });
|
|
1418
|
+
// workarround for https://github.com/angular/angular/issues/43227#issuecomment-904173738
|
|
1419
|
+
class FormlyFieldTemplates {
|
|
1420
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyFieldTemplates, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1421
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyFieldTemplates }); }
|
|
1422
|
+
}
|
|
1423
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyFieldTemplates, decorators: [{
|
|
1424
|
+
type: Injectable
|
|
1425
|
+
}] });
|
|
1584
1426
|
|
|
1585
|
-
/**
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
this.
|
|
1427
|
+
/**
|
|
1428
|
+
* The `<formly-field>` component is used to render the UI widget (layout + type) of a given `field`.
|
|
1429
|
+
*/
|
|
1430
|
+
class FormlyField {
|
|
1431
|
+
get containerRef() {
|
|
1432
|
+
return this.config.extras.renderFormlyFieldElement ? this.viewContainerRef : this.hostContainerRef;
|
|
1591
1433
|
}
|
|
1592
|
-
get
|
|
1593
|
-
if (this.
|
|
1594
|
-
this.
|
|
1595
|
-
template: this.field.template,
|
|
1596
|
-
content: this.props.safeHtml
|
|
1597
|
-
? this.sanitizer.bypassSecurityTrustHtml(this.field.template)
|
|
1598
|
-
: this.field.template,
|
|
1599
|
-
};
|
|
1434
|
+
get elementRef() {
|
|
1435
|
+
if (this.config.extras.renderFormlyFieldElement) {
|
|
1436
|
+
return this._elementRef;
|
|
1600
1437
|
}
|
|
1601
|
-
|
|
1438
|
+
if (this.componentRefs?.[0] instanceof ComponentRef) {
|
|
1439
|
+
return this.componentRefs[0].location;
|
|
1440
|
+
}
|
|
1441
|
+
return null;
|
|
1602
1442
|
}
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
function evalStringExpression(expression, argNames) {
|
|
1616
|
-
try {
|
|
1617
|
-
return Function(...argNames, `return ${expression};`);
|
|
1443
|
+
constructor(config, renderer, _elementRef, hostContainerRef, form) {
|
|
1444
|
+
this.config = config;
|
|
1445
|
+
this.renderer = renderer;
|
|
1446
|
+
this._elementRef = _elementRef;
|
|
1447
|
+
this.hostContainerRef = hostContainerRef;
|
|
1448
|
+
this.form = form;
|
|
1449
|
+
this.hostObservers = [];
|
|
1450
|
+
this.componentRefs = [];
|
|
1451
|
+
this.hooksObservers = [];
|
|
1452
|
+
this.detectFieldBuild = false;
|
|
1453
|
+
this.valueChangesUnsubscribe = () => { };
|
|
1618
1454
|
}
|
|
1619
|
-
|
|
1620
|
-
|
|
1455
|
+
ngAfterContentInit() {
|
|
1456
|
+
this.triggerHook('afterContentInit');
|
|
1621
1457
|
}
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
if (typeof expression === 'function') {
|
|
1625
|
-
return expression.apply(thisArg, argVal);
|
|
1458
|
+
ngAfterViewInit() {
|
|
1459
|
+
this.triggerHook('afterViewInit');
|
|
1626
1460
|
}
|
|
1627
|
-
|
|
1628
|
-
|
|
1461
|
+
ngDoCheck() {
|
|
1462
|
+
if (this.detectFieldBuild && this.field && this.field.options) {
|
|
1463
|
+
this.render();
|
|
1464
|
+
}
|
|
1629
1465
|
}
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1466
|
+
ngOnInit() {
|
|
1467
|
+
this.triggerHook('onInit');
|
|
1468
|
+
}
|
|
1469
|
+
ngOnChanges(changes) {
|
|
1470
|
+
this.triggerHook('onChanges', changes);
|
|
1471
|
+
}
|
|
1472
|
+
ngOnDestroy() {
|
|
1473
|
+
this.resetRefs(this.field);
|
|
1474
|
+
this.hostObservers.forEach((hostObserver) => hostObserver.unsubscribe());
|
|
1475
|
+
this.hooksObservers.forEach((unsubscribe) => unsubscribe());
|
|
1476
|
+
this.valueChangesUnsubscribe();
|
|
1477
|
+
this.triggerHook('onDestroy');
|
|
1478
|
+
}
|
|
1479
|
+
renderField(containerRef, f, wrappers = []) {
|
|
1480
|
+
if (this.containerRef === containerRef) {
|
|
1481
|
+
this.resetRefs(this.field);
|
|
1482
|
+
this.containerRef.clear();
|
|
1483
|
+
wrappers = this.field?.wrappers;
|
|
1636
1484
|
}
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1485
|
+
if (wrappers?.length > 0) {
|
|
1486
|
+
const [wrapper, ...wps] = wrappers;
|
|
1487
|
+
const { component } = this.config.getWrapper(wrapper);
|
|
1488
|
+
const ref = containerRef.createComponent(component);
|
|
1489
|
+
this.attachComponentRef(ref, f);
|
|
1490
|
+
observe(ref.instance, ['fieldComponent'], ({ currentValue, previousValue, firstChange }) => {
|
|
1491
|
+
if (currentValue) {
|
|
1492
|
+
if (previousValue && previousValue._lContainer === currentValue._lContainer) {
|
|
1493
|
+
return;
|
|
1494
|
+
}
|
|
1495
|
+
const viewRef = previousValue ? previousValue.detach() : null;
|
|
1496
|
+
if (viewRef && !viewRef.destroyed) {
|
|
1497
|
+
currentValue.insert(viewRef);
|
|
1498
|
+
}
|
|
1499
|
+
else {
|
|
1500
|
+
this.renderField(currentValue, f, wps);
|
|
1501
|
+
}
|
|
1502
|
+
!firstChange && ref.changeDetectorRef.detectChanges();
|
|
1503
|
+
}
|
|
1649
1504
|
});
|
|
1650
1505
|
}
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1506
|
+
else if (f?.type) {
|
|
1507
|
+
const inlineType = this.form?.templates?.find((ref) => ref.name === f.type);
|
|
1508
|
+
let ref;
|
|
1509
|
+
if (inlineType) {
|
|
1510
|
+
ref = containerRef.createEmbeddedView(inlineType.ref, { $implicit: f });
|
|
1654
1511
|
}
|
|
1655
|
-
else
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
this.evalExpr(field, key, v);
|
|
1659
|
-
field.options._detectChanges(field);
|
|
1660
|
-
})),
|
|
1661
|
-
};
|
|
1512
|
+
else {
|
|
1513
|
+
const { component } = this.config.getType(f.type, true);
|
|
1514
|
+
ref = containerRef.createComponent(component);
|
|
1662
1515
|
}
|
|
1663
|
-
|
|
1664
|
-
field.expressions = field.expressions || {};
|
|
1665
|
-
for (const key of Object.keys(field.expressions)) {
|
|
1666
|
-
observe(field, ['expressions', key], ({ currentValue: expr }) => {
|
|
1667
|
-
evalExpr(key, isFunction(expr) ? (...args) => expr(field, args[3]) : expr);
|
|
1668
|
-
});
|
|
1516
|
+
this.attachComponentRef(ref, f);
|
|
1669
1517
|
}
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1518
|
+
}
|
|
1519
|
+
triggerHook(name, changes) {
|
|
1520
|
+
if (name === 'onInit' || (name === 'onChanges' && changes.field && !changes.field.firstChange)) {
|
|
1521
|
+
this.valueChangesUnsubscribe();
|
|
1522
|
+
this.valueChangesUnsubscribe = this.fieldChanges(this.field);
|
|
1523
|
+
}
|
|
1524
|
+
if (this.field?.hooks?.[name]) {
|
|
1525
|
+
if (!changes || changes.field) {
|
|
1526
|
+
const r = this.field.hooks[name](this.field);
|
|
1527
|
+
if (isObservable(r) && ['onInit', 'afterContentInit', 'afterViewInit'].indexOf(name) !== -1) {
|
|
1528
|
+
const sub = r.subscribe();
|
|
1529
|
+
this.hooksObservers.push(() => sub.unsubscribe());
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
if (name === 'onChanges' && changes.field) {
|
|
1534
|
+
this.resetRefs(changes.field.previousValue);
|
|
1535
|
+
this.render();
|
|
1673
1536
|
}
|
|
1674
1537
|
}
|
|
1675
|
-
|
|
1676
|
-
|
|
1538
|
+
attachComponentRef(ref, field) {
|
|
1539
|
+
this.componentRefs.push(ref);
|
|
1540
|
+
field._componentRefs.push(ref);
|
|
1541
|
+
if (ref instanceof ComponentRef) {
|
|
1542
|
+
Object.assign(ref.instance, { field });
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
render() {
|
|
1546
|
+
if (!this.field) {
|
|
1677
1547
|
return;
|
|
1678
1548
|
}
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
return;
|
|
1684
|
-
}
|
|
1685
|
-
checkLocked = true;
|
|
1686
|
-
const fieldChanged = this.checkExpressions(f, ignoreCache);
|
|
1687
|
-
const options = field.options;
|
|
1688
|
-
options._hiddenFieldsForCheck
|
|
1689
|
-
.sort((f) => (f.field.hide ? -1 : 1))
|
|
1690
|
-
.forEach((f) => this.changeHideState(f.field, f.field.hide ?? f.default, !ignoreCache));
|
|
1691
|
-
options._hiddenFieldsForCheck = [];
|
|
1692
|
-
if (fieldChanged) {
|
|
1693
|
-
this.checkExpressions(field);
|
|
1694
|
-
}
|
|
1695
|
-
checkLocked = false;
|
|
1696
|
-
};
|
|
1697
|
-
field.options._checkField = (f, ignoreCache) => {
|
|
1698
|
-
console.warn(`Formly: 'options._checkField' is deprecated since v6.0, use 'options.checkExpressions' instead.`);
|
|
1699
|
-
field.options.checkExpressions(f, ignoreCache);
|
|
1700
|
-
};
|
|
1549
|
+
// require Formly build
|
|
1550
|
+
if (!this.field.options) {
|
|
1551
|
+
this.detectFieldBuild = true;
|
|
1552
|
+
return;
|
|
1701
1553
|
}
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1554
|
+
this.detectFieldBuild = false;
|
|
1555
|
+
this.hostObservers.forEach((hostObserver) => hostObserver.unsubscribe());
|
|
1556
|
+
this.hostObservers = [
|
|
1557
|
+
observe(this.field, ['hide'], ({ firstChange, currentValue }) => {
|
|
1558
|
+
const containerRef = this.containerRef;
|
|
1559
|
+
if (this.config.extras.lazyRender === false) {
|
|
1560
|
+
firstChange && this.renderField(containerRef, this.field);
|
|
1561
|
+
if (!firstChange || (firstChange && currentValue)) {
|
|
1562
|
+
this.elementRef &&
|
|
1563
|
+
this.renderer.setStyle(this.elementRef.nativeElement, 'display', currentValue ? 'none' : '');
|
|
1564
|
+
}
|
|
1713
1565
|
}
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
if (ignoreCache ||
|
|
1727
|
-
(currentValue !== exprValue &&
|
|
1728
|
-
(!isObject(exprValue) ||
|
|
1729
|
-
isObservable(exprValue) ||
|
|
1730
|
-
JSON.stringify(exprValue) !== JSON.stringify(currentValue)))) {
|
|
1731
|
-
currentValue = exprValue;
|
|
1732
|
-
this.evalExpr(field, path, exprValue);
|
|
1733
|
-
return true;
|
|
1566
|
+
else {
|
|
1567
|
+
if (currentValue) {
|
|
1568
|
+
containerRef.clear();
|
|
1569
|
+
if (this.field.className) {
|
|
1570
|
+
this.renderer.removeAttribute(this.elementRef.nativeElement, 'class');
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
else {
|
|
1574
|
+
this.renderField(containerRef, this.field);
|
|
1575
|
+
if (this.field.className) {
|
|
1576
|
+
this.renderer.setAttribute(this.elementRef.nativeElement, 'class', this.field.className);
|
|
1577
|
+
}
|
|
1734
1578
|
}
|
|
1735
|
-
return false;
|
|
1736
1579
|
}
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1580
|
+
!firstChange && this.field.options.detectChanges(this.field);
|
|
1581
|
+
}),
|
|
1582
|
+
observe(this.field, ['className'], ({ firstChange, currentValue }) => {
|
|
1583
|
+
if ((!firstChange || (firstChange && currentValue)) &&
|
|
1584
|
+
(!this.config.extras.lazyRender || this.field.hide !== true)) {
|
|
1585
|
+
this.elementRef && this.renderer.setAttribute(this.elementRef.nativeElement, 'class', currentValue);
|
|
1740
1586
|
}
|
|
1741
|
-
},
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
if (!field) {
|
|
1746
|
-
return false;
|
|
1587
|
+
}),
|
|
1588
|
+
];
|
|
1589
|
+
if (!isSignalRequired()) {
|
|
1590
|
+
['touched', 'pristine', 'status'].forEach((prop) => this.hostObservers.push(observe(this.field, ['formControl', prop], ({ firstChange }) => !firstChange && markFieldForCheck(this.field))));
|
|
1747
1591
|
}
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
field._expressions[key].callback?.(ignoreCache) && (fieldChanged = true);
|
|
1752
|
-
}
|
|
1592
|
+
else if (this.field.formControl) {
|
|
1593
|
+
const events = this.field.formControl.events.subscribe(() => markFieldForCheck(this.field));
|
|
1594
|
+
this.hostObservers.push(events);
|
|
1753
1595
|
}
|
|
1754
|
-
field.fieldGroup?.forEach((f) => this.checkExpressions(f, ignoreCache) && (fieldChanged = true));
|
|
1755
|
-
return fieldChanged;
|
|
1756
1596
|
}
|
|
1757
|
-
|
|
1758
|
-
if (field
|
|
1759
|
-
field.
|
|
1760
|
-
.
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1597
|
+
resetRefs(field) {
|
|
1598
|
+
if (field) {
|
|
1599
|
+
if (field._localFields) {
|
|
1600
|
+
field._localFields = [];
|
|
1601
|
+
}
|
|
1602
|
+
else {
|
|
1603
|
+
defineHiddenProp(this.field, '_localFields', []);
|
|
1604
|
+
}
|
|
1605
|
+
if (field._componentRefs) {
|
|
1606
|
+
field._componentRefs = field._componentRefs.filter((ref) => this.componentRefs.indexOf(ref) === -1);
|
|
1607
|
+
}
|
|
1608
|
+
else {
|
|
1609
|
+
defineHiddenProp(this.field, '_componentRefs', []);
|
|
1610
|
+
}
|
|
1765
1611
|
}
|
|
1612
|
+
this.componentRefs = [];
|
|
1766
1613
|
}
|
|
1767
|
-
|
|
1768
|
-
if (field
|
|
1769
|
-
|
|
1770
|
-
.filter((f) => f && !f._expressions.hide)
|
|
1771
|
-
.forEach((f) => this.changeHideState(f, hide, resetOnHide));
|
|
1614
|
+
fieldChanges(field) {
|
|
1615
|
+
if (!field) {
|
|
1616
|
+
return () => { };
|
|
1772
1617
|
}
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
if (
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
field.options.fieldChanges.next({ value: undefined, field, type: 'valueChanges' });
|
|
1785
|
-
if (field.fieldGroup && field.formControl instanceof FormArray) {
|
|
1786
|
-
field.fieldGroup.length = 0;
|
|
1787
|
-
}
|
|
1618
|
+
const propsObserver = observeDeep(field, ['props'], () => field.options.detectChanges(field));
|
|
1619
|
+
const subscribes = [
|
|
1620
|
+
() => {
|
|
1621
|
+
propsObserver();
|
|
1622
|
+
},
|
|
1623
|
+
];
|
|
1624
|
+
for (const key of Object.keys(field._expressions || {})) {
|
|
1625
|
+
const expressionObserver = observe(field, ['_expressions', key], ({ currentValue, previousValue }) => {
|
|
1626
|
+
if (previousValue?.subscription) {
|
|
1627
|
+
previousValue.subscription.unsubscribe();
|
|
1628
|
+
previousValue.subscription = null;
|
|
1788
1629
|
}
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
if (field.resetOnHide && !isUndefined(field.defaultValue) && isUndefined(getFieldValue(field))) {
|
|
1792
|
-
assignFieldValue(field, field.defaultValue);
|
|
1630
|
+
if (isObservable(currentValue.value$)) {
|
|
1631
|
+
currentValue.subscription = currentValue.value$.subscribe();
|
|
1793
1632
|
}
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1633
|
+
});
|
|
1634
|
+
subscribes.push(() => {
|
|
1635
|
+
if (field._expressions[key]?.subscription) {
|
|
1636
|
+
field._expressions[key].subscription.unsubscribe();
|
|
1797
1637
|
}
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
if (field.options.fieldChanges) {
|
|
1801
|
-
field.options.fieldChanges.next({ field, type: 'hidden', value: hide });
|
|
1638
|
+
expressionObserver.unsubscribe();
|
|
1639
|
+
});
|
|
1802
1640
|
}
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
const key = prop.replace(/^model\./, ''), parent = field.fieldGroup ? field : field.parent;
|
|
1807
|
-
let control = field?.key === key ? field.formControl : field.form.get(key);
|
|
1808
|
-
if (!control && field.get(key)) {
|
|
1809
|
-
control = field.get(key).formControl;
|
|
1810
|
-
}
|
|
1811
|
-
assignFieldValue({ key, parent, model: field.model }, value);
|
|
1812
|
-
if (control && !(isNil(control.value) && isNil(value)) && control.value !== value) {
|
|
1813
|
-
control.patchValue(value);
|
|
1814
|
-
}
|
|
1641
|
+
for (const path of [['focus'], ['template'], ['fieldGroupClassName'], ['validation', 'show']]) {
|
|
1642
|
+
const fieldObserver = observe(field, path, ({ firstChange }) => !firstChange && field.options.detectChanges(field));
|
|
1643
|
+
subscribes.push(() => fieldObserver.unsubscribe());
|
|
1815
1644
|
}
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
target = target[paths[i]];
|
|
1645
|
+
if (field.formControl && !field.fieldGroup) {
|
|
1646
|
+
const control = field.formControl;
|
|
1647
|
+
let valueChanges = control.valueChanges.pipe(map((value) => {
|
|
1648
|
+
field.parsers?.map((parserFn) => (value = parserFn(value, field)));
|
|
1649
|
+
if (!Object.is(value, field.formControl.value)) {
|
|
1650
|
+
field.formControl.setValue(value);
|
|
1823
1651
|
}
|
|
1824
|
-
|
|
1825
|
-
}
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1652
|
+
return value;
|
|
1653
|
+
}), distinctUntilChanged((x, y) => {
|
|
1654
|
+
if (x !== y || Array.isArray(x) || isObject(x)) {
|
|
1655
|
+
return false;
|
|
1656
|
+
}
|
|
1657
|
+
return true;
|
|
1658
|
+
}));
|
|
1659
|
+
if (control.value !== getFieldValue(field)) {
|
|
1660
|
+
valueChanges = valueChanges.pipe(startWith(control.value));
|
|
1829
1661
|
}
|
|
1830
|
-
|
|
1831
|
-
|
|
1662
|
+
const { updateOn, debounce } = field.modelOptions;
|
|
1663
|
+
if ((!updateOn || updateOn === 'change') && debounce?.default > 0) {
|
|
1664
|
+
valueChanges = control.valueChanges.pipe(debounceTime(debounce.default));
|
|
1832
1665
|
}
|
|
1666
|
+
const sub = valueChanges.subscribe((value) => {
|
|
1667
|
+
// workaround for https://github.com/angular/angular/issues/13792
|
|
1668
|
+
if (control._fields?.length > 1 && control instanceof FormControl) {
|
|
1669
|
+
control.patchValue(value, { emitEvent: false, onlySelf: true });
|
|
1670
|
+
}
|
|
1671
|
+
if (hasKey(field)) {
|
|
1672
|
+
assignFieldValue(field, value);
|
|
1673
|
+
}
|
|
1674
|
+
field.options.fieldChanges.next({ value, field, type: 'valueChanges' });
|
|
1675
|
+
});
|
|
1676
|
+
subscribes.push(() => sub.unsubscribe());
|
|
1833
1677
|
}
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
return;
|
|
1839
|
-
}
|
|
1840
|
-
field.options.fieldChanges.next({
|
|
1841
|
-
field,
|
|
1842
|
-
type: 'expressionChanges',
|
|
1843
|
-
property,
|
|
1844
|
-
value,
|
|
1678
|
+
let templateFieldsSubs = [];
|
|
1679
|
+
observe(field, ['_localFields'], ({ currentValue }) => {
|
|
1680
|
+
templateFieldsSubs.forEach((unsubscribe) => unsubscribe());
|
|
1681
|
+
templateFieldsSubs = (currentValue || []).map((f) => this.fieldChanges(f));
|
|
1845
1682
|
});
|
|
1683
|
+
return () => {
|
|
1684
|
+
subscribes.forEach((unsubscribe) => unsubscribe());
|
|
1685
|
+
templateFieldsSubs.forEach((unsubscribe) => unsubscribe());
|
|
1686
|
+
};
|
|
1846
1687
|
}
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1688
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyField, deps: [{ token: FormlyConfig }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: FormlyFieldTemplates, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1689
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: FormlyField, isStandalone: true, selector: "formly-field", inputs: { field: "field" }, viewQueries: [{ propertyName: "viewContainerRef", first: true, predicate: ["container"], descendants: true, read: ViewContainerRef, static: true }], usesOnChanges: true, ngImport: i0, template: '<ng-template #container></ng-template>', isInline: true, styles: [":host:empty{display:none}\n"] }); }
|
|
1690
|
+
}
|
|
1691
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyField, decorators: [{
|
|
1692
|
+
type: Component,
|
|
1693
|
+
args: [{ selector: 'formly-field', template: '<ng-template #container></ng-template>', standalone: true, styles: [":host:empty{display:none}\n"] }]
|
|
1694
|
+
}], ctorParameters: () => [{ type: FormlyConfig }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: FormlyFieldTemplates, decorators: [{
|
|
1695
|
+
type: Optional
|
|
1696
|
+
}] }], propDecorators: { field: [{
|
|
1697
|
+
type: Input
|
|
1698
|
+
}], viewContainerRef: [{
|
|
1699
|
+
type: ViewChild,
|
|
1700
|
+
args: ['container', { read: ViewContainerRef, static: true }]
|
|
1701
|
+
}] } });
|
|
1702
|
+
class LegacyFormlyField extends FormlyField {
|
|
1703
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LegacyFormlyField, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
1704
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: LegacyFormlyField, selector: "formly-field", usesInheritance: true, ngImport: i0, template: '<ng-template #container></ng-template>', isInline: true, styles: [":host:empty{display:none}\n"] }); }
|
|
1705
|
+
}
|
|
1706
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LegacyFormlyField, decorators: [{
|
|
1707
|
+
type: Component,
|
|
1708
|
+
args: [{ selector: 'formly-field', template: '<ng-template #container></ng-template>', standalone: false, styles: [":host:empty{display:none}\n"] }]
|
|
1709
|
+
}] });
|
|
1710
|
+
|
|
1711
|
+
/** @ignore */
|
|
1712
|
+
class FormlyGroup extends FieldType {
|
|
1713
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyGroup, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
1714
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: FormlyGroup, selector: "formly-group", host: { properties: { "class": "field.fieldGroupClassName || \"\"" } }, usesInheritance: true, ngImport: i0, template: `
|
|
1715
|
+
<formly-field *ngFor="let f of field.fieldGroup" [field]="f"></formly-field>
|
|
1716
|
+
<ng-content></ng-content>
|
|
1717
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: LegacyFormlyField, selector: "formly-field" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1718
|
+
}
|
|
1719
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyGroup, decorators: [{
|
|
1720
|
+
type: Component,
|
|
1721
|
+
args: [{
|
|
1722
|
+
selector: 'formly-group',
|
|
1723
|
+
template: `
|
|
1724
|
+
<formly-field *ngFor="let f of field.fieldGroup" [field]="f"></formly-field>
|
|
1725
|
+
<ng-content></ng-content>
|
|
1726
|
+
`,
|
|
1727
|
+
host: {
|
|
1728
|
+
'[class]': 'field.fieldGroupClassName || ""',
|
|
1729
|
+
},
|
|
1730
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1731
|
+
}]
|
|
1732
|
+
}] });
|
|
1733
|
+
|
|
1734
|
+
/**
|
|
1735
|
+
* An InjectionToken for registering additional formly config options (types, wrappers ...).
|
|
1736
|
+
*/
|
|
1737
|
+
const FORMLY_CONFIG = new InjectionToken('FORMLY_CONFIG');
|
|
1738
|
+
function withDefaultConfig(config) {
|
|
1739
|
+
return {
|
|
1740
|
+
types: [
|
|
1741
|
+
{ name: 'formly-group', component: FormlyGroup },
|
|
1742
|
+
{ name: 'formly-template', component: FormlyTemplateType },
|
|
1743
|
+
],
|
|
1744
|
+
extensions: [
|
|
1745
|
+
{ name: 'core', extension: new CoreExtension(config), priority: -250 },
|
|
1746
|
+
{ name: 'field-validation', extension: new FieldValidationExtension(config), priority: -200 },
|
|
1747
|
+
{ name: 'field-form', extension: new FieldFormExtension(), priority: -150 },
|
|
1748
|
+
{ name: 'field-expression', extension: new FieldExpressionExtension(), priority: -100 },
|
|
1749
|
+
],
|
|
1750
|
+
};
|
|
1751
|
+
}
|
|
1752
|
+
const provideFormlyCore = (configs = []) => {
|
|
1753
|
+
return [
|
|
1754
|
+
{ provide: FORMLY_CONFIG, multi: true, useFactory: withDefaultConfig, deps: [FormlyConfig] },
|
|
1755
|
+
provideFormlyConfig(configs),
|
|
1756
|
+
];
|
|
1757
|
+
};
|
|
1758
|
+
const provideFormlyConfig = (configs = []) => {
|
|
1759
|
+
return [{ provide: FORMLY_CONFIG, multi: true, useValue: configs }];
|
|
1760
|
+
};
|
|
1761
|
+
|
|
1762
|
+
class FormlyFormBuilder {
|
|
1763
|
+
constructor(config, injector, viewContainerRef, parentForm, configs = []) {
|
|
1764
|
+
this.config = config;
|
|
1765
|
+
this.injector = injector;
|
|
1766
|
+
this.viewContainerRef = viewContainerRef;
|
|
1767
|
+
this.parentForm = parentForm;
|
|
1768
|
+
configs.forEach((c) => config.addConfig(c));
|
|
1769
|
+
}
|
|
1770
|
+
buildForm(form, fieldGroup = [], model, options) {
|
|
1771
|
+
this.build({ fieldGroup, model, form, options });
|
|
1772
|
+
}
|
|
1773
|
+
build(field) {
|
|
1774
|
+
if (!this.config.extensions.core) {
|
|
1775
|
+
throw new Error('NgxFormly: missing `forRoot()` call. use `forRoot()` when registering the `FormlyModule`.');
|
|
1850
1776
|
}
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
paths = prop.split('.');
|
|
1777
|
+
if (!field.parent) {
|
|
1778
|
+
this._setOptions(field);
|
|
1854
1779
|
}
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
const
|
|
1861
|
-
if (
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
paths.push(...path.split('.').filter((p) => p));
|
|
1780
|
+
disableTreeValidityCall(field.form, () => {
|
|
1781
|
+
this._build(field);
|
|
1782
|
+
// TODO: add test for https://github.com/ngx-formly/ngx-formly/issues/3910
|
|
1783
|
+
if (!field.parent || field.fieldArray) {
|
|
1784
|
+
// detect changes early to avoid reset value by hidden fields
|
|
1785
|
+
const options = field.options;
|
|
1786
|
+
if (field.parent && isHiddenField(field)) {
|
|
1787
|
+
// when hide is used in expression set defaul value will not be set until detect hide changes
|
|
1788
|
+
// which causes default value not set on new item is added
|
|
1789
|
+
options._hiddenFieldsForCheck?.push({ field, default: false });
|
|
1866
1790
|
}
|
|
1867
|
-
|
|
1791
|
+
options.checkExpressions?.(field, true);
|
|
1792
|
+
options._detectChanges?.(field);
|
|
1793
|
+
}
|
|
1794
|
+
});
|
|
1795
|
+
}
|
|
1796
|
+
_build(field) {
|
|
1797
|
+
if (!field) {
|
|
1798
|
+
return;
|
|
1868
1799
|
}
|
|
1869
|
-
|
|
1870
|
-
|
|
1800
|
+
const extensions = Object.values(this.config.extensions);
|
|
1801
|
+
extensions.forEach((extension) => extension.prePopulate?.(field));
|
|
1802
|
+
extensions.forEach((extension) => extension.onPopulate?.(field));
|
|
1803
|
+
field.fieldGroup?.forEach((f) => this._build(f));
|
|
1804
|
+
extensions.forEach((extension) => extension.postPopulate?.(field));
|
|
1805
|
+
}
|
|
1806
|
+
_setOptions(field) {
|
|
1807
|
+
field.form = field.form || new UntypedFormGroup({});
|
|
1808
|
+
field.model = field.model || {};
|
|
1809
|
+
field.options = field.options || {};
|
|
1810
|
+
const options = field.options;
|
|
1811
|
+
if (!options._viewContainerRef) {
|
|
1812
|
+
defineHiddenProp(options, '_viewContainerRef', this.viewContainerRef);
|
|
1813
|
+
}
|
|
1814
|
+
if (!options._injector) {
|
|
1815
|
+
defineHiddenProp(options, '_injector', this.injector);
|
|
1816
|
+
}
|
|
1817
|
+
if (!options.build) {
|
|
1818
|
+
options._buildForm = () => {
|
|
1819
|
+
console.warn(`Formly: 'options._buildForm' is deprecated since v6.0, use 'options.build' instead.`);
|
|
1820
|
+
this.build(field);
|
|
1821
|
+
};
|
|
1822
|
+
options.build = (f = field) => {
|
|
1823
|
+
this.build(f);
|
|
1824
|
+
return f;
|
|
1825
|
+
};
|
|
1826
|
+
}
|
|
1827
|
+
if (!options.parentForm && this.parentForm) {
|
|
1828
|
+
defineHiddenProp(options, 'parentForm', this.parentForm);
|
|
1829
|
+
if (!isSignalRequired()) {
|
|
1830
|
+
observe(options, ['parentForm', 'submitted'], ({ firstChange }) => {
|
|
1831
|
+
if (!firstChange) {
|
|
1832
|
+
options.detectChanges(field);
|
|
1833
|
+
}
|
|
1834
|
+
});
|
|
1835
|
+
}
|
|
1871
1836
|
}
|
|
1872
|
-
return paths;
|
|
1873
1837
|
}
|
|
1838
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyFormBuilder, deps: [{ token: FormlyConfig }, { token: i0.Injector }, { token: i0.ViewContainerRef, optional: true }, { token: i2.FormGroupDirective, optional: true }, { token: FORMLY_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1839
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyFormBuilder, providedIn: 'root' }); }
|
|
1874
1840
|
}
|
|
1841
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyFormBuilder, decorators: [{
|
|
1842
|
+
type: Injectable,
|
|
1843
|
+
args: [{ providedIn: 'root' }]
|
|
1844
|
+
}], ctorParameters: () => [{ type: FormlyConfig }, { type: i0.Injector }, { type: i0.ViewContainerRef, decorators: [{
|
|
1845
|
+
type: Optional
|
|
1846
|
+
}] }, { type: i2.FormGroupDirective, decorators: [{
|
|
1847
|
+
type: Optional
|
|
1848
|
+
}] }, { type: undefined, decorators: [{
|
|
1849
|
+
type: Optional
|
|
1850
|
+
}, {
|
|
1851
|
+
type: Inject,
|
|
1852
|
+
args: [FORMLY_CONFIG]
|
|
1853
|
+
}] }] });
|
|
1875
1854
|
|
|
1876
|
-
|
|
1877
|
-
|
|
1855
|
+
/**
|
|
1856
|
+
* The `<form-form>` component is the main container of the form,
|
|
1857
|
+
* which takes care of managing the form state
|
|
1858
|
+
* and delegates the rendering of each field to `<formly-field>` component.
|
|
1859
|
+
*/
|
|
1860
|
+
class FormlyForm {
|
|
1861
|
+
/** The form instance which allow to track model value and validation status. */
|
|
1862
|
+
set form(form) {
|
|
1863
|
+
this.field.form = form;
|
|
1864
|
+
}
|
|
1865
|
+
get form() {
|
|
1866
|
+
return this.field.form;
|
|
1867
|
+
}
|
|
1868
|
+
/** The model to be represented by the form. */
|
|
1869
|
+
set model(model) {
|
|
1870
|
+
if (this.config.extras.immutable && this._modelChangeValue === model) {
|
|
1871
|
+
return;
|
|
1872
|
+
}
|
|
1873
|
+
this.setField({ model });
|
|
1874
|
+
}
|
|
1875
|
+
get model() {
|
|
1876
|
+
return this.field.model;
|
|
1877
|
+
}
|
|
1878
|
+
/** The field configurations for building the form. */
|
|
1879
|
+
set fields(fieldGroup) {
|
|
1880
|
+
this.setField({ fieldGroup });
|
|
1881
|
+
}
|
|
1882
|
+
get fields() {
|
|
1883
|
+
return this.field.fieldGroup;
|
|
1884
|
+
}
|
|
1885
|
+
/** Options for the form. */
|
|
1886
|
+
set options(options) {
|
|
1887
|
+
this.setField({ options });
|
|
1888
|
+
}
|
|
1889
|
+
get options() {
|
|
1890
|
+
return this.field.options;
|
|
1891
|
+
}
|
|
1892
|
+
set templates(templates) {
|
|
1893
|
+
this.fieldTemplates.templates = templates;
|
|
1894
|
+
}
|
|
1895
|
+
constructor(builder, config, ngZone, fieldTemplates) {
|
|
1896
|
+
this.builder = builder;
|
|
1878
1897
|
this.config = config;
|
|
1898
|
+
this.ngZone = ngZone;
|
|
1899
|
+
this.fieldTemplates = fieldTemplates;
|
|
1900
|
+
/** Event that is emitted when the model value is changed */
|
|
1901
|
+
this.modelChange = new EventEmitter();
|
|
1902
|
+
this.field = { type: 'formly-group' };
|
|
1903
|
+
this._modelChangeValue = {};
|
|
1904
|
+
this.valueChangesUnsubscribe = () => { };
|
|
1879
1905
|
}
|
|
1880
|
-
|
|
1881
|
-
this.
|
|
1882
|
-
|
|
1906
|
+
ngDoCheck() {
|
|
1907
|
+
if (this.config.extras.checkExpressionOn === 'changeDetectionCheck') {
|
|
1908
|
+
this.checkExpressionChange();
|
|
1909
|
+
}
|
|
1883
1910
|
}
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
validators.push(this.getPredefinedFieldValidation(field));
|
|
1911
|
+
ngOnChanges(changes) {
|
|
1912
|
+
if (changes.fields && this.form) {
|
|
1913
|
+
clearControl(this.form);
|
|
1888
1914
|
}
|
|
1889
|
-
if (
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
: validators.push(this.wrapNgValidatorFn(field, field[type][validatorName], validatorName));
|
|
1894
|
-
}
|
|
1915
|
+
if (changes.fields || changes.form || (changes.model && this._modelChangeValue !== changes.model.currentValue)) {
|
|
1916
|
+
this.valueChangesUnsubscribe();
|
|
1917
|
+
this.builder.build(this.field);
|
|
1918
|
+
this.valueChangesUnsubscribe = this.valueChanges();
|
|
1895
1919
|
}
|
|
1896
|
-
defineHiddenProp(field, '_' + type, validators);
|
|
1897
1920
|
}
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
if (VALIDATORS.length === 0) {
|
|
1914
|
-
return null;
|
|
1915
|
-
}
|
|
1916
|
-
return Validators.compose(VALIDATORS.map((opt) => () => {
|
|
1917
|
-
const value = field.props[opt];
|
|
1918
|
-
switch (opt) {
|
|
1919
|
-
case 'required':
|
|
1920
|
-
return Validators.required(control);
|
|
1921
|
-
case 'pattern':
|
|
1922
|
-
return Validators.pattern(value)(control);
|
|
1923
|
-
case 'minLength':
|
|
1924
|
-
const minLengthResult = Validators.minLength(value)(control);
|
|
1925
|
-
const minLengthKey = this.config.getValidatorMessage('minlength') || field.validation?.messages?.minlength
|
|
1926
|
-
? 'minlength'
|
|
1927
|
-
: 'minLength';
|
|
1928
|
-
return minLengthResult ? { [minLengthKey]: minLengthResult.minlength } : null;
|
|
1929
|
-
case 'maxLength':
|
|
1930
|
-
const maxLengthResult = Validators.maxLength(value)(control);
|
|
1931
|
-
const maxLengthKey = this.config.getValidatorMessage('maxlength') || field.validation?.messages?.maxlength
|
|
1932
|
-
? 'maxlength'
|
|
1933
|
-
: 'maxLength';
|
|
1934
|
-
return maxLengthResult ? { [maxLengthKey]: maxLengthResult.maxlength } : null;
|
|
1935
|
-
case 'min':
|
|
1936
|
-
return Validators.min(value)(control);
|
|
1937
|
-
case 'max':
|
|
1938
|
-
return Validators.max(value)(control);
|
|
1939
|
-
default:
|
|
1940
|
-
return null;
|
|
1921
|
+
ngOnDestroy() {
|
|
1922
|
+
this.valueChangesUnsubscribe();
|
|
1923
|
+
}
|
|
1924
|
+
checkExpressionChange() {
|
|
1925
|
+
this.field.options.checkExpressions?.(this.field);
|
|
1926
|
+
}
|
|
1927
|
+
valueChanges() {
|
|
1928
|
+
this.valueChangesUnsubscribe();
|
|
1929
|
+
let formEvents = null;
|
|
1930
|
+
if (isSignalRequired()) {
|
|
1931
|
+
let submitted = this.options?.parentForm?.submitted;
|
|
1932
|
+
formEvents = this.form.events.subscribe(() => {
|
|
1933
|
+
if (submitted !== this.options?.parentForm?.submitted) {
|
|
1934
|
+
this.options.detectChanges(this.field);
|
|
1935
|
+
submitted = this.options?.parentForm?.submitted;
|
|
1941
1936
|
}
|
|
1942
|
-
})
|
|
1937
|
+
});
|
|
1938
|
+
}
|
|
1939
|
+
const fieldChangesDetection = [
|
|
1940
|
+
observeDeep(this.field.options, ['formState'], () => this.field.options.detectChanges(this.field)),
|
|
1941
|
+
];
|
|
1942
|
+
const valueChanges = this.field.options.fieldChanges
|
|
1943
|
+
.pipe(filter(({ field, type }) => hasKey(field) && type === 'valueChanges'), switchMap(() => (isNoopNgZone(this.ngZone) ? of(null) : this.ngZone.onStable.asObservable().pipe(take(1)))))
|
|
1944
|
+
.subscribe(() => this.ngZone.runGuarded(() => {
|
|
1945
|
+
// runGuarded is used to keep in sync the expression changes
|
|
1946
|
+
// https://github.com/ngx-formly/ngx-formly/issues/2095
|
|
1947
|
+
this.checkExpressionChange();
|
|
1948
|
+
this.modelChange.emit((this._modelChangeValue = clone(this.model)));
|
|
1949
|
+
}));
|
|
1950
|
+
return () => {
|
|
1951
|
+
fieldChangesDetection.forEach((fnc) => fnc());
|
|
1952
|
+
formEvents?.unsubscribe();
|
|
1953
|
+
valueChanges.unsubscribe();
|
|
1943
1954
|
};
|
|
1944
1955
|
}
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
validatorOption = clone(this.config.getValidator(validator));
|
|
1949
|
-
}
|
|
1950
|
-
if (typeof validator === 'object' && validator.name) {
|
|
1951
|
-
validatorOption = clone(this.config.getValidator(validator.name));
|
|
1952
|
-
if (validator.options) {
|
|
1953
|
-
validatorOption.options = validator.options;
|
|
1954
|
-
}
|
|
1955
|
-
}
|
|
1956
|
-
if (typeof validator === 'object' && validator.expression) {
|
|
1957
|
-
const { expression, ...options } = validator;
|
|
1958
|
-
validatorOption = {
|
|
1959
|
-
name: validatorName,
|
|
1960
|
-
validation: expression,
|
|
1961
|
-
options: Object.keys(options).length > 0 ? options : null,
|
|
1962
|
-
};
|
|
1956
|
+
setField(field) {
|
|
1957
|
+
if (this.config.extras.immutable) {
|
|
1958
|
+
this.field = { ...this.field, ...clone(field) };
|
|
1963
1959
|
}
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
name: validatorName,
|
|
1967
|
-
validation: validator,
|
|
1968
|
-
};
|
|
1960
|
+
else {
|
|
1961
|
+
Object.keys(field).forEach((p) => (this.field[p] = field[p]));
|
|
1969
1962
|
}
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1963
|
+
}
|
|
1964
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyForm, deps: [{ token: FormlyFormBuilder }, { token: FormlyConfig }, { token: i0.NgZone }, { token: FormlyFieldTemplates }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1965
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: FormlyForm, isStandalone: true, selector: "formly-form", inputs: { form: "form", model: "model", fields: "fields", options: "options" }, outputs: { modelChange: "modelChange" }, providers: [FormlyFormBuilder, FormlyFieldTemplates], queries: [{ propertyName: "templates", predicate: FormlyTemplate }], usesOnChanges: true, ngImport: i0, template: '<formly-field [field]="field"></formly-field>', isInline: true, dependencies: [{ kind: "component", type: FormlyField, selector: "formly-field", inputs: ["field"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1966
|
+
}
|
|
1967
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyForm, decorators: [{
|
|
1968
|
+
type: Component,
|
|
1969
|
+
args: [{
|
|
1970
|
+
selector: 'formly-form',
|
|
1971
|
+
template: '<formly-field [field]="field"></formly-field>',
|
|
1972
|
+
providers: [FormlyFormBuilder, FormlyFieldTemplates],
|
|
1973
|
+
imports: [FormlyField],
|
|
1974
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1975
|
+
standalone: true,
|
|
1976
|
+
}]
|
|
1977
|
+
}], ctorParameters: () => [{ type: FormlyFormBuilder }, { type: FormlyConfig }, { type: i0.NgZone }, { type: FormlyFieldTemplates }], propDecorators: { form: [{
|
|
1978
|
+
type: Input
|
|
1979
|
+
}], model: [{
|
|
1980
|
+
type: Input
|
|
1981
|
+
}], fields: [{
|
|
1982
|
+
type: Input
|
|
1983
|
+
}], options: [{
|
|
1984
|
+
type: Input
|
|
1985
|
+
}], modelChange: [{
|
|
1986
|
+
type: Output
|
|
1987
|
+
}], templates: [{
|
|
1988
|
+
type: ContentChildren,
|
|
1989
|
+
args: [FormlyTemplate]
|
|
1990
|
+
}] } });
|
|
1991
|
+
class LegacyFormlyForm extends FormlyForm {
|
|
1992
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LegacyFormlyForm, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
1993
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: LegacyFormlyForm, selector: "formly-form", providers: [FormlyFormBuilder, FormlyFieldTemplates], usesInheritance: true, ngImport: i0, template: '<formly-field [field]="field"></formly-field>', isInline: true, dependencies: [{ kind: "component", type: LegacyFormlyField, selector: "formly-field" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1994
|
+
}
|
|
1995
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LegacyFormlyForm, decorators: [{
|
|
1996
|
+
type: Component,
|
|
1997
|
+
args: [{
|
|
1998
|
+
selector: 'formly-form',
|
|
1999
|
+
template: '<formly-field [field]="field"></formly-field>',
|
|
2000
|
+
providers: [FormlyFormBuilder, FormlyFieldTemplates],
|
|
2001
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2002
|
+
standalone: false,
|
|
2003
|
+
}]
|
|
2004
|
+
}] });
|
|
2005
|
+
|
|
2006
|
+
/**
|
|
2007
|
+
* Allow to link the `field` HTML attributes (`id`, `name` ...) and Event attributes (`focus`, `blur` ...) to an element in the DOM.
|
|
2008
|
+
*/
|
|
2009
|
+
class FormlyAttributes {
|
|
2010
|
+
get props() {
|
|
2011
|
+
return this.field.props || {};
|
|
2012
|
+
}
|
|
2013
|
+
get fieldAttrElements() {
|
|
2014
|
+
return this.field?.['_elementRefs'] || [];
|
|
2015
|
+
}
|
|
2016
|
+
constructor(renderer, elementRef, _document) {
|
|
2017
|
+
this.renderer = renderer;
|
|
2018
|
+
this.elementRef = elementRef;
|
|
2019
|
+
this.uiAttributesCache = {};
|
|
2020
|
+
/**
|
|
2021
|
+
* HostBinding doesn't register listeners conditionally which may produce some perf issues.
|
|
2022
|
+
*
|
|
2023
|
+
* Formly issue: https://github.com/ngx-formly/ngx-formly/issues/1991
|
|
2024
|
+
*/
|
|
2025
|
+
this.uiEvents = {
|
|
2026
|
+
listeners: [],
|
|
2027
|
+
events: ['click', 'keyup', 'keydown', 'keypress', 'focus', 'blur', 'change', 'wheel'],
|
|
2028
|
+
callback: (eventName, $event) => {
|
|
2029
|
+
switch (eventName) {
|
|
2030
|
+
case 'focus':
|
|
2031
|
+
return this.onFocus($event);
|
|
2032
|
+
case 'blur':
|
|
2033
|
+
return this.onBlur($event);
|
|
2034
|
+
case 'change':
|
|
2035
|
+
return this.onChange($event);
|
|
2036
|
+
default:
|
|
2037
|
+
return this.props[eventName](this.field, $event);
|
|
2038
|
+
}
|
|
2039
|
+
},
|
|
2040
|
+
};
|
|
2041
|
+
this.document = _document;
|
|
2042
|
+
}
|
|
2043
|
+
ngOnChanges(changes) {
|
|
2044
|
+
if (changes.field) {
|
|
2045
|
+
this.field.name && this.setAttribute('name', this.field.name);
|
|
2046
|
+
this.uiEvents.listeners.forEach((listener) => listener());
|
|
2047
|
+
this.uiEvents.events.forEach((eventName) => {
|
|
2048
|
+
if (this.props?.[eventName] || ['focus', 'blur', 'change'].indexOf(eventName) !== -1) {
|
|
2049
|
+
this.uiEvents.listeners.push(this.renderer.listen(this.elementRef.nativeElement, eventName, (e) => this.uiEvents.callback(eventName, e)));
|
|
2050
|
+
}
|
|
2051
|
+
});
|
|
2052
|
+
if (this.props?.attributes) {
|
|
2053
|
+
observe(this.field, ['props', 'attributes'], ({ currentValue, previousValue }) => {
|
|
2054
|
+
if (previousValue) {
|
|
2055
|
+
Object.keys(previousValue).forEach((attr) => this.removeAttribute(attr));
|
|
2056
|
+
}
|
|
2057
|
+
if (currentValue) {
|
|
2058
|
+
Object.keys(currentValue).forEach((attr) => {
|
|
2059
|
+
if (currentValue[attr] != null) {
|
|
2060
|
+
this.setAttribute(attr, currentValue[attr]);
|
|
2061
|
+
}
|
|
2062
|
+
});
|
|
2063
|
+
}
|
|
2064
|
+
});
|
|
1974
2065
|
}
|
|
1975
|
-
|
|
1976
|
-
|
|
2066
|
+
this.detachElementRef(changes.field.previousValue);
|
|
2067
|
+
this.attachElementRef(changes.field.currentValue);
|
|
2068
|
+
if (this.fieldAttrElements.length === 1) {
|
|
2069
|
+
!this.id && this.field.id && this.setAttribute('id', this.field.id);
|
|
2070
|
+
this.focusObserver = observe(this.field, ['focus'], ({ currentValue }) => {
|
|
2071
|
+
this.toggleFocus(currentValue);
|
|
2072
|
+
});
|
|
1977
2073
|
}
|
|
1978
|
-
return this.handleResult(field, validatorName ? !!errors : errors, validatorOption);
|
|
1979
|
-
};
|
|
1980
|
-
}
|
|
1981
|
-
handleResult(field, errors, { name, options }) {
|
|
1982
|
-
if (typeof errors === 'boolean') {
|
|
1983
|
-
errors = errors ? null : { [name]: options ? options : true };
|
|
1984
2074
|
}
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
if (isObject(errors)) {
|
|
1988
|
-
Object.keys(errors).forEach((name) => {
|
|
1989
|
-
const errorPath = errors[name].errorPath ? errors[name].errorPath : options?.errorPath;
|
|
1990
|
-
const childCtrl = errorPath ? field.formControl.get(errorPath) : null;
|
|
1991
|
-
if (childCtrl) {
|
|
1992
|
-
const { errorPath: _errorPath, ...opts } = errors[name];
|
|
1993
|
-
childCtrl.setErrors({ ...(childCtrl.errors || {}), [name]: opts });
|
|
1994
|
-
!ctrl._childrenErrors && defineHiddenProp(ctrl, '_childrenErrors', {});
|
|
1995
|
-
ctrl._childrenErrors[name] = () => {
|
|
1996
|
-
const { [name]: _toDelete, ...childErrors } = childCtrl.errors || {};
|
|
1997
|
-
childCtrl.setErrors(Object.keys(childErrors).length === 0 ? null : childErrors);
|
|
1998
|
-
};
|
|
1999
|
-
}
|
|
2000
|
-
});
|
|
2075
|
+
if (changes.id) {
|
|
2076
|
+
this.setAttribute('id', this.id);
|
|
2001
2077
|
}
|
|
2002
|
-
return errors;
|
|
2003
2078
|
}
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2079
|
+
/**
|
|
2080
|
+
* We need to re-evaluate all the attributes on every change detection cycle, because
|
|
2081
|
+
* by using a HostBinding we run into certain edge cases. This means that whatever logic
|
|
2082
|
+
* is in here has to be super lean or we risk seriously damaging or destroying the performance.
|
|
2083
|
+
*
|
|
2084
|
+
* Formly issue: https://github.com/ngx-formly/ngx-formly/issues/1317
|
|
2085
|
+
* Material issue: https://github.com/angular/components/issues/14024
|
|
2086
|
+
*/
|
|
2087
|
+
ngDoCheck() {
|
|
2088
|
+
if (!this.uiAttributes) {
|
|
2089
|
+
const element = this.elementRef.nativeElement;
|
|
2090
|
+
this.uiAttributes = [...FORMLY_VALIDATORS, 'tabindex', 'placeholder', 'readonly', 'disabled', 'step'].filter((attr) => !element.hasAttribute || !element.hasAttribute(attr));
|
|
2010
2091
|
}
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2092
|
+
for (let i = 0; i < this.uiAttributes.length; i++) {
|
|
2093
|
+
const attr = this.uiAttributes[i];
|
|
2094
|
+
const value = this.props[attr];
|
|
2095
|
+
if (this.uiAttributesCache[attr] !== value &&
|
|
2096
|
+
(!this.props.attributes || !this.props.attributes.hasOwnProperty(attr.toLowerCase()))) {
|
|
2097
|
+
this.uiAttributesCache[attr] = value;
|
|
2098
|
+
if (value || value === 0) {
|
|
2099
|
+
this.setAttribute(attr, value === true ? attr : `${value}`);
|
|
2100
|
+
}
|
|
2101
|
+
else {
|
|
2102
|
+
this.removeAttribute(attr);
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2016
2105
|
}
|
|
2017
2106
|
}
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2107
|
+
ngOnDestroy() {
|
|
2108
|
+
this.uiEvents.listeners.forEach((listener) => listener());
|
|
2109
|
+
this.detachElementRef(this.field);
|
|
2110
|
+
this.focusObserver?.unsubscribe();
|
|
2111
|
+
}
|
|
2112
|
+
toggleFocus(value) {
|
|
2113
|
+
const element = this.fieldAttrElements ? this.fieldAttrElements[0] : null;
|
|
2114
|
+
if (!element || !element.nativeElement.focus) {
|
|
2115
|
+
return;
|
|
2021
2116
|
}
|
|
2022
|
-
|
|
2023
|
-
this.
|
|
2117
|
+
const isFocused = !!this.document.activeElement &&
|
|
2118
|
+
this.fieldAttrElements.some(({ nativeElement }) => this.document.activeElement === nativeElement || nativeElement.contains(this.document.activeElement));
|
|
2119
|
+
if (value && !isFocused) {
|
|
2120
|
+
Promise.resolve().then(() => element.nativeElement.focus());
|
|
2121
|
+
}
|
|
2122
|
+
else if (!value && isFocused) {
|
|
2123
|
+
Promise.resolve().then(() => element.nativeElement.blur());
|
|
2024
2124
|
}
|
|
2025
2125
|
}
|
|
2026
|
-
|
|
2027
|
-
|
|
2126
|
+
onFocus($event) {
|
|
2127
|
+
this.focusObserver?.setValue(true);
|
|
2128
|
+
this.props.focus?.(this.field, $event);
|
|
2129
|
+
}
|
|
2130
|
+
onBlur($event) {
|
|
2131
|
+
this.focusObserver?.setValue(false);
|
|
2132
|
+
this.props.blur?.(this.field, $event);
|
|
2133
|
+
}
|
|
2134
|
+
// handle custom `change` event, for regular ones rely on DOM listener
|
|
2135
|
+
onHostChange($event) {
|
|
2136
|
+
if ($event instanceof Event) {
|
|
2028
2137
|
return;
|
|
2029
2138
|
}
|
|
2030
|
-
this.
|
|
2031
|
-
const markForCheck = this.setValidators(field);
|
|
2032
|
-
if (markForCheck && field.parent) {
|
|
2033
|
-
let parent = field.parent;
|
|
2034
|
-
while (parent) {
|
|
2035
|
-
if (hasKey(parent) || !parent.parent) {
|
|
2036
|
-
updateValidity(parent.formControl, true);
|
|
2037
|
-
}
|
|
2038
|
-
parent = parent.parent;
|
|
2039
|
-
}
|
|
2040
|
-
}
|
|
2139
|
+
this.onChange($event);
|
|
2041
2140
|
}
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2141
|
+
onChange($event) {
|
|
2142
|
+
this.props.change?.(this.field, $event);
|
|
2143
|
+
this.field.formControl?.markAsDirty();
|
|
2144
|
+
}
|
|
2145
|
+
attachElementRef(f) {
|
|
2146
|
+
if (!f) {
|
|
2045
2147
|
return;
|
|
2046
2148
|
}
|
|
2047
|
-
if (
|
|
2048
|
-
|
|
2049
|
-
if (field.fieldGroup) {
|
|
2050
|
-
control = new FormGroup({}, controlOptions);
|
|
2051
|
-
}
|
|
2052
|
-
else {
|
|
2053
|
-
const value = hasKey(field) ? getFieldValue(field) : field.defaultValue;
|
|
2054
|
-
control = new FormControl({ value, disabled: !!field.props.disabled }, { ...controlOptions, initialValueIsDefault: true });
|
|
2055
|
-
}
|
|
2149
|
+
if (f['_elementRefs']?.indexOf(this.elementRef) === -1) {
|
|
2150
|
+
f['_elementRefs'].push(this.elementRef);
|
|
2056
2151
|
}
|
|
2057
2152
|
else {
|
|
2058
|
-
|
|
2059
|
-
const value = hasKey(field) ? getFieldValue(field) : field.defaultValue;
|
|
2060
|
-
control.defaultValue = value;
|
|
2061
|
-
}
|
|
2153
|
+
defineHiddenProp(f, '_elementRefs', [this.elementRef]);
|
|
2062
2154
|
}
|
|
2063
|
-
registerControl(field, control);
|
|
2064
2155
|
}
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
let markForCheck = false;
|
|
2070
|
-
field.fieldGroup?.forEach((f) => f && this.setValidators(f, disabled) && (markForCheck = true));
|
|
2071
|
-
if (hasKey(field) || !field.parent || (!hasKey(field) && !field.fieldGroup)) {
|
|
2072
|
-
const { formControl: c } = field;
|
|
2073
|
-
if (c) {
|
|
2074
|
-
if (hasKey(field) && c instanceof FormControl) {
|
|
2075
|
-
if (disabled && c.enabled) {
|
|
2076
|
-
c.disable({ emitEvent: false, onlySelf: true });
|
|
2077
|
-
markForCheck = true;
|
|
2078
|
-
}
|
|
2079
|
-
if (!disabled && c.disabled) {
|
|
2080
|
-
c.enable({ emitEvent: false, onlySelf: true });
|
|
2081
|
-
markForCheck = true;
|
|
2082
|
-
}
|
|
2083
|
-
}
|
|
2084
|
-
if (null === c.validator && this.hasValidators(field, '_validators')) {
|
|
2085
|
-
c.setValidators(() => {
|
|
2086
|
-
const v = Validators.compose(this.mergeValidators(field, '_validators'));
|
|
2087
|
-
return v ? v(c) : null;
|
|
2088
|
-
});
|
|
2089
|
-
markForCheck = true;
|
|
2090
|
-
}
|
|
2091
|
-
if (null === c.asyncValidator && this.hasValidators(field, '_asyncValidators')) {
|
|
2092
|
-
c.setAsyncValidators(() => {
|
|
2093
|
-
const v = Validators.composeAsync(this.mergeValidators(field, '_asyncValidators'));
|
|
2094
|
-
return v ? v(c) : of(null);
|
|
2095
|
-
});
|
|
2096
|
-
markForCheck = true;
|
|
2097
|
-
}
|
|
2098
|
-
if (markForCheck) {
|
|
2099
|
-
updateValidity(c, true);
|
|
2100
|
-
// update validity of `FormGroup` instance created by field with nested key.
|
|
2101
|
-
let parent = c.parent;
|
|
2102
|
-
for (let i = 1; i < getKeyPath(field).length; i++) {
|
|
2103
|
-
if (parent) {
|
|
2104
|
-
updateValidity(parent, true);
|
|
2105
|
-
parent = parent.parent;
|
|
2106
|
-
}
|
|
2107
|
-
}
|
|
2108
|
-
}
|
|
2109
|
-
}
|
|
2156
|
+
detachElementRef(f) {
|
|
2157
|
+
const index = f?.['_elementRefs'] ? this.fieldAttrElements.indexOf(this.elementRef) : -1;
|
|
2158
|
+
if (index !== -1) {
|
|
2159
|
+
f['_elementRefs'].splice(index, 1);
|
|
2110
2160
|
}
|
|
2111
|
-
return markForCheck;
|
|
2112
2161
|
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
if (c?._fields?.length > 1 && c._fields.some((f) => f[type].length > 0)) {
|
|
2116
|
-
return true;
|
|
2117
|
-
}
|
|
2118
|
-
else if (field[type].length > 0) {
|
|
2119
|
-
return true;
|
|
2120
|
-
}
|
|
2121
|
-
return field.fieldGroup?.some((f) => f?.fieldGroup && !hasKey(f) && this.hasValidators(f, type));
|
|
2162
|
+
setAttribute(attr, value) {
|
|
2163
|
+
this.renderer.setAttribute(this.elementRef.nativeElement, attr, value);
|
|
2122
2164
|
}
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2165
|
+
removeAttribute(attr) {
|
|
2166
|
+
this.renderer.removeAttribute(this.elementRef.nativeElement, attr);
|
|
2167
|
+
}
|
|
2168
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyAttributes, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2169
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: FormlyAttributes, selector: "[formlyAttributes]", inputs: { field: ["formlyAttributes", "field"], id: "id" }, host: { listeners: { "change": "onHostChange($event)" } }, usesOnChanges: true, ngImport: i0 }); }
|
|
2170
|
+
}
|
|
2171
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyAttributes, decorators: [{
|
|
2172
|
+
type: Directive,
|
|
2173
|
+
args: [{
|
|
2174
|
+
selector: '[formlyAttributes]',
|
|
2175
|
+
host: {
|
|
2176
|
+
'(change)': 'onHostChange($event)',
|
|
2177
|
+
},
|
|
2178
|
+
}]
|
|
2179
|
+
}], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: undefined, decorators: [{
|
|
2180
|
+
type: Inject,
|
|
2181
|
+
args: [DOCUMENT]
|
|
2182
|
+
}] }], propDecorators: { field: [{
|
|
2183
|
+
type: Input,
|
|
2184
|
+
args: ['formlyAttributes']
|
|
2185
|
+
}], id: [{
|
|
2186
|
+
type: Input
|
|
2187
|
+
}] } });
|
|
2188
|
+
|
|
2189
|
+
/**
|
|
2190
|
+
* The `<formly-validation-message>` component renders the error message of a given `field`.
|
|
2191
|
+
*/
|
|
2192
|
+
class FormlyValidationMessage {
|
|
2193
|
+
constructor(config) {
|
|
2194
|
+
this.config = config;
|
|
2195
|
+
}
|
|
2196
|
+
ngOnChanges() {
|
|
2197
|
+
const EXPR_VALIDATORS = FORMLY_VALIDATORS.map((v) => `templateOptions.${v}`);
|
|
2198
|
+
this.errorMessage$ = merge(this.field.formControl.statusChanges, !this.field.options
|
|
2199
|
+
? of(null)
|
|
2200
|
+
: this.field.options.fieldChanges.pipe(filter(({ field, type, property }) => {
|
|
2201
|
+
return (field === this.field &&
|
|
2202
|
+
type === 'expressionChanges' &&
|
|
2203
|
+
(property.indexOf('validation') !== -1 || EXPR_VALIDATORS.indexOf(property) !== -1));
|
|
2204
|
+
}))).pipe(startWith(null), switchMap(() => (isObservable(this.errorMessage) ? this.errorMessage : of(this.errorMessage))));
|
|
2205
|
+
}
|
|
2206
|
+
get errorMessage() {
|
|
2207
|
+
const fieldForm = this.field.formControl;
|
|
2208
|
+
for (const error in fieldForm.errors) {
|
|
2209
|
+
if (fieldForm.errors.hasOwnProperty(error)) {
|
|
2210
|
+
let message = this.config.getValidatorMessage(error);
|
|
2211
|
+
if (isObject(fieldForm.errors[error])) {
|
|
2212
|
+
if (fieldForm.errors[error].errorPath) {
|
|
2213
|
+
return undefined;
|
|
2214
|
+
}
|
|
2215
|
+
if (fieldForm.errors[error].message) {
|
|
2216
|
+
message = fieldForm.errors[error].message;
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
if (this.field.validation?.messages?.[error]) {
|
|
2220
|
+
message = this.field.validation.messages[error];
|
|
2221
|
+
}
|
|
2222
|
+
if (this.field.validators?.[error]?.message) {
|
|
2223
|
+
message = this.field.validators[error].message;
|
|
2224
|
+
}
|
|
2225
|
+
if (this.field.asyncValidators?.[error]?.message) {
|
|
2226
|
+
message = this.field.asyncValidators[error].message;
|
|
2227
|
+
}
|
|
2228
|
+
if (typeof message === 'function') {
|
|
2229
|
+
return message(fieldForm.errors[error], this.field);
|
|
2230
|
+
}
|
|
2231
|
+
return message;
|
|
2232
|
+
}
|
|
2138
2233
|
}
|
|
2139
|
-
return
|
|
2234
|
+
return undefined;
|
|
2140
2235
|
}
|
|
2236
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyValidationMessage, deps: [{ token: FormlyConfig }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2237
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: FormlyValidationMessage, selector: "formly-validation-message", inputs: { field: "field" }, usesOnChanges: true, ngImport: i0, template: '{{ errorMessage$ | async }}', isInline: true, dependencies: [{ kind: "pipe", type: i1$1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2141
2238
|
}
|
|
2239
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyValidationMessage, decorators: [{
|
|
2240
|
+
type: Component,
|
|
2241
|
+
args: [{
|
|
2242
|
+
selector: 'formly-validation-message',
|
|
2243
|
+
template: '{{ errorMessage$ | async }}',
|
|
2244
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2245
|
+
}]
|
|
2246
|
+
}], ctorParameters: () => [{ type: FormlyConfig }], propDecorators: { field: [{
|
|
2247
|
+
type: Input
|
|
2248
|
+
}] } });
|
|
2142
2249
|
|
|
2143
|
-
class
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2250
|
+
class FieldArrayType extends FieldType {
|
|
2251
|
+
onPopulate(field) {
|
|
2252
|
+
if (hasKey(field)) {
|
|
2253
|
+
const control = findControl(field);
|
|
2254
|
+
registerControl(field, control ? control : new UntypedFormArray([], { updateOn: field.modelOptions.updateOn }));
|
|
2255
|
+
}
|
|
2256
|
+
field.fieldGroup = field.fieldGroup || [];
|
|
2257
|
+
const length = Array.isArray(field.model) ? field.model.length : 0;
|
|
2258
|
+
if (field.fieldGroup.length > length) {
|
|
2259
|
+
for (let i = field.fieldGroup.length - 1; i >= length; --i) {
|
|
2260
|
+
unregisterControl(field.fieldGroup[i], true);
|
|
2261
|
+
field.fieldGroup.splice(i, 1);
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
for (let i = field.fieldGroup.length; i < length; i++) {
|
|
2265
|
+
const f = { ...clone(typeof field.fieldArray === 'function' ? field.fieldArray(field) : field.fieldArray) };
|
|
2266
|
+
if (f.key !== null) {
|
|
2267
|
+
f.key = `${i}`;
|
|
2268
|
+
}
|
|
2269
|
+
field.fieldGroup.push(f);
|
|
2158
2270
|
}
|
|
2159
|
-
Object.defineProperty(field, 'get', {
|
|
2160
|
-
value: (key) => getField(field, key),
|
|
2161
|
-
configurable: true,
|
|
2162
|
-
});
|
|
2163
|
-
this.getFieldComponentInstance(field).prePopulate?.(field);
|
|
2164
2271
|
}
|
|
2165
|
-
|
|
2166
|
-
this.
|
|
2167
|
-
this.
|
|
2168
|
-
if (
|
|
2169
|
-
field
|
|
2170
|
-
if (f) {
|
|
2171
|
-
Object.defineProperty(f, 'parent', { get: () => field, configurable: true });
|
|
2172
|
-
Object.defineProperty(f, 'index', { get: () => index, configurable: true });
|
|
2173
|
-
}
|
|
2174
|
-
this.formId++;
|
|
2175
|
-
});
|
|
2272
|
+
add(i, initialModel, { markAsDirty } = { markAsDirty: true }) {
|
|
2273
|
+
markAsDirty && this.formControl.markAsDirty();
|
|
2274
|
+
i = i == null ? this.field.fieldGroup.length : i;
|
|
2275
|
+
if (!this.model) {
|
|
2276
|
+
assignFieldValue(this.field, []);
|
|
2176
2277
|
}
|
|
2278
|
+
this.model.splice(i, 0, initialModel ? clone(initialModel) : undefined);
|
|
2279
|
+
this.markFieldForCheck(this.field.fieldGroup[i]);
|
|
2280
|
+
this._build();
|
|
2177
2281
|
}
|
|
2178
|
-
|
|
2179
|
-
this.
|
|
2282
|
+
remove(i, { markAsDirty } = { markAsDirty: true }) {
|
|
2283
|
+
markAsDirty && this.formControl.markAsDirty();
|
|
2284
|
+
this.model.splice(i, 1);
|
|
2285
|
+
const field = this.field.fieldGroup[i];
|
|
2286
|
+
this.field.fieldGroup.splice(i, 1);
|
|
2287
|
+
this.field.fieldGroup.forEach((f, key) => this.updateArrayElementKey(f, `${key}`));
|
|
2288
|
+
unregisterControl(field, true);
|
|
2289
|
+
this._build();
|
|
2180
2290
|
}
|
|
2181
|
-
|
|
2182
|
-
field.
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2291
|
+
_build() {
|
|
2292
|
+
const fields = this.field.formControl._fields ?? [this.field];
|
|
2293
|
+
fields.forEach((f) => this.options.build(f));
|
|
2294
|
+
this.options.fieldChanges.next({
|
|
2295
|
+
field: this.field,
|
|
2296
|
+
value: getFieldValue(this.field),
|
|
2297
|
+
type: 'valueChanges',
|
|
2187
2298
|
});
|
|
2188
2299
|
}
|
|
2189
|
-
|
|
2190
|
-
if (
|
|
2300
|
+
updateArrayElementKey(f, newKey) {
|
|
2301
|
+
if (hasKey(f)) {
|
|
2302
|
+
f.key = newKey;
|
|
2191
2303
|
return;
|
|
2192
2304
|
}
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
if (!options.showError) {
|
|
2196
|
-
options.showError = this.config.extras.showError;
|
|
2197
|
-
}
|
|
2198
|
-
if (!options.fieldChanges) {
|
|
2199
|
-
defineHiddenProp(options, 'fieldChanges', new Subject());
|
|
2305
|
+
if (!f.fieldGroup?.length) {
|
|
2306
|
+
return;
|
|
2200
2307
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2308
|
+
for (let i = 0; i < f.fieldGroup.length; i++) {
|
|
2309
|
+
this.updateArrayElementKey(f.fieldGroup[i], newKey);
|
|
2203
2310
|
}
|
|
2204
|
-
options._markForCheck = (f) => {
|
|
2205
|
-
console.warn(`Formly: 'options._markForCheck' is deprecated since v6.0, use 'options.detectChanges' instead.`);
|
|
2206
|
-
options.detectChanges(f);
|
|
2207
|
-
};
|
|
2208
|
-
options._detectChanges = (f) => {
|
|
2209
|
-
if (f._componentRefs) {
|
|
2210
|
-
markFieldForCheck(f);
|
|
2211
|
-
}
|
|
2212
|
-
f.fieldGroup?.forEach((f) => f && options._detectChanges(f));
|
|
2213
|
-
};
|
|
2214
|
-
options.detectChanges = (f) => {
|
|
2215
|
-
f.options.checkExpressions?.(f);
|
|
2216
|
-
options._detectChanges(f);
|
|
2217
|
-
};
|
|
2218
|
-
options.resetModel = (model) => {
|
|
2219
|
-
model = clone(model ?? options._initialModel);
|
|
2220
|
-
if (field.model) {
|
|
2221
|
-
Object.keys(field.model).forEach((k) => delete field.model[k]);
|
|
2222
|
-
Object.assign(field.model, model || {});
|
|
2223
|
-
}
|
|
2224
|
-
if (!isSignalRequired()) {
|
|
2225
|
-
observe(options, ['parentForm', 'submitted']).setValue(false, false);
|
|
2226
|
-
}
|
|
2227
|
-
options.build(field);
|
|
2228
|
-
field.form.reset(field.model);
|
|
2229
|
-
};
|
|
2230
|
-
options.updateInitialValue = (model) => (options._initialModel = clone(model ?? field.model));
|
|
2231
|
-
field.options.updateInitialValue();
|
|
2232
2311
|
}
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
hooks: {},
|
|
2237
|
-
modelOptions: {},
|
|
2238
|
-
validation: { messages: {} },
|
|
2239
|
-
props: !field.type || !hasKey(field)
|
|
2240
|
-
? {}
|
|
2241
|
-
: {
|
|
2242
|
-
label: '',
|
|
2243
|
-
placeholder: '',
|
|
2244
|
-
disabled: false,
|
|
2245
|
-
},
|
|
2246
|
-
});
|
|
2247
|
-
if (this.config.extras.resetFieldOnHide && field.resetOnHide !== false) {
|
|
2248
|
-
field.resetOnHide = true;
|
|
2249
|
-
}
|
|
2250
|
-
if (field.type !== 'formly-template' &&
|
|
2251
|
-
(field.template || field.expressions?.template || field.expressionProperties?.template)) {
|
|
2252
|
-
field.type = 'formly-template';
|
|
2253
|
-
}
|
|
2254
|
-
if (!field.type && field.fieldGroup) {
|
|
2255
|
-
field.type = 'formly-group';
|
|
2256
|
-
}
|
|
2257
|
-
if (field.type) {
|
|
2258
|
-
this.config.getMergedField(field);
|
|
2259
|
-
}
|
|
2260
|
-
if (hasKey(field) &&
|
|
2261
|
-
!isUndefined(field.defaultValue) &&
|
|
2262
|
-
isUndefined(getFieldValue(field)) &&
|
|
2263
|
-
!isHiddenField(field)) {
|
|
2264
|
-
assignFieldValue(field, field.defaultValue);
|
|
2312
|
+
markFieldForCheck(f) {
|
|
2313
|
+
if (!f) {
|
|
2314
|
+
return;
|
|
2265
2315
|
}
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
const componentRefInstance = () => {
|
|
2270
|
-
let componentRef = this.config.resolveFieldTypeRef(field);
|
|
2271
|
-
const fieldComponentRef = field._componentRefs?.slice(-1)[0];
|
|
2272
|
-
if (fieldComponentRef instanceof ComponentRef &&
|
|
2273
|
-
fieldComponentRef?.componentType === componentRef?.componentType) {
|
|
2274
|
-
componentRef = fieldComponentRef;
|
|
2275
|
-
}
|
|
2276
|
-
return componentRef?.instance;
|
|
2277
|
-
};
|
|
2278
|
-
if (!field._proxyInstance) {
|
|
2279
|
-
defineHiddenProp(field, '_proxyInstance', new Proxy({}, {
|
|
2280
|
-
get: (_, prop) => componentRefInstance()?.[prop],
|
|
2281
|
-
set: (_, prop, value) => (componentRefInstance()[prop] = value),
|
|
2282
|
-
}));
|
|
2316
|
+
f.fieldGroup?.forEach((c) => this.markFieldForCheck(c));
|
|
2317
|
+
if (f.hide === false) {
|
|
2318
|
+
this.options._hiddenFieldsForCheck.push({ field: f });
|
|
2283
2319
|
}
|
|
2284
|
-
return field._proxyInstance;
|
|
2285
2320
|
}
|
|
2321
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FieldArrayType, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2322
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: FieldArrayType, usesInheritance: true, ngImport: i0 }); }
|
|
2286
2323
|
}
|
|
2324
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FieldArrayType, decorators: [{
|
|
2325
|
+
type: Directive
|
|
2326
|
+
}] });
|
|
2287
2327
|
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
{ name: 'core', extension: new CoreExtension(config), priority: -250 },
|
|
2296
|
-
{ name: 'field-validation', extension: new FieldValidationExtension(config), priority: -200 },
|
|
2297
|
-
{ name: 'field-form', extension: new FieldFormExtension(), priority: -150 },
|
|
2298
|
-
{ name: 'field-expression', extension: new FieldExpressionExtension(), priority: -100 },
|
|
2299
|
-
],
|
|
2300
|
-
};
|
|
2328
|
+
class FieldWrapper extends FieldType {
|
|
2329
|
+
set _formlyControls(_) { }
|
|
2330
|
+
set _staticContent(content) {
|
|
2331
|
+
this.fieldComponent = content;
|
|
2332
|
+
}
|
|
2333
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FieldWrapper, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2334
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: FieldWrapper, viewQueries: [{ propertyName: "fieldComponent", first: true, predicate: ["fieldComponent"], descendants: true, read: ViewContainerRef }, { propertyName: "_staticContent", first: true, predicate: ["fieldComponent"], descendants: true, read: ViewContainerRef, static: true }], usesInheritance: true, ngImport: i0 }); }
|
|
2301
2335
|
}
|
|
2336
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FieldWrapper, decorators: [{
|
|
2337
|
+
type: Directive
|
|
2338
|
+
}], propDecorators: { fieldComponent: [{
|
|
2339
|
+
type: ViewChild,
|
|
2340
|
+
args: ['fieldComponent', { read: ViewContainerRef }]
|
|
2341
|
+
}], _staticContent: [{
|
|
2342
|
+
type: ViewChild,
|
|
2343
|
+
args: ['fieldComponent', { read: ViewContainerRef, static: true }]
|
|
2344
|
+
}] } });
|
|
2345
|
+
|
|
2302
2346
|
class FormlyModule {
|
|
2303
|
-
constructor(configService, configs = []) {
|
|
2304
|
-
if (!configs) {
|
|
2305
|
-
return;
|
|
2306
|
-
}
|
|
2307
|
-
configs.forEach((config) => configService.addConfig(config));
|
|
2308
|
-
}
|
|
2309
2347
|
static forRoot(config = {}) {
|
|
2310
2348
|
return {
|
|
2311
2349
|
ngModule: FormlyModule,
|
|
2312
2350
|
providers: [
|
|
2313
|
-
{ provide: FORMLY_CONFIG, multi: true, useFactory:
|
|
2351
|
+
{ provide: FORMLY_CONFIG, multi: true, useFactory: withDefaultConfig, deps: [FormlyConfig] },
|
|
2314
2352
|
{ provide: FORMLY_CONFIG, useValue: config, multi: true },
|
|
2315
2353
|
FormlyConfig,
|
|
2316
2354
|
FormlyFormBuilder,
|
|
@@ -2321,43 +2359,50 @@ class FormlyModule {
|
|
|
2321
2359
|
return {
|
|
2322
2360
|
ngModule: FormlyModule,
|
|
2323
2361
|
providers: [
|
|
2324
|
-
{ provide: FORMLY_CONFIG, multi: true, useFactory:
|
|
2362
|
+
{ provide: FORMLY_CONFIG, multi: true, useFactory: withDefaultConfig, deps: [FormlyConfig] },
|
|
2325
2363
|
{ provide: FORMLY_CONFIG, useValue: config, multi: true },
|
|
2326
2364
|
FormlyFormBuilder,
|
|
2327
2365
|
],
|
|
2328
2366
|
};
|
|
2329
2367
|
}
|
|
2368
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
2369
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: FormlyModule, declarations: [FormlyTemplate,
|
|
2370
|
+
LegacyFormlyForm,
|
|
2371
|
+
LegacyFormlyField,
|
|
2372
|
+
FormlyAttributes,
|
|
2373
|
+
FormlyGroup,
|
|
2374
|
+
FormlyValidationMessage,
|
|
2375
|
+
FormlyTemplateType], imports: [CommonModule], exports: [FormlyTemplate,
|
|
2376
|
+
LegacyFormlyForm,
|
|
2377
|
+
LegacyFormlyField,
|
|
2378
|
+
FormlyAttributes,
|
|
2379
|
+
FormlyGroup,
|
|
2380
|
+
FormlyValidationMessage] }); }
|
|
2381
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyModule, imports: [CommonModule] }); }
|
|
2330
2382
|
}
|
|
2331
|
-
|
|
2332
|
-
FormlyModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyModule, declarations: [FormlyTemplate,
|
|
2333
|
-
FormlyForm,
|
|
2334
|
-
FormlyField,
|
|
2335
|
-
FormlyAttributes,
|
|
2336
|
-
FormlyGroup,
|
|
2337
|
-
FormlyValidationMessage,
|
|
2338
|
-
FormlyTemplateType], imports: [CommonModule], exports: [FormlyTemplate, FormlyForm, FormlyField, FormlyAttributes, FormlyGroup, FormlyValidationMessage] });
|
|
2339
|
-
FormlyModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyModule, imports: [[CommonModule]] });
|
|
2340
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyModule, decorators: [{
|
|
2383
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyModule, decorators: [{
|
|
2341
2384
|
type: NgModule,
|
|
2342
2385
|
args: [{
|
|
2343
2386
|
declarations: [
|
|
2344
2387
|
FormlyTemplate,
|
|
2345
|
-
|
|
2346
|
-
|
|
2388
|
+
LegacyFormlyForm,
|
|
2389
|
+
LegacyFormlyField,
|
|
2347
2390
|
FormlyAttributes,
|
|
2348
2391
|
FormlyGroup,
|
|
2349
2392
|
FormlyValidationMessage,
|
|
2350
2393
|
FormlyTemplateType,
|
|
2351
2394
|
],
|
|
2352
|
-
exports: [
|
|
2395
|
+
exports: [
|
|
2396
|
+
FormlyTemplate,
|
|
2397
|
+
LegacyFormlyForm,
|
|
2398
|
+
LegacyFormlyField,
|
|
2399
|
+
FormlyAttributes,
|
|
2400
|
+
FormlyGroup,
|
|
2401
|
+
FormlyValidationMessage,
|
|
2402
|
+
],
|
|
2353
2403
|
imports: [CommonModule],
|
|
2354
2404
|
}]
|
|
2355
|
-
}]
|
|
2356
|
-
type: Optional
|
|
2357
|
-
}, {
|
|
2358
|
-
type: Inject,
|
|
2359
|
-
args: [FORMLY_CONFIG]
|
|
2360
|
-
}] }]; } });
|
|
2405
|
+
}] });
|
|
2361
2406
|
|
|
2362
2407
|
/*
|
|
2363
2408
|
* Public API Surface of core
|
|
@@ -2367,5 +2412,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
|
|
|
2367
2412
|
* Generated bundle index. Do not edit.
|
|
2368
2413
|
*/
|
|
2369
2414
|
|
|
2370
|
-
export { FORMLY_CONFIG, FieldArrayType, FieldType, FieldWrapper, FormlyConfig, FormlyField, FormlyForm, FormlyFormBuilder, FormlyModule, FormlyAttributes as ɵFormlyAttributes, FormlyGroup as ɵFormlyGroup, FormlyTemplate as ɵFormlyTemplate, FormlyValidationMessage as ɵFormlyValidationMessage, clone as ɵclone, defineHiddenProp as ɵdefineHiddenProp, getFieldValue as ɵgetFieldValue, hasKey as ɵhasKey, observe as ɵobserve, reverseDeepMerge as ɵreverseDeepMerge };
|
|
2415
|
+
export { FORMLY_CONFIG, FieldArrayType, FieldType, FieldWrapper, FormlyConfig, FormlyField, FormlyForm, FormlyFormBuilder, FormlyModule, LegacyFormlyField, LegacyFormlyForm, provideFormlyConfig, provideFormlyCore, FormlyAttributes as ɵFormlyAttributes, FormlyGroup as ɵFormlyGroup, FormlyTemplate as ɵFormlyTemplate, FormlyValidationMessage as ɵFormlyValidationMessage, clone as ɵclone, defineHiddenProp as ɵdefineHiddenProp, getFieldValue as ɵgetFieldValue, hasKey as ɵhasKey, observe as ɵobserve, reverseDeepMerge as ɵreverseDeepMerge };
|
|
2371
2416
|
//# sourceMappingURL=ngx-formly-core.mjs.map
|