Ever wondered how to create components (textboxes, dropdowns, textareas, etc) from a JSON file?
Note: I'm using Hooks, so no class components
Here's how I do it:
So I have an external json file, could be named data.json
:
{
"fields": [
{
"id": "post-title",
"name": "Post Title",
"fieldType": "text"
},
{
"id": "quantity",
"name": "Quantity",
"fieldType": "number"
},
{
"id": "expiry",
"name": "Expiry",
"fieldType": "date"
},
{
"id": "product-details",
"name": "Product Details",
"fieldType": "textarea"
},
{
"id": "product-details-wysiwyg",
"name": "Product Details",
"fieldType": "wysiwyg"
},
{
"id": "type",
"name": "Type",
"fieldType": "dropdown",
"options": [
{
"value": "basic",
"text": "Basic"
},
{
"value": "pro",
"text": "Pro"
},
{
"value": "premium",
"text": "Premium"
}
]
}
]
}
Inside you return function:
{
data.fields.map((a, i) =>
<div key={i}>
{ renderComponents(a) }
</div>
)
}
const renderComponents = (field) => {
switch (field.fieldType) {
case 'text' :
return <>
<label className="label">{field.name}</label>
<input type="text" placeholder="Type here..." className="textbox"></input>
<DropdownSidebar id={field.id} name={field.name}
values={state.triggerFields}
handleChangeDropdown={changeByDropdown} />
</>
case 'number' :
return <>
<label className="label">{field.name}</label>
<input type="number" defaultValue={1} className="textbox"
></input>
</>
case 'date' :
return <>
<label className="label">{field.name}</label>
<DatePicker
onChange={(date) => setDate(date, field.id)}
value={stateDate}
/>
</>
case 'textarea' :
return <>
<label className="label">{field.name}</label>
<textarea maxLength={100} rows={5} cols={30} draggable={false}
></textarea>
</>
case 'dropdown' :
return <>
<Dropdown isOpen={dropdownOpen} toggle={toggleDropdown}>
<DropdownToggle caret>
{field.name}
</DropdownToggle>
<DropdownMenu>
{
field.options.map((o, i) =>
<DropdownItem key={i} value={o.value} onClick={() => onChangeDropdown(o.value, o.text, field.id)}>{o.text}</DropdownItem>
)
}
</DropdownMenu>
</Dropdown>
</>
case 'wysiwyg' :
return <>
<label className="label">{field.name}</label>
<FroalaEditorComponent
tag='textarea'
config={{
placeholderText: 'Edit Your Content Here!',
charCounterCount: false,
toolbarInline: false,
toolbarButtons: ['bold', 'italic', 'underline', 'strikeThrough',
'subscript', 'superscript', '-', 'paragraphFormat', 'align',
'formatOL', 'formatUL', 'indent', 'outdent', '-', 'insertImage',
'insertLink', 'insertFile', 'insertVideo', 'undo', 'redo', 'textColor', 'inlineStyle'],
toolbarVisibleWithoutSelection: true,
inlineStyles: {
'Big Red': 'font-size: 20px; color: red;',
'Small Blue': 'font-size: 14px; color: blue;'
}
}}
model={model}
onModelChange={(model) => saveEditor(model, field.id)}
/>
</>
default :
return <></>
}
}
Some notes:
For some components there I use these:
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'
import DatePicker from 'react-date-picker'
import FroalaEditorComponent from 'react-froala-wysiwyg'
This solution only solves components that are used once. Next time, I will tackle how to use components like dropdowns that toggles that appear more than once in your component.
Cheers,
FM
Top comments (0)