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

Allow references that don't start with #/definitions/ #1506

Merged
merged 22 commits into from
Feb 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions packages/core/docs/advanced-customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -515,12 +515,13 @@ A field component will always be passed the following props:

#### The `registry` object

The `registry` is an object containing the registered custom fields and widgets as well as root schema definitions.
The `registry` is an object containing the registered custom fields and widgets as well as the root schema definitions.

- `fields`: The [custom registered fields](#custom-field-components). By default this object contains the standard `SchemaField`, `TitleField` and `DescriptionField` components;
- `widgets`: The [custom registered widgets](#custom-widget-components), if any;
- `definitions`: The root schema [definitions](#schema-definitions-and-references), if any.
- `formContext`: The [formContext](#the-formcontext-object) object.
- `rootSchema`: The root schema, which can contain referenced [definitions](#schema-definitions-and-references);
- `formContext`: The [formContext](#the-formcontext-object) object;
- `definitions` (deprecated since v2): Equal to `rootSchema.definitions`.

The registry is passed down the component tree, so you can access it from your custom field and `SchemaField` components.

Expand Down
5 changes: 1 addition & 4 deletions packages/core/docs/definitions.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,4 @@ This library partially supports [inline schema definition dereferencing]( http:/
}
```

*(Sample schema courtesy of the [Space Telescope Science Institute](http://spacetelescope.github.io/understanding-json-schema/structuring.html))*

Note that it only supports local definition referencing; we do not plan on fetching foreign schemas over HTTP anytime soon. Basically, you can only reference a definition from the very schema object defining it.

Note that this library only supports local definition referencing. The value in the `$ref` keyword should be a [JSON Pointer](https://tools.ietf.org/html/rfc6901) in URI fragment identifier format.
5 changes: 5 additions & 0 deletions packages/core/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@babel/runtime-corejs2": "^7.4.5",
"ajv": "^6.7.0",
"core-js": "^2.5.7",
"jsonpointer": "^4.0.1",
"json-schema-merge-allof": "^0.6.0",
"lodash": "^4.17.15",
"prop-types": "^15.7.2",
Expand Down
21 changes: 11 additions & 10 deletions packages/core/src/components/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ export default class Form extends Component {
const edit = typeof inputFormData !== "undefined";
const liveValidate = props.liveValidate || this.props.liveValidate;
const mustValidate = edit && !props.noValidate && liveValidate;
const { definitions } = schema;
const formData = getDefaultFormState(schema, inputFormData, definitions);
const retrievedSchema = retrieveSchema(schema, definitions, formData);
const rootSchema = schema;
const formData = getDefaultFormState(schema, inputFormData, rootSchema);
const retrievedSchema = retrieveSchema(schema, rootSchema, formData);
const customFormats = props.customFormats;
const additionalMetaSchemas = props.additionalMetaSchemas;
let { errors, errorSchema } = mustValidate
Expand All @@ -78,7 +78,7 @@ export default class Form extends Component {
const idSchema = toIdSchema(
retrievedSchema,
uiSchema["ui:rootFieldId"],
definitions,
rootSchema,
formData,
props.idPrefix
);
Expand All @@ -105,8 +105,8 @@ export default class Form extends Component {
customFormats = this.props.customFormats
) {
const { validate, transformErrors } = this.props;
const { definitions } = this.getRegistry();
const resolvedSchema = retrieveSchema(schema, definitions, formData);
const { rootSchema } = this.getRegistry();
const resolvedSchema = retrieveSchema(schema, rootSchema, formData);
return validateFormData(
formData,
resolvedSchema,
Expand Down Expand Up @@ -185,13 +185,13 @@ export default class Form extends Component {
if (this.props.omitExtraData === true && this.props.liveOmit === true) {
const retrievedSchema = retrieveSchema(
this.state.schema,
this.state.schema.definitions,
this.state.schema,
formData
);
const pathSchema = toPathSchema(
retrievedSchema,
"",
this.state.schema.definitions,
this.state.schema,
formData
);

Expand Down Expand Up @@ -250,13 +250,13 @@ export default class Form extends Component {
if (this.props.omitExtraData === true) {
const retrievedSchema = retrieveSchema(
this.state.schema,
this.state.schema.definitions,
this.state.schema,
newFormData
);
const pathSchema = toPathSchema(
retrievedSchema,
"",
this.state.schema.definitions,
this.state.schema,
newFormData
);

Expand Down Expand Up @@ -317,6 +317,7 @@ export default class Form extends Component {
ObjectFieldTemplate: this.props.ObjectFieldTemplate,
FieldTemplate: this.props.FieldTemplate,
definitions: this.props.schema.definitions || {},
rootSchema: this.props.schema,
formContext: this.props.formContext || {},
};
}
Expand Down
32 changes: 16 additions & 16 deletions packages/core/src/components/fields/ArrayField.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,12 +270,12 @@ class ArrayField extends Component {

_getNewFormDataRow = () => {
const { schema, registry = getDefaultRegistry() } = this.props;
const { definitions } = registry;
const { rootSchema } = registry;
let itemSchema = schema.items;
if (isFixedItems(schema) && allowAdditionalItems(schema)) {
itemSchema = schema.additionalItems;
}
return getDefaultFormState(itemSchema, undefined, definitions);
return getDefaultFormState(itemSchema, undefined, rootSchema);
};

onAddClick = event => {
Expand Down Expand Up @@ -425,7 +425,7 @@ class ArrayField extends Component {
idSchema,
registry = getDefaultRegistry(),
} = this.props;
const { definitions } = registry;
const { rootSchema } = registry;
if (!schema.hasOwnProperty("items")) {
return (
<UnsupportedField
Expand All @@ -438,10 +438,10 @@ class ArrayField extends Component {
if (isFixedItems(schema)) {
return this.renderFixedArray();
}
if (isFilesArray(schema, uiSchema, definitions)) {
if (isFilesArray(schema, uiSchema, rootSchema)) {
return this.renderFiles();
}
if (isMultiSelect(schema, definitions)) {
if (isMultiSelect(schema, rootSchema)) {
return this.renderMultiSelect();
}
return this.renderNormalArray();
Expand All @@ -465,21 +465,21 @@ class ArrayField extends Component {
rawErrors,
} = this.props;
const title = schema.title === undefined ? name : schema.title;
const { ArrayFieldTemplate, definitions, fields, formContext } = registry;
const { ArrayFieldTemplate, rootSchema, fields, formContext } = registry;
const { TitleField, DescriptionField } = fields;
const itemsSchema = retrieveSchema(schema.items, definitions);
const itemsSchema = retrieveSchema(schema.items, rootSchema);
const formData = keyedToPlainFormData(this.state.keyedFormData);
const arrayProps = {
canAdd: this.canAddItem(formData),
items: this.state.keyedFormData.map((keyedItem, index) => {
const { key, item } = keyedItem;
const itemSchema = retrieveSchema(schema.items, definitions, item);
const itemSchema = retrieveSchema(schema.items, rootSchema, item);
const itemErrorSchema = errorSchema ? errorSchema[index] : undefined;
const itemIdPrefix = idSchema.$id + "_" + index;
const itemIdSchema = toIdSchema(
itemSchema,
itemIdPrefix,
definitions,
rootSchema,
item,
idPrefix
);
Expand Down Expand Up @@ -541,8 +541,8 @@ class ArrayField extends Component {
rawErrors,
} = this.props;
const items = this.props.formData;
const { widgets, definitions, formContext } = registry;
const itemsSchema = retrieveSchema(schema.items, definitions, formData);
const { widgets, rootSchema, formContext } = registry;
const itemsSchema = retrieveSchema(schema.items, rootSchema, formData);
const enumOptions = optionsList(itemsSchema);
const { widget = "select", ...options } = {
...getUiOptions(uiSchema),
Expand Down Expand Up @@ -631,13 +631,13 @@ class ArrayField extends Component {
} = this.props;
const title = schema.title || name;
let items = this.props.formData;
const { ArrayFieldTemplate, definitions, fields, formContext } = registry;
const { ArrayFieldTemplate, rootSchema, fields, formContext } = registry;
const { TitleField } = fields;
const itemSchemas = schema.items.map((item, index) =>
retrieveSchema(item, definitions, formData[index])
retrieveSchema(item, rootSchema, formData[index])
);
const additionalSchema = allowAdditionalItems(schema)
? retrieveSchema(schema.additionalItems, definitions, formData)
? retrieveSchema(schema.additionalItems, rootSchema, formData)
: null;

if (!items || items.length < itemSchemas.length) {
Expand All @@ -657,13 +657,13 @@ class ArrayField extends Component {
const { key, item } = keyedItem;
const additional = index >= itemSchemas.length;
const itemSchema = additional
? retrieveSchema(schema.additionalItems, definitions, item)
? retrieveSchema(schema.additionalItems, rootSchema, item)
: itemSchemas[index];
const itemIdPrefix = idSchema.$id + "_" + index;
const itemIdSchema = toIdSchema(
itemSchema,
itemIdPrefix,
definitions,
rootSchema,
item,
idPrefix
);
Expand Down
10 changes: 5 additions & 5 deletions packages/core/src/components/fields/MultiSchemaField.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ class AnyOfField extends Component {
}

getMatchingOption(formData, options) {
const { definitions } = this.props.registry;
const { rootSchema } = this.props.registry;

let option = getMatchingOption(formData, options, definitions);
let option = getMatchingOption(formData, options, rootSchema);
if (option !== 0) {
return option;
}
Expand All @@ -57,10 +57,10 @@ class AnyOfField extends Component {
onOptionChange = option => {
const selectedOption = parseInt(option, 10);
const { formData, onChange, options, registry } = this.props;
const { definitions } = registry;
const { rootSchema } = registry;
const newOption = retrieveSchema(
options[selectedOption],
definitions,
rootSchema,
formData
);

Expand Down Expand Up @@ -89,7 +89,7 @@ class AnyOfField extends Component {
}
// Call getDefaultFormState to make sure defaults are populated on change.
onChange(
getDefaultFormState(options[selectedOption], newFormData, definitions)
getDefaultFormState(options[selectedOption], newFormData, rootSchema)
);

this.setState({
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/components/fields/ObjectField.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ class ObjectField extends Component {
const { registry = getDefaultRegistry() } = this.props;
const refSchema = retrieveSchema(
{ $ref: schema.additionalProperties["$ref"] },
registry.definitions,
registry.rootSchema,
this.props.formData
);

Expand Down Expand Up @@ -210,9 +210,9 @@ class ObjectField extends Component {
registry = getDefaultRegistry(),
} = this.props;

const { definitions, fields, formContext } = registry;
const { rootSchema, fields, formContext } = registry;
const { SchemaField, TitleField, DescriptionField } = fields;
const schema = retrieveSchema(this.props.schema, definitions, formData);
const schema = retrieveSchema(this.props.schema, rootSchema, formData);

// If this schema has a title defined, but the user has set a new key/label, retain their input.
let title;
Expand Down
10 changes: 5 additions & 5 deletions packages/core/src/components/fields/SchemaField.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,13 +237,13 @@ function SchemaFieldRender(props) {
registry = getDefaultRegistry(),
wasPropertyKeyModified = false,
} = props;
const { definitions, fields, formContext } = registry;
const { rootSchema, fields, formContext } = registry;
const FieldTemplate =
uiSchema["ui:FieldTemplate"] || registry.FieldTemplate || DefaultTemplate;
let idSchema = props.idSchema;
const schema = retrieveSchema(props.schema, definitions, formData);
const schema = retrieveSchema(props.schema, rootSchema, formData);
idSchema = mergeObjects(
toIdSchema(schema, null, definitions, formData, idPrefix),
toIdSchema(schema, null, rootSchema, formData, idPrefix),
idSchema
);
const FieldComponent = getFieldComponent(schema, uiSchema, idSchema, fields);
Expand All @@ -264,8 +264,8 @@ function SchemaFieldRender(props) {
let { label: displayLabel = true } = uiOptions;
if (schema.type === "array") {
displayLabel =
isMultiSelect(schema, definitions) ||
isFilesArray(schema, uiSchema, definitions);
isMultiSelect(schema, rootSchema) ||
isFilesArray(schema, uiSchema, rootSchema);
}
if (schema.type === "object") {
displayLabel = false;
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const registry = PropTypes.shape({
FieldTemplate: PropTypes.elementType,
ObjectFieldTemplate: PropTypes.elementType,
definitions: PropTypes.object.isRequired,
rootSchema: PropTypes.object,
fields: PropTypes.objectOf(PropTypes.elementType).isRequired,
formContext: PropTypes.object.isRequired,
widgets: PropTypes.objectOf(
Expand Down
Loading