0

I have following JSON string from which I need to dynamically create DOM of the form:

    {
        "formData": [{
            "inputType": "text",
            "type": "string",
            "min": 10,
            "label": "Enter Name:",
            "objectId": "test1"
        }],
        "gridLayout": {
            "rows": [
                {
                    "column": [
                        {
                            "width": "4",
                            "id": "test1"
                        }
                    ]
                }
            ]
        }
    }

from the gridLayout object, I wish to create bootstrap style grid. For instance, first rowobject of the JSON's "rows" has 1 column in the columns object with width of 4. Thus, the layout for that row should be

<div class="row">
    <div class="col-md-4" id="test1">

    </div>
</div>

Later, using formData object of JSON, TextBox component should be appended to grid layout like so:

<div class="row">
    <div class="col-md-4" id="test1">
        <TextBox />
    </div>
</div>

For now, I have written code to display the TextBox component as it is without the grid layout in following way.

Form.jsx:

class Form extends React.Component {
getComponent = (formObj, index) => {
    let returnString;
    if (formObj.inputType === 'text') {
        returnString = (<TextBox key={index} />);
    }

    return returnString;
}


render() {
    let formData = JSON.parse(this.getData()).formData;
    return (
        <React.Fragment> {formData.map((o, index) => this.getComponent(o, index))} </React.Fragment>
    );
}
}

Thus now, how do I dynamically create the Grid Layout and insert the TextBox component in it?

2
  • On what basis does the TextBox end up in a particular column? You have duplicate ids, so it's difficult to find the correct column. Commented Mar 19, 2019 at 2:44
  • @MaazSyedAdeeb: Sorry about that, I have updated the JSON to contain only one row object. Actually, in the original case there were two TextBox components for two row objects. This one's shorter version of the json. Commented Mar 19, 2019 at 2:50

1 Answer 1

1

A solution can be achieved by using a combination of array methods. Use Array#map to render your gridLayout divs as necessary. Use Array#find to find the props of the correct TextBox from formData.

I've simplified formData, but added more rows and columns to give you a complete picture.

const data = {
  "formData": [{
    "label": "Enter Name:",
    "objectId": "test1"
  }, {
    "label": "Enter Address:",
    "objectId": "test2"
  }, {
    "label": "Enter Number:",
    "objectId": "test3"
  }, {
    "label": "Enter Something:",
    "objectId": "test4"
  }],
  "gridLayout": {
    "rows": [{
        "column": [{
          "width": "4",
          "id": "test1"
        }, {
          "width": "4",
          "id": "test2"
        }]
      },
      {
        "column": [{
          "width": "6",
          "id": "test3"
        }, {
          "width": "6",
          "id": "test4"
        }]
      }
    ]
  }
}

const TextBox = ({ label }) => (
  <React.Fragment>
    <label>{label}</label>
  </React.Fragment>
);

const Form = ({ data: { formData, gridLayout } }) => {
  return gridLayout.rows.map(row => {
    return (
      <div class="row">
        {row.column.map(col => {
          const textBoxProps = formData.find(data => data.objectId === col.id);
          // REPLACE col- with col-md-. Done here to demonstrate layout in small snippet output area
          return (
            <div className={`col-${col.width} borderedCol`}>
              <TextBox {...textBoxProps} />
            </div>
          );
        })}
      </div>
    );
  });
};

ReactDOM.render(<Form data={data} />, document.getElementById("app"));
/* ONLY for demo purposes */
.borderedCol {
  border: 1px solid;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Sign up to request clarification or add additional context in comments.

6 Comments

Sure that works! Thanks. But can I separate grid creation code from component insertion code? Something like, in the grid creation I will leave the placeholders as id and in component insertion, I will insert the component as per the id.
You can separate it if you like. But there needs to be a function call which will return what you need to render there.
That's quite obvious. But my question is how do you do that in Reactjs? How do you create plain HTML with place holders and later refer those placeholders to add children in them?
You can replace <TextBox /> with say {getTextBox()}. I don't understand your second question as such. What do you mean by later? You have to return a tree of JSX elements from the render call and React just creates/manages the HTML for you. If this is not answering your question, then please edit the question to explain what problem you're facing or ask a new question.
Also, you could read about JSX. That's what you return from a render call in React.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.