@luomus/laji-form 15.1.110 → 15.1.112

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.
@@ -17,7 +17,7 @@ import DOMIdService from "../services/dom-id-service";
17
17
  import IdService from "../services/id-service";
18
18
  import RootInstanceService from "../services/root-instance-service";
19
19
  import SingletonMapService from "../services/singleton-map-service";
20
- import { FieldProps, HasMaybeChildren, Lang } from "../types";
20
+ import { FieldProps, HasMaybeChildren, JSONSchema, Lang } from "../types";
21
21
  import MultiActiveArrayService from "../services/multi-active-array-service";
22
22
  import * as fields from "./fields";
23
23
  import * as widgets from "./widgets";
@@ -488,4 +488,8 @@ export default class LajiForm extends React.Component<LajiFormProps, LajiFormSta
488
488
  setTimeout: (fn: () => void, time?: number) => number;
489
489
  destroy: () => void;
490
490
  getSchemaValidationErrors: (formData: any) => any;
491
+ getFormDataReadyForSubmit: (formData: any, schema: JSONSchema) => {
492
+ formData: any;
493
+ removedArrayItemsAndObjects: string[];
494
+ };
491
495
  }
@@ -62,6 +62,7 @@ const dom_id_service_1 = __importDefault(require("../services/dom-id-service"));
62
62
  const id_service_1 = __importDefault(require("../services/id-service"));
63
63
  const root_instance_service_1 = __importDefault(require("../services/root-instance-service"));
64
64
  const singleton_map_service_1 = __importDefault(require("../services/singleton-map-service"));
65
+ const types_1 = require("../types");
65
66
  const multi_active_array_service_1 = __importDefault(require("../services/multi-active-array-service"));
66
67
  const fields = __importStar(require("./fields"));
67
68
  const widgets = __importStar(require("./widgets"));
@@ -147,15 +148,17 @@ class LajiForm extends React.Component {
147
148
  React.createElement(ProgressBar, { now: 100 / jobsAmount * (jobsAmount - runningAmount) })));
148
149
  };
