react-jsonschema-form icon indicating copy to clipboard operation
react-jsonschema-form copied to clipboard

Using getDefaultFormState with 'default' and 'const' values to override current formData

Open Bonfims opened this issue 1 year ago • 2 comments

Prerequisites

What theme are you using?

core

What is your question?

Hello!

I was trying to achieve an override-like functionality with getDefaultFormState from the utils. For example:

const { validator } = require("...");
let newSchema = { 
  type: "object", 
  properties: { 
    field: {  
      type: "string", 
      default: "456", 
      const: "456" 
    }
  }
};
let currentFormData = { field: 123 };
let formData = getDefaultFormState(validator, newSchema, currentFormData);
// This will return { field: 123 }

I was expecting it to return { field: "456" }, assuming that the schema's property declarations (const, default and readOnly) would override the current value.

Is there a way to achieve this?

Bonfims avatar Jul 15 '24 21:07 Bonfims

Hey,

I endeed up with a combination of getDefaultFormState, sanitizeDataForNewSchema and mergeDefaultsWithFormData:

const { getDefaultFormState, sanitizeDataForNewSchema, mergeDefaultsWithFormData } = require("...");
const { validator } = require("...");

let oldSchema = { 
  type: "object", 
  properties: { 
    field: {  
      type: "string", 
      default: "123"
    }
  }
};

// getting a form data from schema above
let currentFormData = getDefaultFormState(validator, oldSchema, { test: "hello world!" });
// -> { test: "hello world!", field: "123" }

let newSchema = { 
  type: "object", 
  properties: { 
    field: {  
      type: "string", 
      default: "456", 
      const: "456" 
    }
  }
};

// getting default form data value from newSchema
let newFormData = getDefaultFormState(validator, newSchema, {});
// -> { field: "456" }


// so, i want get a override-like that would be -> { test: "hello world!", field: "456" }

// to achive this, i used `sanitizeDataForNewSchema` to clean currentFormData
let sanitized = sanitizeDataForNewSchema(validator, {}, newSchema, oldSchema, currentFormData);
// -> { test: "hello world!", field: undefined }

// now i can merge it with `mergeDefaultsWithFormData`
let finalFormData = mergeDefaultsWithFormData(sanitized, newFormData);
// -> { test: "hello world!", field: "456" }

For now, i will try for this way, let me know if a missing something, thank you!

Bonfims avatar Jul 16 '24 02:07 Bonfims

@Bonfims as you discovered, getDefaultFormState won't overwrite data that has already been filled in. In Form.tsx, we call it regularly because the 'default state' may change dynamically (e.g. if the user is using oneOf/anyOf or if/then/else.

You might have trouble using sanitizeDataForNewSchema in this way since it won't replace default fields where the formData value does not match the oldSchema default value. Depending on your use case, you may need to dynamically manipulate the data or dynamically create a new 'old schema'. You can take a look at the sanitizeDataForNewSchema source, which describes the process to see if it makes sense for your use case.

In any case, clever solution, hopefully it works how you need it to!

nickgros avatar Jul 19 '24 19:07 nickgros

This issue has been automatically marked as possibly close because it has not had recent activity. It will be closed if no further activity occurs. Please leave a comment if this is still an issue for you. Thank you.

stale[bot] avatar Oct 18 '25 20:10 stale[bot]