@stemy/ngx-dynamic-form 19.6.2 → 19.6.4

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.
@@ -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 => typeof v == "number" && v >= min, "minValue");
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 => typeof v == "number" && v <= max, "maxValue");
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.props = {
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":
@@ -870,10 +902,6 @@ class DynamicFormSchemaService {
870
902
  // if (this.checkIsEditorProperty(property)) {
871
903
  // return this.getFormEditorConfig(property, options, parent);
872
904
  // }
873
- const refs = await this.openApi.getReferences(property, options.schema);
874
- if (refs.length > 0) {
875
- return this.getFormGroupConfig(property, options, parent);
876
- }
877
905
  if (property.format == "file" || property.format == "upload") {
878
906
  return this.getFormUploadConfig(property, options, parent);
879
907
  }
@@ -883,6 +911,10 @@ class DynamicFormSchemaService {
883
911
  if (property.format == "date" || property.format == "date-time") {
884
912
  return this.getFormDatepickerConfig(property, options, parent);
885
913
  }
914
+ const refs = await this.openApi.getReferences(property, options.schema);
915
+ if (refs.length > 0) {
916
+ return this.getFormGroupConfig(property, options, parent);
917
+ }
886
918
  return this.getFormInputConfig(property, options, parent);
887
919
  }
888
920
  getFormFieldData(property, options) {
@@ -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: property.format == "date-time" ? "datetime-local" : "date",
1010
- // format: property.dateFormat || "dd.MM.yyyy",
1011
- min: convertToDate(property.min),
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