149
150
  this.validateAndSubmit = (warnings = true, onlySchema = false) => {
150
- const { formData } = this.state;
151
- const { onValidationError, onSubmit } = this.props;
151
+ let { formData } = this.state;
152
+ const { onValidationError, onSubmit, schema } = this.props;
152
153
  this.setState({ externalErrors: undefined });
153
154
  return this.validate(warnings, true, onlySchema).then(valid => {
154
155
  if (formData !== this.state.formData) {
155
156
  this.validateAndSubmit(warnings, onlySchema);
156
157
  }
157
158
  else if (valid) {
158
- onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit({ formData: removeUndefinedFromArrays(this.memoizedFormContext.services.ids.removeLajiFormIds(formData)) });
159
+ formData = this.getFormDataReadyForSubmit(formData, schema).formData;
160
+ this.setState({ formData });
161
+ onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit({ formData });
159
162
  }
160
163
  else {
161
164
  onValidationError && onValidationError(this.state.extraErrors);
@@ -200,7 +203,7 @@ class LajiForm extends React.Component {
200
203
  const mergedInternalErrors = (0, deepmerge_1.default)(_liveValidations, !nonlive
201
204
  ? (this.cachedNonliveValidations || {})
202
205
  : (0, deepmerge_1.default)(_validations, schemaErrors));
203
- const mergedAll = (0, deepmerge_1.default)(this.state.externalErrors || {}, mergedInternalErrors);
206
+ let mergedAll = (0, deepmerge_1.default)(this.state.externalErrors || {}, mergedInternalErrors);
204
207
  this.validating = false;
205
208
  resolve(!Object.keys(mergedAll).length);
206
209
  if (!equals((this.state.extraErrors || {}), mergedAll)) {
@@ -368,8 +371,17 @@ class LajiForm extends React.Component {
368
371
  this.eventListeners = [];
369
372
  };
370
373
  this.getSchemaValidationErrors = (formData) => {
371
- const errors = validator_ajv6_1.default.validateFormData(removeUndefinedFromArrays(formData), this.props.schema, undefined, ((e) => (0, validation_2.transformErrors)(this.state.formContext.translations, e))).errors;
372
- return (0, validation_1.toErrorSchema)(errors);
374
+ const errors = validator_ajv6_1.default.validateFormData(formData, this.props.schema, undefined, ((e) => (0, validation_2.transformErrors)(this.state.formContext.translations, e))).errors;
375
+ let schemaErrors = (0, validation_1.toErrorSchema)(errors);
376
+ const ignoreErrorPaths = this.getFormDataReadyForSubmit(formData, this.props.schema).removedArrayItemsAndObjects;
377
+ ignoreErrorPaths.forEach(path => {
378
+ schemaErrors = (0, utils_1.immutableDelete)(schemaErrors, path);
379
+ });
380
+ return schemaErrors;
381
+ };
382
+ this.getFormDataReadyForSubmit = (formData, schema) => {
383
+ formData = this.memoizedFormContext.services.ids.removeLajiFormIds(formData);
384
+ return removeEmptyValuesAndTrim(formData, schema);
373
385
  };
374
386
  if (props.apiClient) {
375
387
  this.apiClient = new ApiClient_1.default(props.apiClient, props.lang, this.translations);
@@ -528,23 +540,62 @@ LajiForm.defaultProps = {
528
540
  uiSchema: {}
529
541
  };
530
542
  exports.default = LajiForm;
531
- const removeUndefinedFromArrays = (formData) => {
532
- if ((0, utils_1.isObject)(formData)) {
533
- return Object.keys(formData).reduce((obj, k) => {
534
- obj[k] = removeUndefinedFromArrays(formData[k]);
535
- return obj;
536
- }, {});
537
- }
538
- else if (Array.isArray(formData)) {
539
- return formData.reduce((filtered, i) => {
540
- if (i === undefined || i === null || i === "") {
541
- return filtered;
542
- }
543
- filtered.push(removeUndefinedFromArrays(i));
544
- return filtered;
545
- }, []);
543
+ const removeEmptyValuesAndTrim = (formData, schema) => {
544
+ const removedArrayItemsAndObjects = [];
545
+ return {
546
+ formData: removeRecursive(formData, schema, true, ""),
547
+ removedArrayItemsAndObjects
548
+ };
549
+ function removeRecursive(formData, schema, isRequired, path) {
550
+ if (schema && (0, types_1.isJSONSchemaObject)(schema) && (0, utils_1.isObject)(formData)) {
551
+ const object = Object.keys(formData).reduce((obj, k) => {
552
+ var _a;
553
+ const childSchema = schema.properties[k];
554
+ const childPath = `${path}/${k}`;
555
+ const value = removeRecursive(formData[k], childSchema, ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.includes(k)) || false, childPath);
556
+ if (value !== undefined) {
557
+ obj[k] = value;
558
+ }
559
+ else if (childSchema && (0, types_1.isJSONSchemaObject)(childSchema)) {
560
+ removedArrayItemsAndObjects.push(childPath);
561
+ }
562
+ return obj;
563
+ }, {});
564
+ return isRequired || Object.keys(object).length > 0 ? object : undefined;
565
+ }
566
+ else if (schema && (0, types_1.isJSONSchemaArray)(schema) && Array.isArray(formData)) {
567
+ const nonEmptyItems = {};
568
+ formData.forEach((item, idx) => {
569
+ const value = removeRecursive(item, schema.items, false, `${path}/${idx}`);
570
+ if (value !== undefined) {
571
+ nonEmptyItems[idx] = value;
572
+ }
573
+ });
574
+ let missingItems = Math.max((schema.minItems || 0) - Object.keys(nonEmptyItems).length, 0);
575
+ const array = formData.reduce((arr, item, idx) => {
576
+ const childPath = `${path}/${idx}`;
577
+ if (idx in nonEmptyItems) {
578
+ arr.push(nonEmptyItems[idx]);
579
+ }
580
+ else if (missingItems > 0) {
581
+ arr.push(removeRecursive(item, schema.items, true, childPath));
582
+ missingItems--;
583
+ }
584
+ else {
585
+ removedArrayItemsAndObjects.push(childPath);
586
+ }
587
+ return arr;
588
+ }, []);
589
+ return isRequired || array.length > 0 ? array : undefined;
590
+ }
591
+ else if (formData === null) {
592
+ return undefined;
593
+ }
594
+ else if (typeof formData === "string") {
595
+ return formData.trim() || undefined;
596
+ }
597
+ return formData;
546
598
  }
547
- return formData;
548
599
  };
549
600
  const getShortcuts = (uiSchema) => {
550
601
  var _a, _b;
@@ -90,7 +90,8 @@ const SelectWidget = (props) => props.schema.type === "array"
90
90
  : React.createElement(SearchableDrowndown, Object.assign({}, props));
91
91
  exports.default = SelectWidget;
92
92
  function SearchableDrowndown(props) {
93
- const { id, disabled, readonly, value, uiSchema, options, onChange, includeEmpty = true } = props;
93
+ var _a;
94
+ const { id, disabled, readonly, value, uiSchema, options, onChange, includeEmpty = (_a = options.includeEmpty) !== null && _a !== void 0 ? _a : true } = props;
94
95
  const { theme } = (0, react_1.useContext)(ReactContext_1.default);
95
96
  const { FormControl } = theme;
96
97
  const containerRef = (0, react_1.useRef)(null);
package/lib/types.d.ts CHANGED
@@ -18,6 +18,7 @@ export declare function isJSONSchemaObject(schema: JSONSchema): schema is JSONSc
18
18
  export type JSONSchemaArray<T = JSONSchema, D = never> = JSONShemaTypeCommon<"array", D[]> & {
19
19
  items: T;
20
20
  uniqueItems?: boolean;
21
+ minItems?: number;
21
22
  maxItems?: number;
22
23
  };
23
24
  export declare function isJSONSchemaArray(schema: JSONSchema): schema is JSONSchemaArray;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luomus/laji-form",
3
- "version": "15.1.110",
3
+ "version": "15.1.112",
4
4
  "description": "React module capable of building dynamic forms from Laji form json schemas",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -41,7 +41,7 @@
41
41
  "license": "MIT",
42
42
  "dependencies": {
43
43
  "@luomus/laji-map": "^5.1.19",
44
- "@luomus/laji-validate": "^0.0.130",
44
+ "@luomus/laji-validate": "^0.0.131",
45
45
  "@rjsf/core": "~5.1.0",
46
46
  "@rjsf/utils": "~5.1.0",
47
47
  "@rjsf/validator-ajv6": "~5.1.0",