1

Hi can anyone help me how to create a dynamic html form in reactjs using the json data form local. I have the below json format which contains the form details for 3 fields.

{
"sampleData":
    [{"indexId":"1",
    "abrvIndexName":"firstname",
    "indexDesc":"First Name",
    "htmlControlType":"textbox",
    "cssClassName":"form-control"},
    {"indexId":"2",
    "abrvIndexName":"lastname",
    "indexDesc":"Last Name",
    "htmlControlType":"textbox",
    "cssClassName":"form-control"}
    {"indexId":"3",
    "abrvIndexName":"address",
    "indexDesc":"Address",
    "htmlControlType":"textarea",
    "cssClassName":"form-control"}
    ]
}

and below is the react component for the form which I need to create dynamically, as of now i have 3 fields which are static and need to dynamically put from the above json.

var React = require('react');
var ReactDOM = require('react-dom');

var Menu = React.createClass({

render: function () {
    return (

        <div className="container">
            <br/>
            <div className="panel panel-primary">
                <div className="panel-heading">Sample Dynamic Form using json data</div>
                    <div className="panel-body">
                            <form className="form-horizontal">
                                <div className="form-group">
                                    <label for="firstname" className="col-sm-2 control-label">First Name</label>
                                        <div className="col-sm-8">
                                            <input type="text" className="form-control" id="firstname" placeholder=""/>
                                        </div>
                                </div>
                                <div className="form-group">
                                    <label for="lastname" className="col-sm-2 control-label">Last Name</label>
                                        <div className="col-sm-8">
                                            <input type="text" className="form-control" id="lastname" placeholder=""/>
                                        </div>
                                </div>
                                <div className="form-group">
                                    <label for="address" className="col-sm-2 control-label">Address</label>
                                        <div className="col-sm-8">
                                            <textarea type="text" className="form-control" id="address" placeholder=""/>
                                        </div>
                                </div>

                                <div className="col-md-10 text-right"> 
                                    <button type="button" className="btn btn-primary">Submit</button>
                                </div>

                            </form>


                    </div>      
            </div>
        </div>
    )
}

});
module.exports = Menu

I'm new to react so,Can anyone help me how to do that in reactjs?

3
  • Do you need the code that retrieves the JSON or just code that will render the JSON? Commented Feb 22, 2017 at 9:38
  • Not sure what you mean, are you just wanting to use JSON data as variables in the form? Like the JSON is a property of the form component? Commented Feb 22, 2017 at 9:42
  • @paqash I want to replace the static html controls to a dynamic form using the json data. I want to know how to do that Commented Feb 22, 2017 at 10:05

3 Answers 3

3

Once you have the JSON data, you can map over it and create the layout dynamically, something like that:

// You can `require` a local file or `fetch` it from somewhere
// For the demo purpose, I just included it here.
const JSON = [  
    {  
        "indexId":"1",
        "abrvIndexName":"firstname",
        "indexDesc":"First Name",
        "htmlControlType":"textbox",
        "cssClassName":"form-control"
    },
    {  
        "indexId":"2",
        "abrvIndexName":"lastname",
        "indexDesc":"Last Name",
        "htmlControlType":"textbox",
        "cssClassName":"form-control"
    },
    {  
        "indexId":"3",
        "abrvIndexName":"address",
        "indexDesc":"Address",
        "htmlControlType":"textarea",
        "cssClassName":"form-control"
}];

var Menu = React.createClass({

    renderFormGroups: function() {
        // Assume your data is fetched/available
        const data = JSON;

        // Here we build the form's groups elements dynamically
        return data.map(group => {
            return <div className="form-group">

                <label for={group.abrvIndexName}
                       className={"col-sm-2 " + group.cssClassName}>
                    {group.indexDesc}
                </label>

                 <div className="col-sm-8">
                      <input type="text"
                             className="form-control"
                             id={group.abrvIndexName}
                             placeholder="" />
                  </div>

            </div>
        });
    },

    render: function () {
        return (
            <div className="container">
                <div className="panel panel-primary">
                    <div className="panel-heading">Sample Dynamic Form using json data</div>
                    <div className="panel-body">
                        <form className="form-horizontal">
                            {this.renderFormGroups()}
                        </form>
                    </div>      
                </div>
            </div>
        )
    }
});

