@ngx-formly/core 6.3.10 → 7.0.0-alpha.0
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 +7 -7
- 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/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/{esm2020 → esm2022}/lib/templates/field-template.type.mjs +9 -9
- 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/{esm2020 → esm2022}/lib/templates/formly.validation-message.mjs +4 -4
- package/esm2022/lib/utils.mjs +312 -0
- package/esm2022/preset/preset.config.mjs +11 -0
- package/esm2022/preset/preset.module.mjs +18 -0
- package/{esm2020 → esm2022}/select/select-options.pipe.mjs +4 -4
- package/{esm2020 → esm2022}/select/select.module.mjs +5 -5
- package/{esm2020 → esm2022}/testing/component-factory.mjs +5 -4
- package/{fesm2020 → fesm2022}/ngx-formly-core-json-schema.mjs +6 -6
- package/fesm2022/ngx-formly-core-json-schema.mjs.map +1 -0
- package/{fesm2020 → fesm2022}/ngx-formly-core-preset.mjs +14 -19
- 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 +4 -3
- package/fesm2022/ngx-formly-core-testing.mjs.map +1 -0
- package/{fesm2020 → fesm2022}/ngx-formly-core.mjs +1751 -1707
- 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 +2 -6
- 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 +3 -3
- package/package.json +23 -37
- package/preset/preset.config.d.ts +2 -0
- package/select/select-options.pipe.d.ts +1 -1
- 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 -148
- 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/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.type.mjs +0 -57
- package/esm2020/lib/templates/formly.attributes.mjs +0 -187
- package/esm2020/lib/utils.mjs +0 -312
- package/esm2020/preset/preset.module.mjs +0 -32
- 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 -2418
- 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.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/extensions/field-validation/field-validation.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/preset-substitution.extension.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, VERSION, Directive, ViewChildren, Input, Component, ChangeDetectionStrategy, Injectable, ViewContainerRef, Optional, ViewChild, InjectionToken, Inject, EventEmitter, Output, ContentChildren, 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);
|
|
@@ -317,389 +317,93 @@ function isSignalRequired() {
|
|
|
317
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,631 +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
|
-
|
|
872
|
-
|
|
547
|
+
checkExpressions(field, ignoreCache = false) {
|
|
548
|
+
if (!field) {
|
|
549
|
+
return false;
|
|
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
|
+
}
|
|
873
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
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
if (this.field.options) {
|
|
1125
|
-
fieldChangesDetection.push(observeDeep(this.field.options, ['formState'], () => this.field.options.detectChanges(this.field)));
|
|
740
|
+
options._markForCheck = (f) => {
|
|
741
|
+
console.warn(`Formly: 'options._markForCheck' is deprecated since v6.0, use 'options.detectChanges' instead.`);
|
|
742
|
+
options.detectChanges(f);
|
|
743
|
+
};
|
|
744
|
+
options._detectChanges = (f) => {
|
|
745
|
+
if (f._componentRefs) {
|
|
746
|
+
markFieldForCheck(f);
|
|
1126
747
|
}
|
|
1127
|
-
|
|
1128
|
-
}));
|
|
1129
|
-
return () => {
|
|
1130
|
-
fieldChangesDetection.forEach((fnc) => fnc());
|
|
1131
|
-
formEvents?.unsubscribe();
|
|
1132
|
-
valueChanges.unsubscribe();
|
|
748
|
+
f.fieldGroup?.forEach((f) => f && options._detectChanges(f));
|
|
1133
749
|
};
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
this.field = { ...this.field, ...clone(field) };
|
|
1138
|
-
}
|
|
1139
|
-
else {
|
|
1140
|
-
Object.keys(field).forEach((p) => (this.field[p] = field[p]));
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
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 });
|
|
1145
|
-
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 });
|
|
1146
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyForm, decorators: [{
|
|
1147
|
-
type: Component,
|
|
1148
|
-
args: [{
|
|
1149
|
-
selector: 'formly-form',
|
|
1150
|
-
template: '<formly-field [field]="field"></formly-field>',
|
|
1151
|
-
providers: [FormlyFormBuilder, FormlyFieldTemplates],
|
|
1152
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1153
|
-
}]
|
|
1154
|
-
}], ctorParameters: function () { return [{ type: FormlyFormBuilder }, { type: FormlyConfig }, { type: i0.NgZone }, { type: FormlyFieldTemplates }]; }, propDecorators: { form: [{
|
|
1155
|
-
type: Input
|
|
1156
|
-
}], model: [{
|
|
1157
|
-
type: Input
|
|
1158
|
-
}], fields: [{
|
|
1159
|
-
type: Input
|
|
1160
|
-
}], options: [{
|
|
1161
|
-
type: Input
|
|
1162
|
-
}], modelChange: [{
|
|
1163
|
-
type: Output
|
|
1164
|
-
}], templates: [{
|
|
1165
|
-
type: ContentChildren,
|
|
1166
|
-
args: [FormlyTemplate]
|
|
1167
|
-
}] } });
|
|
1168
|
-
|
|
1169
|
-
/**
|
|
1170
|
-
* Allow to link the `field` HTML attributes (`id`, `name` ...) and Event attributes (`focus`, `blur` ...) to an element in the DOM.
|
|
1171
|
-
*/
|
|
1172
|
-
class FormlyAttributes {
|
|
1173
|
-
constructor(renderer, elementRef, _document) {
|
|
1174
|
-
this.renderer = renderer;
|
|
1175
|
-
this.elementRef = elementRef;
|
|
1176
|
-
this.uiAttributesCache = {};
|
|
1177
|
-
/**
|
|
1178
|
-
* HostBinding doesn't register listeners conditionally which may produce some perf issues.
|
|
1179
|
-
*
|
|
1180
|
-
* Formly issue: https://github.com/ngx-formly/ngx-formly/issues/1991
|
|
1181
|
-
*/
|
|
1182
|
-
this.uiEvents = {
|
|
1183
|
-
listeners: [],
|
|
1184
|
-
events: ['click', 'keyup', 'keydown', 'keypress', 'focus', 'blur', 'change'],
|
|
1185
|
-
callback: (eventName, $event) => {
|
|
1186
|
-
switch (eventName) {
|
|
1187
|
-
case 'focus':
|
|
1188
|
-
return this.onFocus($event);
|
|
1189
|
-
case 'blur':
|
|
1190
|
-
return this.onBlur($event);
|
|
1191
|
-
case 'change':
|
|
1192
|
-
return this.onChange($event);
|
|
1193
|
-
default:
|
|
1194
|
-
return this.props[eventName](this.field, $event);
|
|
1195
|
-
}
|
|
1196
|
-
},
|
|
750
|
+
options.detectChanges = (f) => {
|
|
751
|
+
f.options.checkExpressions?.(f);
|
|
752
|
+
options._detectChanges(f);
|
|
1197
753
|
};
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
get fieldAttrElements() {
|
|
1204
|
-
return this.field?.['_elementRefs'] || [];
|
|
1205
|
-
}
|
|
1206
|
-
ngOnChanges(changes) {
|
|
1207
|
-
if (changes.field) {
|
|
1208
|
-
this.field.name && this.setAttribute('name', this.field.name);
|
|
1209
|
-
this.uiEvents.listeners.forEach((listener) => listener());
|
|
1210
|
-
this.uiEvents.events.forEach((eventName) => {
|
|
1211
|
-
if (this.props?.[eventName] || ['focus', 'blur', 'change'].indexOf(eventName) !== -1) {
|
|
1212
|
-
this.uiEvents.listeners.push(this.renderer.listen(this.elementRef.nativeElement, eventName, (e) => this.uiEvents.callback(eventName, e)));
|
|
1213
|
-
}
|
|
1214
|
-
});
|
|
1215
|
-
if (this.props?.attributes) {
|
|
1216
|
-
observe(this.field, ['props', 'attributes'], ({ currentValue, previousValue }) => {
|
|
1217
|
-
if (previousValue) {
|
|
1218
|
-
Object.keys(previousValue).forEach((attr) => this.removeAttribute(attr));
|
|
1219
|
-
}
|
|
1220
|
-
if (currentValue) {
|
|
1221
|
-
Object.keys(currentValue).forEach((attr) => {
|
|
1222
|
-
if (currentValue[attr] != null) {
|
|
1223
|
-
this.setAttribute(attr, currentValue[attr]);
|
|
1224
|
-
}
|
|
1225
|
-
});
|
|
1226
|
-
}
|
|
1227
|
-
});
|
|
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 || {});
|
|
1228
759
|
}
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
if (this.fieldAttrElements.length === 1) {
|
|
1232
|
-
!this.id && this.field.id && this.setAttribute('id', this.field.id);
|
|
1233
|
-
this.focusObserver = observe(this.field, ['focus'], ({ currentValue }) => {
|
|
1234
|
-
this.toggleFocus(currentValue);
|
|
1235
|
-
});
|
|
760
|
+
if (!isSignalRequired()) {
|
|
761
|
+
observe(options, ['parentForm', 'submitted']).setValue(false, false);
|
|
1236
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;
|
|
1237
785
|
}
|
|
1238
|
-
if (
|
|
1239
|
-
|
|
786
|
+
if (field.type !== 'formly-template' &&
|
|
787
|
+
(field.template || field.expressions?.template || field.expressionProperties?.template)) {
|
|
788
|
+
field.type = 'formly-template';
|
|
1240
789
|
}
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
* We need to re-evaluate all the attributes on every change detection cycle, because
|
|
1244
|
-
* by using a HostBinding we run into certain edge cases. This means that whatever logic
|
|
1245
|
-
* is in here has to be super lean or we risk seriously damaging or destroying the performance.
|
|
1246
|
-
*
|
|
1247
|
-
* Formly issue: https://github.com/ngx-formly/ngx-formly/issues/1317
|
|
1248
|
-
* Material issue: https://github.com/angular/components/issues/14024
|
|
1249
|
-
*/
|
|
1250
|
-
ngDoCheck() {
|
|
1251
|
-
if (!this.uiAttributes) {
|
|
1252
|
-
const element = this.elementRef.nativeElement;
|
|
1253
|
-
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';
|
|
1254
792
|
}
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
const value = this.props[attr];
|
|
1258
|
-
if (this.uiAttributesCache[attr] !== value &&
|
|
1259
|
-
(!this.props.attributes || !this.props.attributes.hasOwnProperty(attr.toLowerCase()))) {
|
|
1260
|
-
this.uiAttributesCache[attr] = value;
|
|
1261
|
-
if (value || value === 0) {
|
|
1262
|
-
this.setAttribute(attr, value === true ? attr : `${value}`);
|
|
1263
|
-
}
|
|
1264
|
-
else {
|
|
1265
|
-
this.removeAttribute(attr);
|
|
1266
|
-
}
|
|
1267
|
-
}
|
|
793
|
+
if (field.type) {
|
|
794
|
+
this.config.getMergedField(field);
|
|
1268
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 || [];
|
|
1269
803
|
}
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
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
|
+
}));
|
|
1279
819
|
}
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
820
|
+
return field._proxyInstance;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
class FieldFormExtension {
|
|
825
|
+
prePopulate(field) {
|
|
826
|
+
if (!this.root) {
|
|
827
|
+
this.root = field;
|
|
1284
828
|
}
|
|
1285
|
-
|
|
1286
|
-
|
|
829
|
+
if (field.parent) {
|
|
830
|
+
Object.defineProperty(field, 'form', {
|
|
831
|
+
get: () => field.parent.formControl,
|
|
832
|
+
configurable: true,
|
|
833
|
+
});
|
|
1287
834
|
}
|
|
1288
835
|
}
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
836
|
+
onPopulate(field) {
|
|
837
|
+
if (field.hasOwnProperty('fieldGroup') && !hasKey(field)) {
|
|
838
|
+
defineHiddenProp(field, 'formControl', field.form);
|
|
839
|
+
}
|
|
840
|
+
else {
|
|
841
|
+
this.addFormControl(field);
|
|
842
|
+
}
|
|
1296
843
|
}
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
if ($event instanceof Event) {
|
|
844
|
+
postPopulate(field) {
|
|
845
|
+
if (this.root !== field) {
|
|
1300
846
|
return;
|
|
1301
847
|
}
|
|
1302
|
-
this.
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
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
|
+
}
|
|
1307
859
|
}
|
|
1308
|
-
|
|
1309
|
-
|
|
860
|
+
addFormControl(field) {
|
|
861
|
+
let control = findControl(field);
|
|
862
|
+
if (field.fieldArray) {
|
|
1310
863
|
return;
|
|
1311
864
|
}
|
|
1312
|
-
if (
|
|
1313
|
-
|
|
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
|
+
}
|
|
1314
874
|
}
|
|
1315
875
|
else {
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
const index = f?.['_elementRefs'] ? this.fieldAttrElements.indexOf(this.elementRef) : -1;
|
|
1321
|
-
if (index !== -1) {
|
|
1322
|
-
f['_elementRefs'].splice(index, 1);
|
|
876
|
+
if (control instanceof FormControl) {
|
|
877
|
+
const value = hasKey(field) ? getFieldValue(field) : field.defaultValue;
|
|
878
|
+
control.defaultValue = value;
|
|
879
|
+
}
|
|
1323
880
|
}
|
|
881
|
+
registerControl(field, control);
|
|
1324
882
|
}
|
|
1325
|
-
|
|
1326
|
-
|
|
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
|
+
}
|
|
928
|
+
}
|
|
929
|
+
return markForCheck;
|
|
1327
930
|
}
|
|
1328
|
-
|
|
1329
|
-
|
|
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));
|
|
940
|
+
}
|
|
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;
|
|
1330
1088
|
}
|
|
1331
1089
|
}
|
|
1332
|
-
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 });
|
|
1333
|
-
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 });
|
|
1334
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyAttributes, decorators: [{
|
|
1335
|
-
type: Directive,
|
|
1336
|
-
args: [{
|
|
1337
|
-
selector: '[formlyAttributes]',
|
|
1338
|
-
host: {
|
|
1339
|
-
'(change)': 'onHostChange($event)',
|
|
1340
|
-
},
|
|
1341
|
-
}]
|
|
1342
|
-
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: undefined, decorators: [{
|
|
1343
|
-
type: Inject,
|
|
1344
|
-
args: [DOCUMENT]
|
|
1345
|
-
}] }]; }, propDecorators: { field: [{
|
|
1346
|
-
type: Input,
|
|
1347
|
-
args: ['formlyAttributes']
|
|
1348
|
-
}], id: [{
|
|
1349
|
-
type: Input
|
|
1350
|
-
}] } });
|
|
1351
1090
|
|
|
1352
1091
|
class FieldType {
|
|
1353
1092
|
constructor() {
|
|
@@ -1391,10 +1130,10 @@ class FieldType {
|
|
|
1391
1130
|
get formState() {
|
|
1392
1131
|
return this.options?.formState || {};
|
|
1393
1132
|
}
|
|
1133
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FieldType, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1134
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: FieldType, inputs: { field: "field" }, viewQueries: [{ propertyName: "_formlyControls", predicate: NgControl, descendants: true }], ngImport: i0 }); }
|
|
1394
1135
|
}
|
|
1395
|
-
|
|
1396
|
-
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 });
|
|
1397
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FieldType, decorators: [{
|
|
1136
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FieldType, decorators: [{
|
|
1398
1137
|
type: Directive
|
|
1399
1138
|
}], propDecorators: { _formlyControls: [{
|
|
1400
1139
|
type: ViewChildren,
|
|
@@ -1404,914 +1143,1212 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
|
|
|
1404
1143
|
}] } });
|
|
1405
1144
|
|
|
1406
1145
|
/** @ignore */
|
|
1407
|
-
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: "16.2.12", ngImport: i0, type: FormlyTemplateType, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1164
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: FormlyTemplateType, selector: "formly-template", usesInheritance: true, ngImport: i0, template: `<div [innerHtml]="template"></div>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1408
1165
|
}
|
|
1409
|
-
|
|
1410
|
-
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: `
|
|
1411
|
-
<formly-field *ngFor="let f of field.fieldGroup" [field]="f"></formly-field>
|
|
1412
|
-
<ng-content></ng-content>
|
|
1413
|
-
`, 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 });
|
|
1414
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyGroup, decorators: [{
|
|
1166
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormlyTemplateType, decorators: [{
|
|
1415
1167
|
type: Component,
|
|
1416
1168
|
args: [{
|
|
1417
|
-
selector: 'formly-
|
|
1418
|
-
template:
|
|
1419
|
-
<formly-field *ngFor="let f of field.fieldGroup" [field]="f"></formly-field>
|
|
1420
|
-
<ng-content></ng-content>
|
|
1421
|
-
`,
|
|
1422
|
-
host: {
|
|
1423
|
-
'[class]': 'field.fieldGroupClassName || ""',
|
|
1424
|
-
},
|
|
1169
|
+
selector: 'formly-template',
|
|
1170
|
+
template: `<div [innerHtml]="template"></div>`,
|
|
1425
1171
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1426
1172
|
}]
|
|
1427
|
-
}] });
|
|
1173
|
+
}], ctorParameters: function () { return [{ type: i1.DomSanitizer }]; } });
|
|
1428
1174
|
|
|
1429
1175
|
/**
|
|
1430
|
-
*
|
|
1176
|
+
* Maintains list of formly config options. This can be used to register new field type.
|
|
1431
1177
|
*/
|
|
1432
|
-
class
|
|
1433
|
-
constructor(
|
|
1434
|
-
this.
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
this.
|
|
1439
|
-
|
|
1440
|
-
:
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
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 = {};
|
|
1445
1197
|
}
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
let message = this.config.getValidatorMessage(error);
|
|
1451
|
-
if (isObject(fieldForm.errors[error])) {
|
|
1452
|
-
if (fieldForm.errors[error].errorPath) {
|
|
1453
|
-
return undefined;
|
|
1454
|
-
}
|
|
1455
|
-
if (fieldForm.errors[error].message) {
|
|
1456
|
-
message = fieldForm.errors[error].message;
|
|
1457
|
-
}
|
|
1458
|
-
}
|
|
1459
|
-
if (this.field.validation?.messages?.[error]) {
|
|
1460
|
-
message = this.field.validation.messages[error];
|
|
1461
|
-
}
|
|
1462
|
-
if (this.field.validators?.[error]?.message) {
|
|
1463
|
-
message = this.field.validators[error].message;
|
|
1464
|
-
}
|
|
1465
|
-
if (this.field.asyncValidators?.[error]?.message) {
|
|
1466
|
-
message = this.field.asyncValidators[error].message;
|
|
1467
|
-
}
|
|
1468
|
-
if (typeof message === 'function') {
|
|
1469
|
-
return message(fieldForm.errors[error], this.field);
|
|
1470
|
-
}
|
|
1471
|
-
return message;
|
|
1472
|
-
}
|
|
1198
|
+
addConfig(config) {
|
|
1199
|
+
if (Array.isArray(config)) {
|
|
1200
|
+
config.forEach((c) => this.addConfig(c));
|
|
1201
|
+
return;
|
|
1473
1202
|
}
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
}
|
|
1477
|
-
FormlyValidationMessage.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyValidationMessage, deps: [{ token: FormlyConfig }], target: i0.ɵɵFactoryTarget.Component });
|
|
1478
|
-
FormlyValidationMessage.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: FormlyValidationMessage, selector: "formly-validation-message", inputs: { field: "field" }, usesOnChanges: true, ngImport: i0, template: '{{ errorMessage$ | async }}', isInline: true, pipes: { "async": i2$1.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1479
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyValidationMessage, decorators: [{
|
|
1480
|
-
type: Component,
|
|
1481
|
-
args: [{
|
|
1482
|
-
selector: 'formly-validation-message',
|
|
1483
|
-
template: '{{ errorMessage$ | async }}',
|
|
1484
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1485
|
-
}]
|
|
1486
|
-
}], ctorParameters: function () { return [{ type: FormlyConfig }]; }, propDecorators: { field: [{
|
|
1487
|
-
type: Input
|
|
1488
|
-
}] } });
|
|
1489
|
-
|
|
1490
|
-
class FieldArrayType extends FieldType {
|
|
1491
|
-
onPopulate(field) {
|
|
1492
|
-
if (hasKey(field)) {
|
|
1493
|
-
const control = findControl(field);
|
|
1494
|
-
registerControl(field, control ? control : new FormArray([], { updateOn: field.modelOptions.updateOn }));
|
|
1203
|
+
if (config.types) {
|
|
1204
|
+
config.types.forEach((type) => this.setType(type));
|
|
1495
1205
|
}
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
if (field.fieldGroup.length > length) {
|
|
1499
|
-
for (let i = field.fieldGroup.length - 1; i >= length; --i) {
|
|
1500
|
-
unregisterControl(field.fieldGroup[i], true);
|
|
1501
|
-
field.fieldGroup.splice(i, 1);
|
|
1502
|
-
}
|
|
1206
|
+
if (config.validators) {
|
|
1207
|
+
config.validators.forEach((validator) => this.setValidator(validator));
|
|
1503
1208
|
}
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
if (f.key !== null) {
|
|
1507
|
-
f.key = `${i}`;
|
|
1508
|
-
}
|
|
1509
|
-
field.fieldGroup.push(f);
|
|
1209
|
+
if (config.wrappers) {
|
|
1210
|
+
config.wrappers.forEach((wrapper) => this.setWrapper(wrapper));
|
|
1510
1211
|
}
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
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
|
+
};
|
|
1517
1226
|
}
|
|
1518
|
-
this.model.splice(i, 0, initialModel ? clone(initialModel) : undefined);
|
|
1519
|
-
this.markFieldForCheck(this.field.fieldGroup[i]);
|
|
1520
|
-
this._build();
|
|
1521
1227
|
}
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
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 };
|
|
1239
|
+
}
|
|
1240
|
+
['component', 'extends', 'defaultOptions', 'wrappers'].forEach((prop) => {
|
|
1241
|
+
if (options.hasOwnProperty(prop)) {
|
|
1242
|
+
this.types[options.name][prop] = options[prop];
|
|
1243
|
+
}
|
|
1244
|
+
});
|
|
1245
|
+
}
|
|
1530
1246
|
}
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1247
|
+
getType(name, throwIfNotFound = false) {
|
|
1248
|
+
if (name instanceof Type) {
|
|
1249
|
+
return { component: name, name: name.prototype.constructor.name };
|
|
1250
|
+
}
|
|
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.`);
|
|
1254
|
+
}
|
|
1255
|
+
return null;
|
|
1256
|
+
}
|
|
1257
|
+
this.mergeExtendedType(name);
|
|
1258
|
+
return this.types[name];
|
|
1539
1259
|
}
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1260
|
+
/** @ignore */
|
|
1261
|
+
getMergedField(field = {}) {
|
|
1262
|
+
const type = this.getType(field.type);
|
|
1263
|
+
if (!type) {
|
|
1543
1264
|
return;
|
|
1544
1265
|
}
|
|
1545
|
-
if (
|
|
1546
|
-
|
|
1266
|
+
if (type.defaultOptions) {
|
|
1267
|
+
reverseDeepMerge(field, type.defaultOptions);
|
|
1547
1268
|
}
|
|
1548
|
-
|
|
1549
|
-
|
|
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];
|
|
1550
1287
|
}
|
|
1551
1288
|
}
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1289
|
+
/** @ignore @internal */
|
|
1290
|
+
resolveFieldTypeRef(field = {}) {
|
|
1291
|
+
const type = this.getType(field.type);
|
|
1292
|
+
if (!type) {
|
|
1293
|
+
return null;
|
|
1555
1294
|
}
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1295
|
+
if (!type.component || type._componentRef) {
|
|
1296
|
+
return type._componentRef;
|
|
1297
|
+
}
|
|
1298
|
+
const { _viewContainerRef, _injector } = field.options;
|
|
1299
|
+
if (!_viewContainerRef || !_injector) {
|
|
1300
|
+
return null;
|
|
1559
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;
|
|
1560
1311
|
}
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
class FieldWrapper extends FieldType {
|
|
1569
|
-
set _formlyControls(_) { }
|
|
1570
|
-
set _staticContent(content) {
|
|
1571
|
-
this.fieldComponent = content;
|
|
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
|
+
}
|
|
1572
1319
|
}
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
}], _staticContent: [{
|
|
1582
|
-
type: ViewChild,
|
|
1583
|
-
args: ['fieldComponent', { read: ViewContainerRef, static: true }]
|
|
1584
|
-
}] } });
|
|
1585
|
-
|
|
1586
|
-
/** @ignore */
|
|
1587
|
-
class FormlyTemplateType extends FieldType {
|
|
1588
|
-
constructor(sanitizer) {
|
|
1589
|
-
super();
|
|
1590
|
-
this.sanitizer = sanitizer;
|
|
1591
|
-
this.innerHtml = {};
|
|
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];
|
|
1592
1328
|
}
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1329
|
+
/** @ignore */
|
|
1330
|
+
setTypeWrapper(type, name) {
|
|
1331
|
+
if (!this.types[type]) {
|
|
1332
|
+
this.types[type] = {};
|
|
1333
|
+
}
|
|
1334
|
+
if (!this.types[type].wrappers) {
|
|
1335
|
+
this.types[type].wrappers = [];
|
|
1336
|
+
}
|
|
1337
|
+
if (this.types[type].wrappers.indexOf(name) === -1) {
|
|
1338
|
+
this.types[type].wrappers.push(name);
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
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.`);
|
|
1347
|
+
}
|
|
1348
|
+
return this.validators[name];
|
|
1349
|
+
}
|
|
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,
|
|
1600
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;
|
|
1601
1391
|
}
|
|
1602
|
-
return this.innerHtml.content;
|
|
1603
1392
|
}
|
|
1393
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormlyConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1394
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormlyConfig, providedIn: 'root' }); }
|
|
1604
1395
|
}
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
args: [{
|
|
1610
|
-
selector: 'formly-template',
|
|
1611
|
-
template: `<div [innerHtml]="template"></div>`,
|
|
1612
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1613
|
-
}]
|
|
1614
|
-
}], ctorParameters: function () { return [{ type: i1.DomSanitizer }]; } });
|
|
1396
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormlyConfig, decorators: [{
|
|
1397
|
+
type: Injectable,
|
|
1398
|
+
args: [{ providedIn: 'root' }]
|
|
1399
|
+
}] });
|
|
1615
1400
|
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1401
|
+
class FormlyTemplate {
|
|
1402
|
+
constructor(ref) {
|
|
1403
|
+
this.ref = ref;
|
|
1619
1404
|
}
|
|
1620
|
-
|
|
1621
|
-
|
|
1405
|
+
ngOnChanges() {
|
|
1406
|
+
this.name = this.name || 'formly-group';
|
|
1622
1407
|
}
|
|
1408
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormlyTemplate, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1409
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: FormlyTemplate, selector: "[formlyTemplate]", inputs: { name: ["formlyTemplate", "name"] }, usesOnChanges: true, ngImport: i0 }); }
|
|
1623
1410
|
}
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1411
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormlyTemplate, decorators: [{
|
|
1412
|
+
type: Directive,
|
|
1413
|
+
args: [{ selector: '[formlyTemplate]' }]
|
|
1414
|
+
}], ctorParameters: function () { return [{ type: i0.TemplateRef }]; }, propDecorators: { name: [{
|
|
1415
|
+
type: Input,
|
|
1416
|
+
args: ['formlyTemplate']
|
|
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: "16.2.12", ngImport: i0, type: FormlyFieldTemplates, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1421
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormlyFieldTemplates }); }
|
|
1631
1422
|
}
|
|
1423
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormlyFieldTemplates, decorators: [{
|
|
1424
|
+
type: Injectable
|
|
1425
|
+
}] });
|
|
1632
1426
|
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
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;
|
|
1433
|
+
}
|
|
1434
|
+
get elementRef() {
|
|
1435
|
+
if (this.config.extras.renderFormlyFieldElement) {
|
|
1436
|
+
return this._elementRef;
|
|
1637
1437
|
}
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1438
|
+
if (this.componentRefs?.[0] instanceof ComponentRef) {
|
|
1439
|
+
return this.componentRefs[0].location;
|
|
1440
|
+
}
|
|
1441
|
+
return null;
|
|
1442
|
+
}
|
|
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 = () => { };
|
|
1454
|
+
}
|
|
1455
|
+
ngAfterContentInit() {
|
|
1456
|
+
this.triggerHook('afterContentInit');
|
|
1457
|
+
}
|
|
1458
|
+
ngAfterViewInit() {
|
|
1459
|
+
this.triggerHook('afterViewInit');
|
|
1460
|
+
}
|
|
1461
|
+
ngDoCheck() {
|
|
1462
|
+
if (this.detectFieldBuild && this.field && this.field.options) {
|
|
1463
|
+
this.render();
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
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;
|
|
1484
|
+
}
|
|
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
|
+
}
|
|
1650
1504
|
});
|
|
1651
1505
|
}
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
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 });
|
|
1655
1511
|
}
|
|
1656
|
-
else
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
this.evalExpr(field, key, v);
|
|
1660
|
-
field.options._detectChanges(field);
|
|
1661
|
-
})),
|
|
1662
|
-
};
|
|
1512
|
+
else {
|
|
1513
|
+
const { component } = this.config.getType(f.type, true);
|
|
1514
|
+
ref = containerRef.createComponent(component);
|
|
1663
1515
|
}
|
|
1664
|
-
|
|
1665
|
-
field.expressions = field.expressions || {};
|
|
1666
|
-
for (const key of Object.keys(field.expressions)) {
|
|
1667
|
-
observe(field, ['expressions', key], ({ currentValue: expr }) => {
|
|
1668
|
-
evalExpr(key, isFunction(expr) ? (...args) => expr(field, args[3]) : expr);
|
|
1669
|
-
});
|
|
1670
|
-
}
|
|
1671
|
-
field.expressionProperties = field.expressionProperties || {};
|
|
1672
|
-
for (const key of Object.keys(field.expressionProperties)) {
|
|
1673
|
-
observe(field, ['expressionProperties', key], ({ currentValue }) => evalExpr(key, currentValue));
|
|
1516
|
+
this.attachComponentRef(ref, f);
|
|
1674
1517
|
}
|
|
1675
1518
|
}
|
|
1676
|
-
|
|
1677
|
-
if (field.
|
|
1678
|
-
|
|
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);
|
|
1679
1523
|
}
|
|
1680
|
-
if (
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
if (
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
checkLocked = true;
|
|
1687
|
-
const fieldChanged = this.checkExpressions(f, ignoreCache);
|
|
1688
|
-
const options = field.options;
|
|
1689
|
-
options._hiddenFieldsForCheck
|
|
1690
|
-
.sort((f) => (f.field.hide ? -1 : 1))
|
|
1691
|
-
.forEach((f) => this.changeHideState(f.field, f.field.hide ?? f.default, !ignoreCache));
|
|
1692
|
-
options._hiddenFieldsForCheck = [];
|
|
1693
|
-
if (fieldChanged) {
|
|
1694
|
-
this.checkExpressions(field);
|
|
1695
|
-
}
|
|
1696
|
-
checkLocked = false;
|
|
1697
|
-
};
|
|
1698
|
-
field.options._checkField = (f, ignoreCache) => {
|
|
1699
|
-
console.warn(`Formly: 'options._checkField' is deprecated since v6.0, use 'options.checkExpressions' instead.`);
|
|
1700
|
-
field.options.checkExpressions(f, ignoreCache);
|
|
1701
|
-
};
|
|
1702
|
-
}
|
|
1703
|
-
}
|
|
1704
|
-
parseExpressions(field, path, expr) {
|
|
1705
|
-
let parentExpression;
|
|
1706
|
-
if (field.parent && ['hide', 'props.disabled'].includes(path)) {
|
|
1707
|
-
const rootValue = (f) => {
|
|
1708
|
-
return path === 'hide' ? f.hide : f.props.disabled;
|
|
1709
|
-
};
|
|
1710
|
-
parentExpression = () => {
|
|
1711
|
-
let root = field.parent;
|
|
1712
|
-
while (root.parent && !rootValue(root)) {
|
|
1713
|
-
root = root.parent;
|
|
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());
|
|
1714
1530
|
}
|
|
1715
|
-
|
|
1716
|
-
};
|
|
1531
|
+
}
|
|
1717
1532
|
}
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1533
|
+
if (name === 'onChanges' && changes.field) {
|
|
1534
|
+
this.resetRefs(changes.field.previousValue);
|
|
1535
|
+
this.render();
|
|
1721
1536
|
}
|
|
1722
|
-
let currentValue;
|
|
1723
|
-
return {
|
|
1724
|
-
callback: (ignoreCache) => {
|
|
1725
|
-
try {
|
|
1726
|
-
const exprValue = evalExpression(parentExpression ? (...args) => parentExpression(field) || expr(...args) : expr, { field }, [field.model, field.options.formState, field, ignoreCache]);
|
|
1727
|
-
if (ignoreCache ||
|
|
1728
|
-
(currentValue !== exprValue &&
|
|
1729
|
-
(!isObject(exprValue) ||
|
|
1730
|
-
isObservable(exprValue) ||
|
|
1731
|
-
JSON.stringify(exprValue) !== JSON.stringify(currentValue)))) {
|
|
1732
|
-
currentValue = exprValue;
|
|
1733
|
-
this.evalExpr(field, path, exprValue);
|
|
1734
|
-
return true;
|
|
1735
|
-
}
|
|
1736
|
-
return false;
|
|
1737
|
-
}
|
|
1738
|
-
catch (error) {
|
|
1739
|
-
error.message = `[Formly Error] [Expression "${path}"] ${error.message}`;
|
|
1740
|
-
throw error;
|
|
1741
|
-
}
|
|
1742
|
-
},
|
|
1743
|
-
};
|
|
1744
1537
|
}
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
if (field._expressions) {
|
|
1751
|
-
for (const key of Object.keys(field._expressions)) {
|
|
1752
|
-
field._expressions[key].callback?.(ignoreCache) && (fieldChanged = true);
|
|
1753
|
-
}
|
|
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 });
|
|
1754
1543
|
}
|
|
1755
|
-
field.fieldGroup?.forEach((f) => this.checkExpressions(f, ignoreCache) && (fieldChanged = true));
|
|
1756
|
-
return fieldChanged;
|
|
1757
1544
|
}
|
|
1758
|
-
|
|
1759
|
-
if (field
|
|
1760
|
-
|
|
1761
|
-
.filter((f) => !f._expressions.hasOwnProperty('props.disabled'))
|
|
1762
|
-
.forEach((f) => this.changeDisabledState(f, value));
|
|
1763
|
-
}
|
|
1764
|
-
if (hasKey(field) && field.props.disabled !== value) {
|
|
1765
|
-
field.props.disabled = value;
|
|
1545
|
+
render() {
|
|
1546
|
+
if (!this.field) {
|
|
1547
|
+
return;
|
|
1766
1548
|
}
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
.filter((f) => f && !f._expressions.hide)
|
|
1772
|
-
.forEach((f) => this.changeHideState(f, hide, resetOnHide));
|
|
1549
|
+
// require Formly build
|
|
1550
|
+
if (!this.field.options) {
|
|
1551
|
+
this.detectFieldBuild = true;
|
|
1552
|
+
return;
|
|
1773
1553
|
}
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
field.formControl.reset({ value: undefined, disabled: field.formControl.disabled });
|
|
1785
|
-
field.options.fieldChanges.next({ value: undefined, field, type: 'valueChanges' });
|
|
1786
|
-
if (field.fieldGroup && field.formControl instanceof FormArray) {
|
|
1787
|
-
field.fieldGroup.length = 0;
|
|
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' : '');
|
|
1788
1564
|
}
|
|
1789
1565
|
}
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
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
|
+
}
|
|
1578
|
+
}
|
|
1794
1579
|
}
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
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);
|
|
1798
1586
|
}
|
|
1799
|
-
}
|
|
1587
|
+
}),
|
|
1588
|
+
];
|
|
1589
|
+
if (!isSignalRequired()) {
|
|
1590
|
+
['touched', 'pristine', 'status'].forEach((prop) => this.hostObservers.push(observe(this.field, ['formControl', prop], ({ firstChange }) => !firstChange && markFieldForCheck(this.field))));
|
|
1800
1591
|
}
|
|
1801
|
-
if (field.
|
|
1802
|
-
field.
|
|
1592
|
+
else if (this.field.formControl) {
|
|
1593
|
+
const events = this.field.formControl.events.subscribe(() => markFieldForCheck(this.field));
|
|
1594
|
+
this.hostObservers.push(events);
|
|
1803
1595
|
}
|
|
1804
1596
|
}
|
|
1805
|
-
|
|
1806
|
-
if (
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
if (!control && field.get(key)) {
|
|
1810
|
-
control = field.get(key).formControl;
|
|
1811
|
-
}
|
|
1812
|
-
assignFieldValue({ key, parent, model: field.model }, value);
|
|
1813
|
-
if (control && !(isNil(control.value) && isNil(value)) && control.value !== value) {
|
|
1814
|
-
control.patchValue(value);
|
|
1597
|
+
resetRefs(field) {
|
|
1598
|
+
if (field) {
|
|
1599
|
+
if (field._localFields) {
|
|
1600
|
+
field._localFields = [];
|
|
1815
1601
|
}
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
try {
|
|
1819
|
-
let target = field;
|
|
1820
|
-
const paths = this._evalExpressionPath(field, prop);
|
|
1821
|
-
const lastIndex = paths.length - 1;
|
|
1822
|
-
for (let i = 0; i < lastIndex; i++) {
|
|
1823
|
-
target = target[paths[i]];
|
|
1824
|
-
}
|
|
1825
|
-
target[paths[lastIndex]] = value;
|
|
1602
|
+
else {
|
|
1603
|
+
defineHiddenProp(this.field, '_localFields', []);
|
|
1826
1604
|
}
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
throw error;
|
|
1605
|
+
if (field._componentRefs) {
|
|
1606
|
+
field._componentRefs = field._componentRefs.filter((ref) => this.componentRefs.indexOf(ref) === -1);
|
|
1830
1607
|
}
|
|
1831
|
-
|
|
1832
|
-
this.
|
|
1608
|
+
else {
|
|
1609
|
+
defineHiddenProp(this.field, '_componentRefs', []);
|
|
1833
1610
|
}
|
|
1834
1611
|
}
|
|
1835
|
-
this.
|
|
1836
|
-
}
|
|
1837
|
-
emitExpressionChanges(field, property, value) {
|
|
1838
|
-
if (!field.options.fieldChanges) {
|
|
1839
|
-
return;
|
|
1840
|
-
}
|
|
1841
|
-
field.options.fieldChanges.next({
|
|
1842
|
-
field,
|
|
1843
|
-
type: 'expressionChanges',
|
|
1844
|
-
property,
|
|
1845
|
-
value,
|
|
1846
|
-
});
|
|
1612
|
+
this.componentRefs = [];
|
|
1847
1613
|
}
|
|
1848
|
-
|
|
1849
|
-
if (field
|
|
1850
|
-
return
|
|
1851
|
-
}
|
|
1852
|
-
let paths = [];
|
|
1853
|
-
if (prop.indexOf('[') === -1) {
|
|
1854
|
-
paths = prop.split('.');
|
|
1614
|
+
fieldChanges(field) {
|
|
1615
|
+
if (!field) {
|
|
1616
|
+
return () => { };
|
|
1855
1617
|
}
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
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;
|
|
1864
1629
|
}
|
|
1865
|
-
|
|
1866
|
-
|
|
1630
|
+
if (isObservable(currentValue.value$)) {
|
|
1631
|
+
currentValue.subscription = currentValue.value$.subscribe();
|
|
1632
|
+
}
|
|
1633
|
+
});
|
|
1634
|
+
subscribes.push(() => {
|
|
1635
|
+
if (field._expressions[key]?.subscription) {
|
|
1636
|
+
field._expressions[key].subscription.unsubscribe();
|
|
1867
1637
|
}
|
|
1638
|
+
expressionObserver.unsubscribe();
|
|
1868
1639
|
});
|
|
1869
1640
|
}
|
|
1870
|
-
|
|
1871
|
-
field.
|
|
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());
|
|
1872
1644
|
}
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
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);
|
|
1651
|
+
}
|
|
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));
|
|
1661
|
+
}
|
|
1662
|
+
const { updateOn, debounce } = field.modelOptions;
|
|
1663
|
+
if ((!updateOn || updateOn === 'change') && debounce?.default > 0) {
|
|
1664
|
+
valueChanges = control.valueChanges.pipe(debounceTime(debounce.default));
|
|
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());
|
|
1677
|
+
}
|
|
1678
|
+
let templateFieldsSubs = [];
|
|
1679
|
+
observe(field, ['_localFields'], ({ currentValue }) => {
|
|
1680
|
+
templateFieldsSubs.forEach((unsubscribe) => unsubscribe());
|
|
1681
|
+
templateFieldsSubs = (currentValue || []).map((f) => this.fieldChanges(f));
|
|
1682
|
+
});
|
|
1683
|
+
return () => {
|
|
1684
|
+
subscribes.forEach((unsubscribe) => unsubscribe());
|
|
1685
|
+
templateFieldsSubs.forEach((unsubscribe) => unsubscribe());
|
|
1686
|
+
};
|
|
1687
|
+
}
|
|
1688
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.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 }); }
|
|
1689
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", 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: "16.2.12", 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: function () { return [{ 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: "16.2.12", ngImport: i0, type: LegacyFormlyField, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
1704
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", 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: "16.2.12", 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: "16.2.12", ngImport: i0, type: FormlyGroup, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
1714
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", 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: "16.2.12", 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 = []) {
|
|
1879
1764
|
this.config = config;
|
|
1765
|
+
this.injector = injector;
|
|
1766
|
+
this.viewContainerRef = viewContainerRef;
|
|
1767
|
+
this.parentForm = parentForm;
|
|
1768
|
+
configs.forEach((c) => config.addConfig(c));
|
|
1880
1769
|
}
|
|
1881
|
-
|
|
1882
|
-
this.
|
|
1883
|
-
this.initFieldValidation(field, 'asyncValidators');
|
|
1770
|
+
buildForm(form, fieldGroup = [], model, options) {
|
|
1771
|
+
this.build({ fieldGroup, model, form, options });
|
|
1884
1772
|
}
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
validators.push(this.getPredefinedFieldValidation(field));
|
|
1773
|
+
build(field) {
|
|
1774
|
+
if (!this.config.extensions.core) {
|
|
1775
|
+
throw new Error('NgxFormly: missing `forRoot()` call. use `forRoot()` when registering the `FormlyModule`.');
|
|
1889
1776
|
}
|
|
1890
|
-
if (field
|
|
1891
|
-
|
|
1892
|
-
validatorName === 'validation'
|
|
1893
|
-
? validators.push(...field[type].validation.map((v) => this.wrapNgValidatorFn(field, v)))
|
|
1894
|
-
: validators.push(this.wrapNgValidatorFn(field, field[type][validatorName], validatorName));
|
|
1895
|
-
}
|
|
1777
|
+
if (!field.parent) {
|
|
1778
|
+
this._setOptions(field);
|
|
1896
1779
|
}
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
VALIDATORS.push(opt);
|
|
1908
|
-
}
|
|
1909
|
-
if (!firstChange && field.formControl) {
|
|
1910
|
-
updateValidity(field.formControl);
|
|
1911
|
-
}
|
|
1912
|
-
}));
|
|
1913
|
-
return (control) => {
|
|
1914
|
-
if (VALIDATORS.length === 0) {
|
|
1915
|
-
return null;
|
|
1916
|
-
}
|
|
1917
|
-
return Validators.compose(VALIDATORS.map((opt) => () => {
|
|
1918
|
-
const value = field.props[opt];
|
|
1919
|
-
switch (opt) {
|
|
1920
|
-
case 'required':
|
|
1921
|
-
return Validators.required(control);
|
|
1922
|
-
case 'pattern':
|
|
1923
|
-
return Validators.pattern(value)(control);
|
|
1924
|
-
case 'minLength':
|
|
1925
|
-
const minLengthResult = Validators.minLength(value)(control);
|
|
1926
|
-
const minLengthKey = this.config.getValidatorMessage('minlength') || field.validation?.messages?.minlength
|
|
1927
|
-
? 'minlength'
|
|
1928
|
-
: 'minLength';
|
|
1929
|
-
return minLengthResult ? { [minLengthKey]: minLengthResult.minlength } : null;
|
|
1930
|
-
case 'maxLength':
|
|
1931
|
-
const maxLengthResult = Validators.maxLength(value)(control);
|
|
1932
|
-
const maxLengthKey = this.config.getValidatorMessage('maxlength') || field.validation?.messages?.maxlength
|
|
1933
|
-
? 'maxlength'
|
|
1934
|
-
: 'maxLength';
|
|
1935
|
-
return maxLengthResult ? { [maxLengthKey]: maxLengthResult.maxlength } : null;
|
|
1936
|
-
case 'min':
|
|
1937
|
-
return Validators.min(value)(control);
|
|
1938
|
-
case 'max':
|
|
1939
|
-
return Validators.max(value)(control);
|
|
1940
|
-
default:
|
|
1941
|
-
return null;
|
|
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 });
|
|
1942
1790
|
}
|
|
1943
|
-
|
|
1944
|
-
|
|
1791
|
+
options.checkExpressions?.(field, true);
|
|
1792
|
+
options._detectChanges?.(field);
|
|
1793
|
+
}
|
|
1794
|
+
});
|
|
1945
1795
|
}
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
validatorOption = clone(this.config.getValidator(validator));
|
|
1796
|
+
_build(field) {
|
|
1797
|
+
if (!field) {
|
|
1798
|
+
return;
|
|
1950
1799
|
}
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
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);
|
|
1956
1813
|
}
|
|
1957
|
-
if (
|
|
1958
|
-
|
|
1959
|
-
validatorOption = {
|
|
1960
|
-
name: validatorName,
|
|
1961
|
-
validation: expression,
|
|
1962
|
-
options: Object.keys(options).length > 0 ? options : null,
|
|
1963
|
-
};
|
|
1814
|
+
if (!options._injector) {
|
|
1815
|
+
defineHiddenProp(options, '_injector', this.injector);
|
|
1964
1816
|
}
|
|
1965
|
-
if (
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
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;
|
|
1969
1825
|
};
|
|
1970
1826
|
}
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
if (
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
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
|
+
});
|
|
1978
1835
|
}
|
|
1979
|
-
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", 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: "16.2.12", ngImport: i0, type: FormlyFormBuilder, providedIn: 'root' }); }
|
|
1840
|
+
}
|
|
1841
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormlyFormBuilder, decorators: [{
|
|
1842
|
+
type: Injectable,
|
|
1843
|
+
args: [{ providedIn: 'root' }]
|
|
1844
|
+
}], ctorParameters: function () { return [{ 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
|
+
}] }]; } });
|
|
1854
|
+
|
|
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;
|
|
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 = () => { };
|
|
1905
|
+
}
|
|
1906
|
+
ngDoCheck() {
|
|
1907
|
+
if (this.config.extras.checkExpressionOn === 'changeDetectionCheck') {
|
|
1908
|
+
this.checkExpressionChange();
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
ngOnChanges(changes) {
|
|
1912
|
+
if (changes.fields && this.form) {
|
|
1913
|
+
clearControl(this.form);
|
|
1914
|
+
}
|
|
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();
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
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;
|
|
1936
|
+
}
|
|
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();
|
|
1980
1954
|
};
|
|
1981
1955
|
}
|
|
1982
|
-
|
|
1983
|
-
if (
|
|
1984
|
-
|
|
1956
|
+
setField(field) {
|
|
1957
|
+
if (this.config.extras.immutable) {
|
|
1958
|
+
this.field = { ...this.field, ...clone(field) };
|
|
1985
1959
|
}
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
1960
|
+
else {
|
|
1961
|
+
Object.keys(field).forEach((p) => (this.field[p] = field[p]));
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", 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: "16.2.12", 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: "16.2.12", 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: function () { return [{ 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: "16.2.12", ngImport: i0, type: LegacyFormlyForm, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
1993
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", 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: "16.2.12", 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)));
|
|
2000
2050
|
}
|
|
2001
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
|
+
});
|
|
2065
|
+
}
|
|
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
|
+
});
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
if (changes.id) {
|
|
2076
|
+
this.setAttribute('id', this.id);
|
|
2002
2077
|
}
|
|
2003
|
-
return errors;
|
|
2004
2078
|
}
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
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));
|
|
2011
2091
|
}
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
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
|
+
}
|
|
2017
2105
|
}
|
|
2018
2106
|
}
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
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;
|
|
2022
2116
|
}
|
|
2023
|
-
|
|
2024
|
-
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());
|
|
2025
2124
|
}
|
|
2026
2125
|
}
|
|
2027
|
-
|
|
2028
|
-
|
|
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) {
|
|
2029
2137
|
return;
|
|
2030
2138
|
}
|
|
2031
|
-
this.
|
|
2032
|
-
const markForCheck = this.setValidators(field);
|
|
2033
|
-
if (markForCheck && field.parent) {
|
|
2034
|
-
let parent = field.parent;
|
|
2035
|
-
while (parent) {
|
|
2036
|
-
if (hasKey(parent) || !parent.parent) {
|
|
2037
|
-
updateValidity(parent.formControl, true);
|
|
2038
|
-
}
|
|
2039
|
-
parent = parent.parent;
|
|
2040
|
-
}
|
|
2041
|
-
}
|
|
2139
|
+
this.onChange($event);
|
|
2042
2140
|
}
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2141
|
+
onChange($event) {
|
|
2142
|
+
this.props.change?.(this.field, $event);
|
|
2143
|
+
this.field.formControl?.markAsDirty();
|
|
2144
|
+
}
|
|
2145
|
+
attachElementRef(f) {
|
|
2146
|
+
if (!f) {
|
|
2046
2147
|
return;
|
|
2047
2148
|
}
|
|
2048
|
-
if (
|
|
2049
|
-
|
|
2050
|
-
if (field.fieldGroup) {
|
|
2051
|
-
control = new FormGroup({}, controlOptions);
|
|
2052
|
-
}
|
|
2053
|
-
else {
|
|
2054
|
-
const value = hasKey(field) ? getFieldValue(field) : field.defaultValue;
|
|
2055
|
-
control = new FormControl({ value, disabled: !!field.props.disabled }, { ...controlOptions, initialValueIsDefault: true });
|
|
2056
|
-
}
|
|
2149
|
+
if (f['_elementRefs']?.indexOf(this.elementRef) === -1) {
|
|
2150
|
+
f['_elementRefs'].push(this.elementRef);
|
|
2057
2151
|
}
|
|
2058
2152
|
else {
|
|
2059
|
-
|
|
2060
|
-
const value = hasKey(field) ? getFieldValue(field) : field.defaultValue;
|
|
2061
|
-
control.defaultValue = value;
|
|
2062
|
-
}
|
|
2153
|
+
defineHiddenProp(f, '_elementRefs', [this.elementRef]);
|
|
2063
2154
|
}
|
|
2064
|
-
registerControl(field, control);
|
|
2065
2155
|
}
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
let markForCheck = false;
|
|
2071
|
-
field.fieldGroup?.forEach((f) => f && this.setValidators(f, disabled) && (markForCheck = true));
|
|
2072
|
-
if (hasKey(field) || !field.parent || (!hasKey(field) && !field.fieldGroup)) {
|
|
2073
|
-
const { formControl: c } = field;
|
|
2074
|
-
if (c) {
|
|
2075
|
-
if (hasKey(field) && c instanceof FormControl) {
|
|
2076
|
-
if (disabled && c.enabled) {
|
|
2077
|
-
c.disable({ emitEvent: false, onlySelf: true });
|
|
2078
|
-
markForCheck = true;
|
|
2079
|
-
}
|
|
2080
|
-
if (!disabled && c.disabled) {
|
|
2081
|
-
c.enable({ emitEvent: false, onlySelf: true });
|
|
2082
|
-
markForCheck = true;
|
|
2083
|
-
}
|
|
2084
|
-
}
|
|
2085
|
-
if (null === c.validator && this.hasValidators(field, '_validators')) {
|
|
2086
|
-
c.setValidators(() => {
|
|
2087
|
-
const v = Validators.compose(this.mergeValidators(field, '_validators'));
|
|
2088
|
-
return v ? v(c) : null;
|
|
2089
|
-
});
|
|
2090
|
-
markForCheck = true;
|
|
2091
|
-
}
|
|
2092
|
-
if (null === c.asyncValidator && this.hasValidators(field, '_asyncValidators')) {
|
|
2093
|
-
c.setAsyncValidators(() => {
|
|
2094
|
-
const v = Validators.composeAsync(this.mergeValidators(field, '_asyncValidators'));
|
|
2095
|
-
return v ? v(c) : of(null);
|
|
2096
|
-
});
|
|
2097
|
-
markForCheck = true;
|
|
2098
|
-
}
|
|
2099
|
-
if (markForCheck) {
|
|
2100
|
-
updateValidity(c, true);
|
|
2101
|
-
// update validity of `FormGroup` instance created by field with nested key.
|
|
2102
|
-
let parent = c.parent;
|
|
2103
|
-
for (let i = 1; i < getKeyPath(field).length; i++) {
|
|
2104
|
-
if (parent) {
|
|
2105
|
-
updateValidity(parent, true);
|
|
2106
|
-
parent = parent.parent;
|
|
2107
|
-
}
|
|
2108
|
-
}
|
|
2109
|
-
}
|
|
2110
|
-
}
|
|
2156
|
+
detachElementRef(f) {
|
|
2157
|
+
const index = f?.['_elementRefs'] ? this.fieldAttrElements.indexOf(this.elementRef) : -1;
|
|
2158
|
+
if (index !== -1) {
|
|
2159
|
+
f['_elementRefs'].splice(index, 1);
|
|
2111
2160
|
}
|
|
2112
|
-
return markForCheck;
|
|
2113
2161
|
}
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
if (c?._fields?.length > 1 && c._fields.some((f) => f[type].length > 0)) {
|
|
2117
|
-
return true;
|
|
2118
|
-
}
|
|
2119
|
-
else if (field[type].length > 0) {
|
|
2120
|
-
return true;
|
|
2121
|
-
}
|
|
2122
|
-
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);
|
|
2123
2164
|
}
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2165
|
+
removeAttribute(attr) {
|
|
2166
|
+
this.renderer.removeAttribute(this.elementRef.nativeElement, attr);
|
|
2167
|
+
}
|
|
2168
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", 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: "16.2.12", 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: "16.2.12", ngImport: i0, type: FormlyAttributes, decorators: [{
|
|
2172
|
+
type: Directive,
|
|
2173
|
+
args: [{
|
|
2174
|
+
selector: '[formlyAttributes]',
|
|
2175
|
+
host: {
|
|
2176
|
+
'(change)': 'onHostChange($event)',
|
|
2177
|
+
},
|
|
2178
|
+
}]
|
|
2179
|
+
}], ctorParameters: function () { return [{ 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
|
+
}
|
|
2139
2233
|
}
|
|
2140
|
-
return
|
|
2234
|
+
return undefined;
|
|
2141
2235
|
}
|
|
2236
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormlyValidationMessage, deps: [{ token: FormlyConfig }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2237
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", 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 }); }
|
|
2142
2238
|
}
|
|
2239
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", 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: function () { return [{ type: FormlyConfig }]; }, propDecorators: { field: [{
|
|
2247
|
+
type: Input
|
|
2248
|
+
}] } });
|
|
2143
2249
|
|
|
2144
|
-
class
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
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);
|
|
2159
2270
|
}
|
|
2160
|
-
Object.defineProperty(field, 'get', {
|
|
2161
|
-
value: (key) => getField(field, key),
|
|
2162
|
-
configurable: true,
|
|
2163
|
-
});
|
|
2164
|
-
this.getFieldComponentInstance(field).prePopulate?.(field);
|
|
2165
2271
|
}
|
|
2166
|
-
|
|
2167
|
-
this.
|
|
2168
|
-
this.
|
|
2169
|
-
if (
|
|
2170
|
-
field
|
|
2171
|
-
if (f) {
|
|
2172
|
-
Object.defineProperty(f, 'parent', { get: () => field, configurable: true });
|
|
2173
|
-
Object.defineProperty(f, 'index', { get: () => index, configurable: true });
|
|
2174
|
-
}
|
|
2175
|
-
this.formId++;
|
|
2176
|
-
});
|
|
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, []);
|
|
2177
2277
|
}
|
|
2278
|
+
this.model.splice(i, 0, initialModel ? clone(initialModel) : undefined);
|
|
2279
|
+
this.markFieldForCheck(this.field.fieldGroup[i]);
|
|
2280
|
+
this._build();
|
|
2178
2281
|
}
|
|
2179
|
-
|
|
2180
|
-
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();
|
|
2181
2290
|
}
|
|
2182
|
-
|
|
2183
|
-
field.
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
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',
|
|
2188
2298
|
});
|
|
2189
2299
|
}
|
|
2190
|
-
|
|
2191
|
-
if (
|
|
2300
|
+
updateArrayElementKey(f, newKey) {
|
|
2301
|
+
if (hasKey(f)) {
|
|
2302
|
+
f.key = newKey;
|
|
2192
2303
|
return;
|
|
2193
2304
|
}
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
if (!options.showError) {
|
|
2197
|
-
options.showError = this.config.extras.showError;
|
|
2198
|
-
}
|
|
2199
|
-
if (!options.fieldChanges) {
|
|
2200
|
-
defineHiddenProp(options, 'fieldChanges', new Subject());
|
|
2305
|
+
if (!f.fieldGroup?.length) {
|
|
2306
|
+
return;
|
|
2201
2307
|
}
|
|
2202
|
-
|
|
2203
|
-
|
|
2308
|
+
for (let i = 0; i < f.fieldGroup.length; i++) {
|
|
2309
|
+
this.updateArrayElementKey(f.fieldGroup[i], newKey);
|
|
2204
2310
|
}
|
|
2205
|
-
options._markForCheck = (f) => {
|
|
2206
|
-
console.warn(`Formly: 'options._markForCheck' is deprecated since v6.0, use 'options.detectChanges' instead.`);
|
|
2207
|
-
options.detectChanges(f);
|
|
2208
|
-
};
|
|
2209
|
-
options._detectChanges = (f) => {
|
|
2210
|
-
if (f._componentRefs) {
|
|
2211
|
-
markFieldForCheck(f);
|
|
2212
|
-
}
|
|
2213
|
-
f.fieldGroup?.forEach((f) => f && options._detectChanges(f));
|
|
2214
|
-
};
|
|
2215
|
-
options.detectChanges = (f) => {
|
|
2216
|
-
f.options.checkExpressions?.(f);
|
|
2217
|
-
options._detectChanges(f);
|
|
2218
|
-
};
|
|
2219
|
-
options.resetModel = (model) => {
|
|
2220
|
-
model = clone(model ?? options._initialModel);
|
|
2221
|
-
if (field.model) {
|
|
2222
|
-
Object.keys(field.model).forEach((k) => delete field.model[k]);
|
|
2223
|
-
Object.assign(field.model, model || {});
|
|
2224
|
-
}
|
|
2225
|
-
if (!isSignalRequired()) {
|
|
2226
|
-
observe(options, ['parentForm', 'submitted']).setValue(false, false);
|
|
2227
|
-
}
|
|
2228
|
-
options.build(field);
|
|
2229
|
-
field.form.reset(field.model);
|
|
2230
|
-
};
|
|
2231
|
-
options.updateInitialValue = (model) => (options._initialModel = clone(model ?? field.model));
|
|
2232
|
-
field.options.updateInitialValue();
|
|
2233
2311
|
}
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
hooks: {},
|
|
2238
|
-
modelOptions: {},
|
|
2239
|
-
validation: { messages: {} },
|
|
2240
|
-
props: !field.type || !hasKey(field)
|
|
2241
|
-
? {}
|
|
2242
|
-
: {
|
|
2243
|
-
label: '',
|
|
2244
|
-
placeholder: '',
|
|
2245
|
-
disabled: false,
|
|
2246
|
-
},
|
|
2247
|
-
});
|
|
2248
|
-
if (this.config.extras.resetFieldOnHide && field.resetOnHide !== false) {
|
|
2249
|
-
field.resetOnHide = true;
|
|
2250
|
-
}
|
|
2251
|
-
if (field.type !== 'formly-template' &&
|
|
2252
|
-
(field.template || field.expressions?.template || field.expressionProperties?.template)) {
|
|
2253
|
-
field.type = 'formly-template';
|
|
2254
|
-
}
|
|
2255
|
-
if (!field.type && field.fieldGroup) {
|
|
2256
|
-
field.type = 'formly-group';
|
|
2257
|
-
}
|
|
2258
|
-
if (field.type) {
|
|
2259
|
-
this.config.getMergedField(field);
|
|
2260
|
-
}
|
|
2261
|
-
if (hasKey(field) &&
|
|
2262
|
-
!isUndefined(field.defaultValue) &&
|
|
2263
|
-
isUndefined(getFieldValue(field)) &&
|
|
2264
|
-
!isHiddenField(field)) {
|
|
2265
|
-
assignFieldValue(field, field.defaultValue);
|
|
2312
|
+
markFieldForCheck(f) {
|
|
2313
|
+
if (!f) {
|
|
2314
|
+
return;
|
|
2266
2315
|
}
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
const componentRefInstance = () => {
|
|
2271
|
-
let componentRef = this.config.resolveFieldTypeRef(field);
|
|
2272
|
-
const fieldComponentRef = field._componentRefs?.slice(-1)[0];
|
|
2273
|
-
if (fieldComponentRef instanceof ComponentRef &&
|
|
2274
|
-
fieldComponentRef?.componentType === componentRef?.componentType) {
|
|
2275
|
-
componentRef = fieldComponentRef;
|
|
2276
|
-
}
|
|
2277
|
-
return componentRef?.instance;
|
|
2278
|
-
};
|
|
2279
|
-
if (!field._proxyInstance) {
|
|
2280
|
-
defineHiddenProp(field, '_proxyInstance', new Proxy({}, {
|
|
2281
|
-
get: (_, prop) => componentRefInstance()?.[prop],
|
|
2282
|
-
set: (_, prop, value) => (componentRefInstance()[prop] = value),
|
|
2283
|
-
}));
|
|
2316
|
+
f.fieldGroup?.forEach((c) => this.markFieldForCheck(c));
|
|
2317
|
+
if (f.hide === false) {
|
|
2318
|
+
this.options._hiddenFieldsForCheck.push({ field: f });
|
|
2284
2319
|
}
|
|
2285
|
-
return field._proxyInstance;
|
|
2286
2320
|
}
|
|
2321
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FieldArrayType, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2322
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: FieldArrayType, usesInheritance: true, ngImport: i0 }); }
|
|
2287
2323
|
}
|
|
2324
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FieldArrayType, decorators: [{
|
|
2325
|
+
type: Directive
|
|
2326
|
+
}] });
|
|
2288
2327
|
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
{ name: 'core', extension: new CoreExtension(config), priority: -250 },
|
|
2297
|
-
{ name: 'field-validation', extension: new FieldValidationExtension(config), priority: -200 },
|
|
2298
|
-
{ name: 'field-form', extension: new FieldFormExtension(), priority: -150 },
|
|
2299
|
-
{ name: 'field-expression', extension: new FieldExpressionExtension(), priority: -100 },
|
|
2300
|
-
],
|
|
2301
|
-
};
|
|
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: "16.2.12", ngImport: i0, type: FieldWrapper, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2334
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", 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 }); }
|
|
2302
2335
|
}
|
|
2336
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", 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
|
+
|
|
2303
2346
|
class FormlyModule {
|
|
2304
|
-
constructor(configService, configs = []) {
|
|
2305
|
-
if (!configs) {
|
|
2306
|
-
return;
|
|
2307
|
-
}
|
|
2308
|
-
configs.forEach((config) => configService.addConfig(config));
|
|
2309
|
-
}
|
|
2310
2347
|
static forRoot(config = {}) {
|
|
2311
2348
|
return {
|
|
2312
2349
|
ngModule: FormlyModule,
|
|
2313
2350
|
providers: [
|
|
2314
|
-
{ provide: FORMLY_CONFIG, multi: true, useFactory:
|
|
2351
|
+
{ provide: FORMLY_CONFIG, multi: true, useFactory: withDefaultConfig, deps: [FormlyConfig] },
|
|
2315
2352
|
{ provide: FORMLY_CONFIG, useValue: config, multi: true },
|
|
2316
2353
|
FormlyConfig,
|
|
2317
2354
|
FormlyFormBuilder,
|
|
@@ -2322,43 +2359,50 @@ class FormlyModule {
|
|
|
2322
2359
|
return {
|
|
2323
2360
|
ngModule: FormlyModule,
|
|
2324
2361
|
providers: [
|
|
2325
|
-
{ provide: FORMLY_CONFIG, multi: true, useFactory:
|
|
2362
|
+
{ provide: FORMLY_CONFIG, multi: true, useFactory: withDefaultConfig, deps: [FormlyConfig] },
|
|
2326
2363
|
{ provide: FORMLY_CONFIG, useValue: config, multi: true },
|
|
2327
2364
|
FormlyFormBuilder,
|
|
2328
2365
|
],
|
|
2329
2366
|
};
|
|
2330
2367
|
}
|
|
2368
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormlyModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
2369
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", 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: "16.2.12", ngImport: i0, type: FormlyModule, imports: [CommonModule] }); }
|
|
2331
2382
|
}
|
|
2332
|
-
|
|
2333
|
-
FormlyModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyModule, declarations: [FormlyTemplate,
|
|
2334
|
-
FormlyForm,
|
|
2335
|
-
FormlyField,
|
|
2336
|
-
FormlyAttributes,
|
|
2337
|
-
FormlyGroup,
|
|
2338
|
-
FormlyValidationMessage,
|
|
2339
|
-
FormlyTemplateType], imports: [CommonModule], exports: [FormlyTemplate, FormlyForm, FormlyField, FormlyAttributes, FormlyGroup, FormlyValidationMessage] });
|
|
2340
|
-
FormlyModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyModule, imports: [[CommonModule]] });
|
|
2341
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FormlyModule, decorators: [{
|
|
2383
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormlyModule, decorators: [{
|
|
2342
2384
|
type: NgModule,
|
|
2343
2385
|
args: [{
|
|
2344
2386
|
declarations: [
|
|
2345
2387
|
FormlyTemplate,
|
|
2346
|
-
|
|
2347
|
-
|
|
2388
|
+
LegacyFormlyForm,
|
|
2389
|
+
LegacyFormlyField,
|
|
2348
2390
|
FormlyAttributes,
|
|
2349
2391
|
FormlyGroup,
|
|
2350
2392
|
FormlyValidationMessage,
|
|
2351
2393
|
FormlyTemplateType,
|
|
2352
2394
|
],
|
|
2353
|
-
exports: [
|
|
2395
|
+
exports: [
|
|
2396
|
+
FormlyTemplate,
|
|
2397
|
+
LegacyFormlyForm,
|
|
2398
|
+
LegacyFormlyField,
|
|
2399
|
+
FormlyAttributes,
|
|
2400
|
+
FormlyGroup,
|
|
2401
|
+
FormlyValidationMessage,
|
|
2402
|
+
],
|
|
2354
2403
|
imports: [CommonModule],
|
|
2355
2404
|
}]
|
|
2356
|
-
}]
|
|
2357
|
-
type: Optional
|
|
2358
|
-
}, {
|
|
2359
|
-
type: Inject,
|
|
2360
|
-
args: [FORMLY_CONFIG]
|
|
2361
|
-
}] }]; } });
|
|
2405
|
+
}] });
|
|
2362
2406
|
|
|
2363
2407
|
/*
|
|
2364
2408
|
* Public API Surface of core
|
|
@@ -2368,5 +2412,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
|
|
|
2368
2412
|
* Generated bundle index. Do not edit.
|
|
2369
2413
|
*/
|
|
2370
2414
|
|
|
2371
|
-
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 };
|
|
2372
2416
|
//# sourceMappingURL=ngx-formly-core.mjs.map
|