Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix omitExtraData bugs for nested empties and nonspecified objects #1419

Merged
merged 13 commits into from
Aug 22, 2019
58 changes: 34 additions & 24 deletions src/components/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { Component } from "react";
import PropTypes from "prop-types";
import _pick from "lodash/pick";
import _get from "lodash/get";
import _isEmpty from "lodash/isEmpty";

import { default as DefaultErrorList } from "./ErrorList";
import {
Expand Down Expand Up @@ -78,7 +79,6 @@ export default class Form extends Component {
formData,
props.idPrefix
);
const pathSchema = toPathSchema(retrievedSchema, "", definitions, formData);
return {
schema,
uiSchema,
Expand All @@ -88,7 +88,6 @@ export default class Form extends Component {
errors,
errorSchema,
additionalMetaSchemas,
pathSchema,
};
}

Expand Down Expand Up @@ -148,23 +147,16 @@ export default class Form extends Component {
};

getFieldNames = (pathSchema, formData) => {
const getAllPaths = (_obj, acc = [], paths = []) => {
const getAllPaths = (_obj, acc = [], paths = [""]) => {
Object.keys(_obj).forEach(key => {
if (typeof _obj[key] === "object") {
if (!paths.length) {
getAllPaths(_obj[key], acc, [key]);
} else {
let newPaths = [];
paths.forEach(path => {
newPaths.push(path);
});
newPaths = newPaths.map(path => `${path}.${key}`);
getAllPaths(_obj[key], acc, newPaths);
}
} else if (key === "$name") {
let newPaths = paths.map(path => `${path}.${key}`);
getAllPaths(_obj[key], acc, newPaths);
} else if (key === "$name" && _obj[key] !== "") {
paths.forEach(path => {
path = path.replace(/^\./, "");
const formValue = _get(formData, path);
if (typeof formValue !== "object") {
if (typeof formValue !== "object" || _isEmpty(formValue)) {
epicfaace marked this conversation as resolved.
Show resolved Hide resolved
acc.push(path);
}
});
Expand All @@ -186,13 +178,20 @@ export default class Form extends Component {
let newFormData = formData;

if (this.props.omitExtraData === true && this.props.liveOmit === true) {
const newState = this.getStateFromProps(this.props, formData);

const fieldNames = this.getFieldNames(
newState.pathSchema,
newState.formData
const retrievedSchema = retrieveSchema(
this.state.schema,
this.state.schema.definitions,
formData
);
const pathSchema = toPathSchema(
retrievedSchema,
"",
this.state.schema.definitions,
formData
);

const fieldNames = this.getFieldNames(pathSchema, formData);

newFormData = this.getUsedFormData(formData, fieldNames);
state = {
formData: newFormData,
Expand Down Expand Up @@ -237,11 +236,22 @@ export default class Form extends Component {
event.persist();
let newFormData = this.state.formData;

const { pathSchema } = this.state;

if (this.props.omitExtraData === true) {
const fieldNames = this.getFieldNames(pathSchema, this.state.formData);
newFormData = this.getUsedFormData(this.state.formData, fieldNames);
const retrievedSchema = retrieveSchema(
this.state.schema,
this.state.schema.definitions,
newFormData
);
const pathSchema = toPathSchema(
retrievedSchema,
"",
this.state.schema.definitions,
newFormData
);

const fieldNames = this.getFieldNames(pathSchema, newFormData);

newFormData = this.getUsedFormData(newFormData, fieldNames);
}

if (!this.props.noValidate) {
Expand Down
53 changes: 22 additions & 31 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -873,43 +873,34 @@ export function toIdSchema(

export function toPathSchema(schema, name = "", definitions, formData = {}) {
epicfaace marked this conversation as resolved.
Show resolved Hide resolved
const pathSchema = {
$name: name,
$name: name.replace(/^\./, ""),
};
if ("$ref" in schema || "dependencies" in schema) {
const _schema = retrieveSchema(schema, definitions, formData);
return toPathSchema(_schema, name, definitions, formData);
}
if ("items" in schema) {
const retVal = {};
if (Array.isArray(formData) && formData.length > 0) {
formData.forEach((element, index) => {
retVal[`${index}`] = toPathSchema(
schema.items,
`${name}.${index}`,
definitions,
element
);
});
if (
schema.hasOwnProperty("items") &&
Array.isArray(formData) &&
formData.length > 0
Copy link
Member

@epicfaace epicfaace Aug 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is probably not necessary (line 885)

) {
formData.forEach((element, i) => {
pathSchema[i] = toPathSchema(
schema.items,
`${name}.${i}`,
definitions,
element
);
});
} else if (schema.hasOwnProperty("properties")) {
for (const property in schema.properties) {
pathSchema[property] = toPathSchema(
schema.properties[property],
`${name}.${property}`,
definitions,
(formData || {})[property]
);
}
return retVal;
}
if (schema.type !== "object") {
return pathSchema;
}
for (const property in schema.properties || {}) {
const field = schema.properties[property];
const fieldId = pathSchema.$name
? pathSchema.$name + "." + property
: property;

pathSchema[property] = toPathSchema(
field,
fieldId,
definitions,
// It's possible that formData is not an object -- this can happen if an
epicfaace marked this conversation as resolved.
Show resolved Hide resolved
// array item has just been added, but not populated with data yet
(formData || {})[property]
);
}
return pathSchema;
}
Expand Down
Loading