diff --git a/src/components/fields/StringField.js b/src/components/fields/StringField.js index 31dc31580b..6f583ba9be 100644 --- a/src/components/fields/StringField.js +++ b/src/components/fields/StringField.js @@ -7,6 +7,7 @@ import { isSelect, optionsList, getDefaultRegistry, + hasWidget, } from "../../utils"; function StringField(props) { @@ -29,7 +30,10 @@ function StringField(props) { const { title, format } = schema; const { widgets, formContext } = registry; const enumOptions = isSelect(schema) && optionsList(schema); - const defaultWidget = format || (enumOptions ? "select" : "text"); + let defaultWidget = enumOptions ? "select" : "text"; + if (format && hasWidget(schema, format, widgets)) { + defaultWidget = format; + } const { widget = defaultWidget, placeholder = "", ...options } = getUiOptions( uiSchema ); diff --git a/src/utils.js b/src/utils.js index a4b2c8af15..8088bc5fa3 100644 --- a/src/utils.js +++ b/src/utils.js @@ -123,6 +123,22 @@ export function getWidget(schema, widget, registeredWidgets = {}) { throw new Error(`No widget "${widget}" for type "${type}"`); } +export function hasWidget(schema, widget, registeredWidgets = {}) { + try { + getWidget(schema, widget, registeredWidgets); + return true; + } catch (e) { + if ( + e.message && + (e.message.startsWith("No widget") || + e.message.startsWith("Unsupported widget")) + ) { + return false; + } + throw e; + } +} + function computeDefaults(schema, parentDefaults, definitions = {}) { // Compute the defaults recursively: give highest priority to deepest nodes. let defaults = parentDefaults; diff --git a/src/validate.js b/src/validate.js index f20afc79e2..526bceef93 100644 --- a/src/validate.js +++ b/src/validate.js @@ -14,6 +14,7 @@ function createAjvInstance() { allErrors: true, multipleOfPrecision: 8, schemaId: "auto", + unknownFormats: "ignore", }); // add custom formats @@ -215,13 +216,7 @@ export default function validateFormData( typeof validationError.message === "string" && validationError.message.includes("no schema with key or ref "); - const unknownFormat = - validationError && - validationError.message && - typeof validationError.message === "string" && - validationError.message.includes("unknown format"); - - if (noProperMetaSchema || unknownFormat) { + if (noProperMetaSchema) { errors = [ ...errors, { @@ -235,7 +230,7 @@ export default function validateFormData( let errorSchema = toErrorSchema(errors); - if (noProperMetaSchema || unknownFormat) { + if (noProperMetaSchema) { errorSchema = { ...errorSchema, ...{ diff --git a/test/Form_test.js b/test/Form_test.js index 388ed1e665..45cc89e7e7 100644 --- a/test/Form_test.js +++ b/test/Form_test.js @@ -1984,13 +1984,13 @@ describe("Form", () => { const formProps = { liveValidate: true, formData: { - areaCode: 123, + areaCode: "123455", }, schema: { type: "object", properties: { areaCode: { - type: "number", + type: "string", format: "area-code", }, }, @@ -2007,22 +2007,20 @@ describe("Form", () => { const { comp } = createFormComponent(formProps); - expect(comp.state.errorSchema).eql({ - $schema: { - __errors: [ - 'unknown format "area-code" is used in schema at path "#/properties/areaCode"', - ], - }, - }); + expect(comp.state.errorSchema).eql({}); setProps(comp, { ...formProps, customFormats: { - "area-code": /\d{3}/, + "area-code": /^\d{3}$/, }, }); - expect(comp.state.errorSchema).eql({}); + expect(comp.state.errorSchema).eql({ + areaCode: { + __errors: ['should match format "area-code"'], + }, + }); }); }); diff --git a/test/validate_test.js b/test/validate_test.js index 3ea9d40fef..696ed06311 100644 --- a/test/validate_test.js +++ b/test/validate_test.js @@ -174,15 +174,9 @@ describe("Validation", () => { }, }; - it("should return a validation error if unknown string format is used", () => { + it("should not return a validation error if unknown string format is used", () => { const result = validateFormData({ phone: "800.555.2368" }, schema); - const errMessage = - 'unknown format "phone-us" is used in schema at path "#/properties/phone"'; - - expect(result.errors[0].stack).include(errMessage); - expect(result.errorSchema).to.eql({ - $schema: { __errors: [errMessage] }, - }); + expect(result.errors.length).eql(0); }); it("should return a validation error about formData", () => {