JSFiddle - React, Tailwind, and code Playground
HTML
<div id="app"></div>
CSS
body {
background: #333333;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #ffffee;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
border: 1px solid black;
padding:5px;
background-color:#ffffdd;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
.done {
color: rgba(0, 0, 0, 0.3);
text-decoration: line-through;
}
input {
margin-right: 5px;
}
React
const ModuleElement = (props) => {
const [fieldName, setFieldName] = React.useState(props.config.fieldName);
const key = props.index;
return (
<React.Fragment>
<div className="form-group row" key={`block_${key}`}>
<input
key={`block_input_${key}`}
type="text"
className="form-control"
id={`fieldname_${key}`}
name="fieldName"
onChange={(e)=>{
setFieldName(e.target.value);
props.updateBlock(key, {fieldName:e.target.value, required:true})
}}
placeholder="Field Name"
defaultValue={fieldName}
/>
</div>
</React.Fragment>
);
};
const ModuleBuilder = () => {
const emptyBlock = {
fieldName: "",
required: true,
};
const [blocks, setBlocks] = React.useState([emptyBlock]);
const updateBlock = (key, data) => {
console.log(`i was asked to update element #${key}`);
console.log("this is data", data);
let copyOfBlocks = blocks;
copyOfBlocks[key] = data;
setBlocks([...copyOfBlocks]);
console.log("this is blocks", blocks);
};
const add1Block = () => {
setBlocks([...blocks, {fieldName:"", required:true}]);
};
const renderBlockFormElements = () => {
return blocks.map((value, index) => {
return (
<li key={index}>
<b>Subcomponent with Index #{index}</b>
<ModuleElement
index={index}
config={value}
updateBlock={updateBlock}
/>
</li>
);
});
};
return (
<div>
<h2>Now it works </h2>
<form>
<ul className="list-group">{renderBlockFormElements()}</ul>
<button type="button" onClick={add1Block}>
Add another field
</button>
</form>
<br></br>
<h2>This is the state:</h2>
{blocks.map((value, index) => (
<p key={`checkup_${index}`}>
<span>{index}: </span>
...