@stemy/ngx-dynamic-form 19.6.2 → 19.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/stemy-ngx-dynamic-form.mjs +159 -127
- package/fesm2022/stemy-ngx-dynamic-form.mjs.map +1 -1
- package/ngx-dynamic-form/utils/internal.d.ts +1 -1
- package/ngx-dynamic-form/utils/misc.d.ts +8 -1
- package/ngx-dynamic-form/utils/validation.d.ts +2 -2
- package/package.json +1 -1
- package/public_api.d.ts +1 -1
|
@@ -2,10 +2,10 @@ import * as i2 from '@stemy/ngx-utils';
|
|
|
2
2
|
import { cachedFactory, ReflectUtils, ObjectUtils, LANGUAGE_SERVICE, ForbiddenZone, API_SERVICE, StringUtils, TOASTER_SERVICE, EventsService, NgxUtilsModule } from '@stemy/ngx-utils';
|
|
3
3
|
import { of, merge, Observable, firstValueFrom, BehaviorSubject, combineLatestWith, switchMap, distinctUntilChanged, first, Subject } from 'rxjs';
|
|
4
4
|
import { debounceTime } from 'rxjs/operators';
|
|
5
|
-
import * as i0 from '@angular/core';
|
|
6
|
-
import { Inject, Injectable, untracked, input, output, inject, Renderer2, ElementRef, computed, signal, effect, HostListener, HostBinding, Directive, Type, Component, Injector, ChangeDetectionStrategy, ViewEncapsulation, makeEnvironmentProviders, NgModule } from '@angular/core';
|
|
7
5
|
import * as i1 from '@angular/forms';
|
|
8
6
|
import { FormGroup as FormGroup$1, FormArray as FormArray$1, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
7
|
+
import * as i0 from '@angular/core';
|
|
8
|
+
import { Inject, Injectable, untracked, input, output, inject, Renderer2, ElementRef, computed, signal, effect, HostListener, HostBinding, Directive, Type, Component, Injector, ChangeDetectionStrategy, ViewEncapsulation, makeEnvironmentProviders, NgModule } from '@angular/core';
|
|
9
9
|
import { outputToObservable, toSignal, rxResource } from '@angular/core/rxjs-interop';
|
|
10
10
|
import * as i3 from '@ngx-formly/core';
|
|
11
11
|
import { FieldType, ɵobserve as _observe, FieldArrayType, FieldWrapper, provideFormlyConfig, provideFormlyCore, FormlyModule } from '@ngx-formly/core';
|
|
@@ -212,10 +212,139 @@ function maxLengthValidation(maxLength, each) {
|
|
|
212
212
|
return validateEach(each, v => typeof v == "string" && v.length <= maxLength, "maxLength");
|
|
213
213
|
}
|
|
214
214
|
function minValueValidation(min, each) {
|
|
215
|
-
return validateEach(each, v =>
|
|
215
|
+
return validateEach(each, v => {
|
|
216
|
+
if (min instanceof Date) {
|
|
217
|
+
v = new Date(v);
|
|
218
|
+
return isNaN(v) || v >= min;
|
|
219
|
+
}
|
|
220
|
+
return v == null || v >= min;
|
|
221
|
+
}, "minValue");
|
|
216
222
|
}
|
|
217
223
|
function maxValueValidation(max, each) {
|
|
218
|
-
return validateEach(each, v =>
|
|
224
|
+
return validateEach(each, v => {
|
|
225
|
+
if (max instanceof Date) {
|
|
226
|
+
v = new Date(v);
|
|
227
|
+
return isNaN(v) || v <= max;
|
|
228
|
+
}
|
|
229
|
+
return v == null || v <= max;
|
|
230
|
+
}, "maxValue");
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
class ConfigForSchemaWrap {
|
|
234
|
+
opts;
|
|
235
|
+
mode;
|
|
236
|
+
injector;
|
|
237
|
+
schema;
|
|
238
|
+
get labelPrefix() {
|
|
239
|
+
return this.opts.labelPrefix;
|
|
240
|
+
}
|
|
241
|
+
get labelCustomizer() {
|
|
242
|
+
return this.opts.labelCustomizer;
|
|
243
|
+
}
|
|
244
|
+
get testId() {
|
|
245
|
+
return this.opts.testId;
|
|
246
|
+
}
|
|
247
|
+
get context() {
|
|
248
|
+
return this.opts.context;
|
|
249
|
+
}
|
|
250
|
+
fieldCustomizer;
|
|
251
|
+
constructor(opts, mode, injector, schema) {
|
|
252
|
+
this.opts = opts;
|
|
253
|
+
this.mode = mode;
|
|
254
|
+
this.injector = injector;
|
|
255
|
+
this.schema = schema;
|
|
256
|
+
this.fieldCustomizer = this.mode !== "wrap" || !ObjectUtils.isFunction(this.opts.fieldCustomizer)
|
|
257
|
+
? field => field
|
|
258
|
+
: this.opts.fieldCustomizer;
|
|
259
|
+
}
|
|
260
|
+
async customize(field, property, schema) {
|
|
261
|
+
field.defaultValue = property.format?.startsWith("date")
|
|
262
|
+
? convertToDateFormat(property.default, property.format) : property.default;
|
|
263
|
+
const res = await ForbiddenZone.run("customizer", () => this.fieldCustomizer(field, this.forCustomizer(), this.injector, property, schema));
|
|
264
|
+
return !res ? [field] : handleConfigs(res);
|
|
265
|
+
}
|
|
266
|
+
forCustomizer() {
|
|
267
|
+
return new ConfigForSchemaWrap(this.opts, "customizer", this.injector, this.schema);
|
|
268
|
+
}
|
|
269
|
+
forSchema(schema) {
|
|
270
|
+
return new ConfigForSchemaWrap(this.opts, this.mode, this.injector, schema);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
async function toWrapOptions(customizeOrOptions, injector, schema, errorMsg) {
|
|
274
|
+
if (errorMsg && ForbiddenZone.isForbidden("customizer")) {
|
|
275
|
+
throw new Error(errorMsg);
|
|
276
|
+
}
|
|
277
|
+
if (customizeOrOptions instanceof ConfigForSchemaWrap) {
|
|
278
|
+
return customizeOrOptions;
|
|
279
|
+
}
|
|
280
|
+
let schemaOptions = customizeOrOptions;
|
|
281
|
+
if (!ObjectUtils.isObject(schemaOptions)) {
|
|
282
|
+
schemaOptions = {
|
|
283
|
+
fieldCustomizer: customizeOrOptions
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
return new ConfigForSchemaWrap(schemaOptions, "wrap", injector, schema);
|
|
287
|
+
}
|
|
288
|
+
function convertToDateFormat(value, format) {
|
|
289
|
+
if (!ObjectUtils.isDefined(value))
|
|
290
|
+
return undefined;
|
|
291
|
+
value = ObjectUtils.isDate(value) ? value : new Date(value);
|
|
292
|
+
const date = isNaN(value) ? new Date() : value;
|
|
293
|
+
return format === "datetime-local" || format === "date-time"
|
|
294
|
+
? new Date(date.getTime() - date.getTimezoneOffset() * 60000)
|
|
295
|
+
.toISOString()
|
|
296
|
+
.slice(0, 16)
|
|
297
|
+
: date.toISOString().slice(0, 10);
|
|
298
|
+
}
|
|
299
|
+
function handleConfigs(configs) {
|
|
300
|
+
return Array.isArray(configs) ? configs : [configs];
|
|
301
|
+
}
|
|
302
|
+
function arrayItemActionToExpression(actionName) {
|
|
303
|
+
return (field) => {
|
|
304
|
+
const action = field.parent?.props?.[actionName];
|
|
305
|
+
// Needed to immediately reflect the changes on the view
|
|
306
|
+
field.options.detectChanges(field);
|
|
307
|
+
if (action === false)
|
|
308
|
+
return false;
|
|
309
|
+
// Returns the actual calculated value
|
|
310
|
+
return ObjectUtils.isFunction(action)
|
|
311
|
+
? action(field.formControl?.value, Number(field.key), field)
|
|
312
|
+
: true;
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
function mergeFormFields(formFields) {
|
|
316
|
+
const res = [];
|
|
317
|
+
for (const formModel of formFields) {
|
|
318
|
+
for (const subModel of formModel) {
|
|
319
|
+
const index = res.findIndex(t => t.key == subModel.key);
|
|
320
|
+
if (index >= 0) {
|
|
321
|
+
res[index] = subModel;
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
res.push(subModel);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return res;
|
|
328
|
+
}
|
|
329
|
+
function getFormValidationErrors(controls, parentPath = "") {
|
|
330
|
+
const errors = [];
|
|
331
|
+
Object.entries(controls).forEach(([name, control], ix) => {
|
|
332
|
+
const path = !parentPath ? name : `${parentPath}.${name}`;
|
|
333
|
+
if (control instanceof FormGroup$1) {
|
|
334
|
+
getFormValidationErrors(control.controls, path).forEach(error => errors.push(error));
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
if (control instanceof FormArray$1) {
|
|
338
|
+
control.controls.forEach((control, ix) => {
|
|
339
|
+
getFormValidationErrors(control.controls, `${path}.${ix}`).forEach(error => errors.push(error));
|
|
340
|
+
});
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
Object.entries(control.errors || {}).forEach(([errorKey, errorValue]) => {
|
|
344
|
+
errors.push({ control, path, errorKey, errorValue });
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
return errors;
|
|
219
348
|
}
|
|
220
349
|
|
|
221
350
|
function replaceSpecialChars(str, to = "-") {
|
|
@@ -297,11 +426,23 @@ function removeFromFieldArray(field, ix) {
|
|
|
297
426
|
model.splice(ix, 1);
|
|
298
427
|
field.options.build(field);
|
|
299
428
|
}
|
|
429
|
+
function setFieldDefault(field, value) {
|
|
430
|
+
field.defaultValue = value instanceof Date ? convertToDateFormat(value, field.props?.type || "date") : value;
|
|
431
|
+
}
|
|
432
|
+
function setFieldProps(field, values) {
|
|
433
|
+
if (!ObjectUtils.isObject(values))
|
|
434
|
+
return;
|
|
435
|
+
const props = Object.assign({}, field.props || {});
|
|
436
|
+
props.type = values.type || props.type;
|
|
437
|
+
Object.keys(values).forEach(key => {
|
|
438
|
+
const value = values[key];
|
|
439
|
+
props[key] = value instanceof Date ? convertToDateFormat(value, props.type || "date") : value;
|
|
440
|
+
});
|
|
441
|
+
field.props = props;
|
|
442
|
+
return field;
|
|
443
|
+
}
|
|
300
444
|
function setFieldProp(field, prop, value) {
|
|
301
|
-
field
|
|
302
|
-
...(field.props || {}),
|
|
303
|
-
[prop]: value
|
|
304
|
-
};
|
|
445
|
+
return setFieldProps(field, { [prop]: value });
|
|
305
446
|
}
|
|
306
447
|
function setFieldHidden(field, hidden = true) {
|
|
307
448
|
setFieldProp(field, "hidden", hidden);
|
|
@@ -328,120 +469,6 @@ const MIN_INPUT_NUM = -1999999999;
|
|
|
328
469
|
const MAX_INPUT_NUM = 1999999999;
|
|
329
470
|
const EDITOR_FORMATS = ["php", "json", "html", "css", "scss"];
|
|
330
471
|
|
|
331
|
-
class ConfigForSchemaWrap {
|
|
332
|
-
opts;
|
|
333
|
-
mode;
|
|
334
|
-
injector;
|
|
335
|
-
schema;
|
|
336
|
-
get labelPrefix() {
|
|
337
|
-
return this.opts.labelPrefix;
|
|
338
|
-
}
|
|
339
|
-
get labelCustomizer() {
|
|
340
|
-
return this.opts.labelCustomizer;
|
|
341
|
-
}
|
|
342
|
-
get testId() {
|
|
343
|
-
return this.opts.testId;
|
|
344
|
-
}
|
|
345
|
-
get context() {
|
|
346
|
-
return this.opts.context;
|
|
347
|
-
}
|
|
348
|
-
fieldCustomizer;
|
|
349
|
-
constructor(opts, mode, injector, schema) {
|
|
350
|
-
this.opts = opts;
|
|
351
|
-
this.mode = mode;
|
|
352
|
-
this.injector = injector;
|
|
353
|
-
this.schema = schema;
|
|
354
|
-
this.fieldCustomizer = this.mode !== "wrap" || !ObjectUtils.isFunction(this.opts.fieldCustomizer)
|
|
355
|
-
? field => field
|
|
356
|
-
: this.opts.fieldCustomizer;
|
|
357
|
-
}
|
|
358
|
-
async customize(field, property, schema) {
|
|
359
|
-
field.defaultValue = `${field.props?.type}`.startsWith("date")
|
|
360
|
-
? convertToDate(property.default) : property.default;
|
|
361
|
-
const res = await ForbiddenZone.run("customizer", () => this.fieldCustomizer(field, this.forCustomizer(), this.injector, property, schema));
|
|
362
|
-
return !res ? [field] : handleConfigs(res);
|
|
363
|
-
}
|
|
364
|
-
forCustomizer() {
|
|
365
|
-
return new ConfigForSchemaWrap(this.opts, "customizer", this.injector, this.schema);
|
|
366
|
-
}
|
|
367
|
-
forSchema(schema) {
|
|
368
|
-
return new ConfigForSchemaWrap(this.opts, this.mode, this.injector, schema);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
async function toWrapOptions(customizeOrOptions, injector, schema, errorMsg) {
|
|
372
|
-
if (errorMsg && ForbiddenZone.isForbidden("customizer")) {
|
|
373
|
-
throw new Error(errorMsg);
|
|
374
|
-
}
|
|
375
|
-
if (customizeOrOptions instanceof ConfigForSchemaWrap) {
|
|
376
|
-
return customizeOrOptions;
|
|
377
|
-
}
|
|
378
|
-
let schemaOptions = customizeOrOptions;
|
|
379
|
-
if (!ObjectUtils.isObject(schemaOptions)) {
|
|
380
|
-
schemaOptions = {
|
|
381
|
-
fieldCustomizer: customizeOrOptions
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
return new ConfigForSchemaWrap(schemaOptions, "wrap", injector, schema);
|
|
385
|
-
}
|
|
386
|
-
function convertToDate(value) {
|
|
387
|
-
if (ObjectUtils.isNullOrUndefined(value))
|
|
388
|
-
return null;
|
|
389
|
-
const date = ObjectUtils.isDate(value)
|
|
390
|
-
? value
|
|
391
|
-
: new Date(value);
|
|
392
|
-
return isNaN(date) ? new Date() : date;
|
|
393
|
-
}
|
|
394
|
-
function handleConfigs(configs) {
|
|
395
|
-
return Array.isArray(configs) ? configs : [configs];
|
|
396
|
-
}
|
|
397
|
-
function arrayItemActionToExpression(actionName) {
|
|
398
|
-
return (field) => {
|
|
399
|
-
const action = field.parent?.props?.[actionName];
|
|
400
|
-
// Needed to immediately reflect the changes on the view
|
|
401
|
-
field.options.detectChanges(field);
|
|
402
|
-
if (action === false)
|
|
403
|
-
return false;
|
|
404
|
-
// Returns the actual calculated value
|
|
405
|
-
return ObjectUtils.isFunction(action)
|
|
406
|
-
? action(field.formControl?.value, Number(field.key), field)
|
|
407
|
-
: true;
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
function mergeFormFields(formFields) {
|
|
411
|
-
const res = [];
|
|
412
|
-
for (const formModel of formFields) {
|
|
413
|
-
for (const subModel of formModel) {
|
|
414
|
-
const index = res.findIndex(t => t.key == subModel.key);
|
|
415
|
-
if (index >= 0) {
|
|
416
|
-
res[index] = subModel;
|
|
417
|
-
continue;
|
|
418
|
-
}
|
|
419
|
-
res.push(subModel);
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
return res;
|
|
423
|
-
}
|
|
424
|
-
function getFormValidationErrors(controls, parentPath = "") {
|
|
425
|
-
const errors = [];
|
|
426
|
-
Object.entries(controls).forEach(([name, control], ix) => {
|
|
427
|
-
const path = !parentPath ? name : `${parentPath}.${name}`;
|
|
428
|
-
if (control instanceof FormGroup$1) {
|
|
429
|
-
getFormValidationErrors(control.controls, path).forEach(error => errors.push(error));
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
if (control instanceof FormArray$1) {
|
|
433
|
-
control.controls.forEach((control, ix) => {
|
|
434
|
-
getFormValidationErrors(control.controls, `${path}.${ix}`).forEach(error => errors.push(error));
|
|
435
|
-
});
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
438
|
-
Object.entries(control.errors || {}).forEach(([errorKey, errorValue]) => {
|
|
439
|
-
errors.push({ control, path, errorKey, errorValue });
|
|
440
|
-
});
|
|
441
|
-
});
|
|
442
|
-
return errors;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
472
|
class DynamicFormBuilderService {
|
|
446
473
|
injector;
|
|
447
474
|
events;
|
|
@@ -546,6 +573,11 @@ class DynamicFormBuilderService {
|
|
|
546
573
|
props.min = isNaN(data.min) ? MIN_INPUT_NUM : data.min;
|
|
547
574
|
props.max = isNaN(data.max) ? MAX_INPUT_NUM : data.max;
|
|
548
575
|
break;
|
|
576
|
+
case "date":
|
|
577
|
+
case "datetime-local":
|
|
578
|
+
props.min = data.min;
|
|
579
|
+
props.max = data.max;
|
|
580
|
+
break;
|
|
549
581
|
case "string":
|
|
550
582
|
case "text":
|
|
551
583
|
case "textarea":
|
|
@@ -1004,12 +1036,12 @@ class DynamicFormSchemaService {
|
|
|
1004
1036
|
// );
|
|
1005
1037
|
// }
|
|
1006
1038
|
getFormDatepickerConfig(property, options, parent) {
|
|
1039
|
+
const type = property.format == "date-time" ? "datetime-local" : "date";
|
|
1007
1040
|
return this.builder.createFormInput(property.id, {
|
|
1008
1041
|
...this.getFormFieldData(property, options),
|
|
1009
|
-
type
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
max: convertToDate(property.max),
|
|
1042
|
+
type,
|
|
1043
|
+
min: convertToDateFormat(property.min, property.format),
|
|
1044
|
+
max: convertToDateFormat(property.max, property.format),
|
|
1013
1045
|
}, parent, options);
|
|
1014
1046
|
}
|
|
1015
1047
|
getFormSelectConfig($enum, property, options, parent) {
|
|
@@ -1805,5 +1837,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
1805
1837
|
* Generated bundle index. Do not edit.
|
|
1806
1838
|
*/
|
|
1807
1839
|
|
|
1808
|
-
export { AsyncSubmitDirective, DynamicFieldType, DynamicFormAlertComponent, DynamicFormArrayComponent, DynamicFormBuilderService, DynamicFormChipsComponent, DynamicFormComponent, DynamicFormFieldComponent, DynamicFormFieldsetComponent, DynamicFormGroupComponent, DynamicFormSchemaService, DynamicFormService, DynamicFormUploadComponent, EDITOR_FORMATS, FORM_ROOT_ID, FormFile, FormGroup, FormInput, FormModel, FormSelect, FormSerializable, FormUpload, MAX_INPUT_NUM, MIN_INPUT_NUM, NgxDynamicFormModule, addFieldValidators, clearFieldArray, controlStatus, controlValues, customizeFormField, emailValidation, getFieldByPath, getFieldsByKey, getFieldsByPredicate, getSelectOptions, insertToFieldArray, jsonValidation, maxLengthValidation, maxValueValidation, minLengthValidation, minValueValidation, phoneValidation, removeFieldValidators, removeFromFieldArray, replaceFieldArray, replaceSpecialChars, requiredValidation, setFieldDisabled, setFieldHidden, setFieldHooks, setFieldProp, translationValidation };
|
|
1840
|
+
export { AsyncSubmitDirective, DynamicFieldType, DynamicFormAlertComponent, DynamicFormArrayComponent, DynamicFormBuilderService, DynamicFormChipsComponent, DynamicFormComponent, DynamicFormFieldComponent, DynamicFormFieldsetComponent, DynamicFormGroupComponent, DynamicFormSchemaService, DynamicFormService, DynamicFormUploadComponent, EDITOR_FORMATS, FORM_ROOT_ID, FormFile, FormGroup, FormInput, FormModel, FormSelect, FormSerializable, FormUpload, MAX_INPUT_NUM, MIN_INPUT_NUM, NgxDynamicFormModule, addFieldValidators, clearFieldArray, controlStatus, controlValues, customizeFormField, emailValidation, getFieldByPath, getFieldsByKey, getFieldsByPredicate, getSelectOptions, insertToFieldArray, jsonValidation, maxLengthValidation, maxValueValidation, minLengthValidation, minValueValidation, phoneValidation, removeFieldValidators, removeFromFieldArray, replaceFieldArray, replaceSpecialChars, requiredValidation, setFieldDefault, setFieldDisabled, setFieldHidden, setFieldHooks, setFieldProp, setFieldProps, translationValidation };
|
|
1809
1841
|
//# sourceMappingURL=stemy-ngx-dynamic-form.mjs.map
|