Skip to main content
Code Review

Return to Question

Notice removed Draw attention by Community Bot
Bounty Ended with Sᴀᴍ Onᴇᴌᴀ's answer chosen by Community Bot
edited tags
Link
Tweeted twitter.com/StackCodeReview/status/1199387496020361221
Notice added Draw attention by Johan
Bounty Started worth 250 reputation by Johan
Source Link
Johan
  • 631
  • 1
  • 10
  • 27

Recursive component JSON configuration builder

My goal here is to make data driven nested forms in React. I've created a function that points to a form configuration JSON, which can contain both components and references to other configuration files, with their own components. I'm splitting it to separate files to keep things DRY and to get an easier overview (hierarchy can be about 5 levels deep, one JSON file would be rather hard to overview).

I've introduced $ref to be able to point to another JSON configuration and $extends for inheritance (configurations can differ dependings on context but have common properties). args will be spread out as props to the component.

config-builder.js

function createConfiguration(configuration) {
 return _.reduce(configuration.components, (result, data) => {
 // if it's a reference to another configuration - fetch it - otherwise use as is
 const component = data.$ref ? getComponentByReference(data) : data
 return addResult(result, component.key, component.components ? { ...component, components: createConfiguration(component) } : component)
 }, {})
}
function getComponentByReference(data) {
 const component = _.merge({}, configMap[data.$ref], data)
 const result = component.$extends ? _.merge({}, configMap[component.$extends], component) : component
 // clear internal values like $ref, $extends
 return _.omitBy(result, (value, key) => _.startsWith(key, '$'))
}
// use an array to wrap results to handle multiple keys of the same type on same level
function addResult(result, key, data) {
 if(!result[key]) {
 result[key] = [data]
 } else {
 result[key].push(data)
 }
 return result
}

foo.json

{
 "key": "foo",
 "type": "DefaultContainer",
 "components": [
 { "key": "name", "type": "Text" },
 { "$ref": "Bar" }
 ]
}

bar.json

{
 "key": "bar",
 "type": "DefaultContainer",
 "components": [
 { "key": "id", "type": "DropDown", "args": { options: [] } }
 ]
}

https://jsfiddle.net/wkmrp4gc/

lang-js

AltStyle によって変換されたページ (->オリジナル) /