ReactDOM.render(<Menu />, document.getElementById('container'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container">
    <!-- This element's contents will be replaced with your component. -->
</div>

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

7 Comments

How we can import the json into react component? say my json is in data folder, app/data/samplejson.json, How this will be imported?
var data = require(app/data/samplejson');. More details here: stackoverflow.com/questions/37649695/…
@knbibin I've added a working code sample, you can play with it. You're free to import/fetch the JSON data from everywhere you want.
Thanks for the example in detail :-) working fine :-)
Can you help me on the previous question?
|
0

If you are using Formik and class component the please see the following sloution:

let say I have following json on every attribute need to create one field in the create product form:

{
  "name": "keychoda",
  "attributes": {
    "General_Attributes": [
      {
        "name": "Product Type",
        "code": "product_code",
        "mandatory": "1",
        "type": "text",
        "max_length": "30",
        "default_value": "cellularphonecase",
        "Hint": "Enter Feed Product Type here",
        "AmazonExportHeader": "feed_product_type",
        "ShopifyExportHeader": "Type",
        "EbayExportHeader": "*Category",
        "GoogleExportHeader": "Google Shopping / Google Product Category"
      },
      {
        "name": "Shop Keeping Unit",
        "code": "shop_keeping_unit",
        "mandatory": "1",
        "type": "text",
        "max_length": "12",
        "default_value": "",
        "Hint": "Enter Product SKU Number",
        "AmazonExportHeader": "item_sku",
        "ShopifyExportHeader": "Variant SKU",
        "EbayExportHeader": "CustomLabel",
        "GoogleExportHeader": ""
      },
      {
        "name": "Brand Name",
        "code": "brand_name",
        "mandatory": "1",
        "type": "dropdown",
        "options": [
          "Oxnoble Group",
          "Membrane"
        ],
        "max_length": "",
        "default_value": "Oxnoble Group",
        "Hint": "Select Brand Name",
        "AmazonExportHeader": "item_sku",
        "ShopifyExportHeader": "Vendor",
        "EbayExportHeader": "*C:Brand",
        "GoogleExportHeader": ""
      },
      {
        "name": "Barcode",
        "code": "barcode",
        "mandatory": "1",
        "type": "number",
        "min_length": "13",
        "max_length": "13",
        "default_value": "",
        "Hint": "Enter EAN / GTIN HERE",
        "AmazonExportHeader": "external_product_id",
        "ShopifyExportHeader": "Variant Barcode",
        "EbayExportHeader": "Product:EAN",
        "GoogleExportHeader": ""
      },
      {
        "name": "Barcode Type",
        "code": "barcode_type",
        "mandatory": "1",
        "type": "dropdown",
        "options": [
          "GTIN",
          "EAN",
          "UPC",
          "ASIN"
        ],
        "min_length": "",
        "max_length": "",
        "default_value": "",
        "Hint": "Select Barcode Type",
        "AmazonExportHeader": "external_product_id_type",
        "ShopifyExportHeader": "",
        "EbayExportHeader": "C:Type",
        "GoogleExportHeader": ""
      },
      {
        "name": "condition_type",
        "code": "condition_type",
        "mandatory": "1",
        "type": "dropdown",
        "options": [
          "New",
          "Used - Acceptable",
          "Used - Good",
          "Used - Like New",
          "Used - Very Good"
        ],
        "min_length": "",
        "max_length": "",
        "default_value": "",
        "Hint": "condition_type",
        "AmazonExportHeader": "condition_type",
        "ShopifyExportHeader": "",
        "EbayExportHeader": "",
        "GoogleExportHeader": ""
      },
      {
        "name": "condition_note",
        "code": "condition_note",
        "mandatory": "1",
        "type": "text",
        "min_length": "",
        "max_length": "",
        "default_value": "",
        "Hint": "condition_note",
        "AmazonExportHeader": "condition_note",
        "ShopifyExportHeader": "",
        "EbayExportHeader": "",
        "GoogleExportHeader": ""
      }
    ],
    "Variation_Attributes": [
      
    ],
    "Dimentions_Attributes": [
      {
        "name": "image1",
        "code": "image1",
        "mandatory": "1",
        "type": "file",
        "default_value": "",
        "Hint": "condition_type",
        "AmazonExportHeader": "condition_type",
        "ShopifyExportHeader": "",
        "EbayExportHeader": "",
        "GoogleExportHeader": ""
      },
            {
        "name": "image2",
        "code": "image2",
        "mandatory": "1",
        "type": "file",
        "default_value": "",
        "Hint": "condition_type",
        "AmazonExportHeader": "condition_type",
        "ShopifyExportHeader": "",
        "EbayExportHeader": "",
        "GoogleExportHeader": ""
      },
      {
        "name": "Short Description",
        "code": "short_description",
        "mandatory": "0",
        "type": "textarea",
        "min_length": "",
        "max_length": "",
        "default_value": "",
        "Hint": "condition_note",
        "AmazonExportHeader": "condition_note",
        "ShopifyExportHeader": "",
        "EbayExportHeader": "",
        "GoogleExportHeader": ""
      }
    ]
  }
}

createproduct.js

import React from 'react';
import { connect } from 'react-redux';
import { axiosInstance }  from "../../network/apis/index";
import { END_POINTS } from "../../utils/Constants";
import { Link } from "react-router-dom";
import DashboardTemplate from '../../components/DashboardTemplate';
import AttributeSet from '../../components/AttributeSet';
import { Formik, Form, Field } from 'formik';
import { ToastContainer, toast } from 'react-toastify';
import { Btn } from '../../components/Controls/Button/Button';


class CreateProduct extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            redirect: false,
            catId: "",
            attributes : {},
            initialvalues: {}
        }
    }

    componentDidMount() {
        const params = new URLSearchParams(window.location.search);
        
        let cat;
        this.props.Categories.some( (item) => {
            return (item._id === params.get('catid')) ? cat = item : "";
        });

        let iniValues = {};
        const obj = Object.values(cat.attributes);
        
        obj.map( entries => {
            
            if(entries.length > 0) {
                entries.map(entry => {
                    let name = "\""+ entry.code + "\"";
                    if(entry.type == "file") {
                        iniValues[name] = null;
                    } else {
                        iniValues[name] = "";
                    }
                    
                })
            }
            
        });

        this.setState(
            {
                catId: cat._id,
                attributes: cat.attributes,
                initialvalues: iniValues
            }
        );
    }

    handleProduct = async (values) => {
        console.log(values);

        let newProductPayload = {
            name: "",
            category_id: "",
            attributes: {}
        }
        
        let combined = [];
        Object.entries(this.state.attributes).map( attributes => {
            combined = combined.concat(...attributes[1]);
        });

        //console.log(combined);
        
        this.buildProductPayload(values, newProductPayload, combined);
        console.log(newProductPayload);

        let url = END_POINTS.createProduct;

        try {
            const response = await axiosInstance.post(url,newProductPayload);
            console.log(response);
            toast.success("Product saved");
            this.setState({redirect: true})
        } catch (error) {
            console.log(error);
            toast.error("Unable to save Product");
        }


    }

    buildProductPayload(values, newProductPayload, combined) {
        Object.entries(values).map((value) => {
            if (value[0] == "name") {
                newProductPayload.name = value[1];
                newProductPayload.category_id = this.state.catId;
            } else {
                for (let i = 0; i < combined.length; i++) {
                    if (combined[i].code == value[0]) {
                        newProductPayload.attributes[value[0]] = { value: value[1], AmazonExportHeader: combined[i].AmazonExportHeader, EbayExportHeader: combined[i].EbayExportHeader, GoogleExportHeader: combined[i].GoogleExportHeader, ShopifyExportHeader: combined[i].ShopifyExportHeader };
                        break;
                    }
                }
            }
        });
    }

    render() {
        console.log(this.state.initialvalues,this.state.attributes);
        return (
            <DashboardTemplate>
                <div className="content_header_bar">
                    <div className="content_header_bar_child content_bar_left">
                        <h3>Create Product</h3>
                    </div>
                    <div className="content_header_bar_child content_bar_right">
                        <Link to="/category-select" className="gray-button">Back</Link>
                    </div>
                </div>

                <div className="create_product_main">

                    <div className="create_product_inner">

                    <ToastContainer />

                        <Formik
                            initialValues={ this.state.initialvalues }
                            onSubmit={(values, { setSubmitting }) => {
                                setTimeout(() => {
                                setSubmitting(false);
                                this.handleProduct(values);
                                }, 500);
                            }}
                        >

                            {({ submitForm, isSubmitting, setFieldValue, values }) => (
                            <Form>

                            <div className="create_product_item">
                                <AttributeSet title="Product Name" fieldname="name" type="text" required="1" />
                            </div>

                                { Object.keys(this.state.attributes).map((attribute,i) => {
                                    
                                    return(
                                        <div key={i} className="create_product_item">
                                            <div className="attribute_set_name">{ attribute.replace("_", " ") }</div>
                                                {this.state.attributes[attribute].length > 0 && this.state.attributes[attribute].map((entry,index) => {
                                                    return(
                                                        <AttributeSet key={index} title={ entry.name } fieldname={entry.code} type={ entry.type } options={entry.options} required={entry.mandatory} sfv={setFieldValue} values={values} />
                                                    )
                                                })}
                                        </div>
                                    )
                                })}

                                <Btn className="create_button create_product_button" handleClick={submitForm} text="Create" />
                            </Form>
                            )}
                        </Formik>
                    </div>
                </div>


            </DashboardTemplate>
        )
    }
}

const mapStateToProps = ({Categories}) => {
    return {
        Categories: Categories
    }
}

export default connect(mapStateToProps,null)(CreateProduct);

and child component which is responsible to return dynamic form is Attributeset.js

import React, {Component} from "react";
import { Field } from 'formik';
import PlaceholderImage from '../../assets/images/image-placeholder.jpg';


class AttributeSet extends Component {
    constructor(props) {
        super(props)
        this.state = {
            file: PlaceholderImage
        }
        this.handleChange = this.handleChange.bind(this)
    }
    handleChange(event) {
        //console.log(this.props.sfv);
        const reader = new FileReader();
        reader.onload = () => {
            if (reader.readyState === 2) {
                this.setState({file: reader.result})
            }
        } 
        reader.readAsDataURL(event.target.files[0]);
        //console.log(this.props.values);
        this.props.sfv(this.props.fieldname, event.currentTarget.files[0]);
        //console.log(this.props.values);
    }
    render() {
        let column = 'four_column';
        var inputValue = '';
        switch (this.props.type) {
            case 'textarea':
                column = 'full_width';
                inputValue =  <Field
                                className="attribute_input"
                                name={this.props.fieldname}
                                type="textarea"
                                rows="4" cols="50"
                                placeholder={
                                    this.props.title
                                }
                                />
                break;
                case 'file':
                    inputValue = <>
                    <img src={
                            this.state.file
                        }
                        alt=""
                        className="image_preview"/>
                <input
                className="attribute_input"
                name={this.props.fieldname}
                type="file"
                onChange={this.handleChange}
                />
                </>
                    break;

                case 'dropdown':
                    inputValue = <Field 
                    as="select" 
                    name={this.props.fieldname}
                    className="attribute_input"
                    >
                        <option value=""></option>
                        { this.props.options && this.props.options.map( (option,i) => {
                            return (
                            <option key={i} value={ option }>{ option }</option>
                            );
                        })}
                    </Field>

                    break;

            default:
                inputValue = <Field
                className="attribute_input"
                name={this.props.fieldname}
                type="text"
                placeholder={
                    this.props.title
                }
                />
                break;
        }

        return (
            <div className={
                `attibute_set ${column}`
            }>
                <div className="attibute_name">
                    {
                    this.props.title
                }</div>
                <div className="attribute_input">

                    {inputValue}

                    <div className="attribute_field_error"></div>
                </div>
            </div>
        );
    }
}

export default AttributeSet;

Comments

-2

we have To File One data.json and Other is component.js file first Import The data from json file and then use That data to Create custom form

data.json  


[
   {
      UILabel : "Name",
      type : "text"(put any Type)
      attribute : {
             name : "name",
             minLength : 10,
             MaxLength : 20
             put all The Property Related to input type text
         }
   },

   {
        UILabel : "Gender",
        type : radio,
         attributes: {
                 Put all The attributes Related to gender
                 If you Put Value attribute and if you have type is date,time 
                 and  week then put default value in Proper Formate. or else it will 
                 through an error..
           }
   }
]

import React from 'react';
import fields from './data.json;

const customComponent = () => {
        return (
           fields.map(field => {
                <div className="input-box">
                     <input 
                        type={field.type}
                        name={field.atttibute.name}
                        className={field.attribute.className}
                        max={field.attribute.max
                        maxlength={field.attribute.maxlength}
                        min={field.attribute.min
                        minlength={field.attribute.minlength}
                        src={field.attribute.src}
                        ... Put all The jsx Props ..
                     />
                </div> 
            })
       )
}

[Here in Data file If i Put "type":"text" then it will consider
 only type text Related Props and will Ignore Other Porps like src, width and so on...]

[Here in Data file If i Put "type":"text" then it will consider only type text Related Props and will Ignore Other Porps like src, width and so on...]

Comments

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.