如何在React中以表单的形式基于json动态生成组件?

时间:2019-03-14 04:48:55

标签: javascript reactjs dynamic ui-automation dynamicform

我创建了一个包含form.json文件的简单应用程序:

{
"items": [
    {
        "componentType": "NameBox",
        "lable": "Name",
        "properties": {
            "type": "text",
            "minLength": 3,
            "description": "Enter Your Name"
        }
    },
    {
        "componenetType": "UserNameBox",
        "lable": "Username",
        "properties": {
            "type": "text",
            "minLength": 4,
            "maxLength": 8,
            "description": "Enter user name"
        }
    },
    {
        "componenetType": "EmailBox",
        "lable": "Email",
        "properties": {
            "type": "text",
            "pattern": "^\\S+@\\S+$",
            "description": "Enter email"
        }
    },
    {
        "componenetType": "PasswordBox",
        "lable": "Password",
        "properties": {
            "type": "password",
            "minLength": 8,
            "maxLength": 16,
            "pattern": "^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{6,16}$",
            "description": "Enter password"
        }
    },
    {
        "componentType": "CountryDropDown",
        "lable": "Country",
        "properties": {
            "type": "dropDown",
            "enum": [
                "AUS",
                "IN",
                "JP",
                "US",
                "RU",
                "Other"
            ]
        }
    },
    {
        "componenetType": "RadioButton",
        "lable": "Gender",
        "properties": {

                "type": "radio",
                "anyOf": 
                    {
                        "type": "radio",
                        "key": "radios",
                        "enum": [
                            {
                                "value":"male",
                                "name":"Male"
                            },
                            {
                                "value":"female",
                                "name":"Female"
                            }
                        ]
                    }




        }
    },
    {
        "componenetType":"CheckBox",
        "lable":"Language",
        "properties": {

                "type": "checkBox",
                "items": {
                    "type": "string",
                    "enum": [
                        "English",
                        "Spanish",
                        "Japanese",
                        "French",
                        "Hindi"
                    ]
                }
            }

    },
    {
        "componenetType":"SubmitButton",
        "lable":"Submit",
        "properties": {

                "type": "submit",
                "title":"Submit"
            }

    }
  ]
}

根据此json文件,我希望自动生成组件。我的意思是,如果添加组件,则应用程序必须添加该组件,如果删除该应用程序,则必须自动删除该组件。

这是App.js文件:

import React, { Component } from 'react';
import './App.css';
import {InputBox} from './InputBox';
import {dataService} from './dataService';
import {RadioButton} from './RadioButton';
import {DropDown} from './DropDown';
import { CheckedBox } from './CheckedBox';
import { Submit } from './Submit';
import { PasswordBox } from './PasswordBox';

class App extends Component {
  constructor(props){
    super(props);
    this.state={items:[]};
    this.dataService= new dataService();
  }
  /*componentWillMount(){
    fetch("components/form.json").then(response=>response.json).then(({results: items})=>{this.setState({items})})
  }*/
  componentDidMount(){
    this.dataService.getComponentData().then(item=>this.setState({items:item}));
  }
  getComponent(item,index){
    switch(item.properties.type){
      case "text":
      return <InputBox className="input" key={index} lable={item.lable} type={item.properties.type} placeholder={item.properties.description} pattern={item.properties.pattern} maxLength={item.properties.maxLength} minLength={item.properties.minLength}/>

      case "password":
      return <PasswordBox key={index} lable={item.lable} placeholder={item.properties.description}  pattern={item.properties.pattern} maxLength={item.properties.maxLength} minLength={item.properties.minLength}/>

      case "dropDown":
      return <DropDown key={index} lable={item.lable} type={item.properties.type} arrayData={item.properties.enum}/>

      case "radio":
      return <RadioButton key={index} type='radio' lable={item.lable} arrayData={item.properties.anyOf.enum}/>

      case "checkBox":
      return <CheckedBox key={index} lable={item.lable} type={item.properties.type} arrayData={item.properties.items.enum}/>

      case "submit":
      return <Submit key={index} type={item.properties.type} title={item.properties.title}/>

      default:
      break;
    }
  }
  render() {
    let items=this.state.items;
    const dynamicComponents= items.map((item,index)=><div>

          {
            this.getComponent(item,index)
            /*item.properties.type==='text'?<InputBox lable={item.lable} type={item.properties.type} placeholder={item.properties.description} pattern={item.properties.pattern} maxLength={item.properties.maxLength} minLength={item.properties.minLength}/>:
            item.properties.type==='password'?<InputBox lable={item.lable} type={item.properties.type} placeholder={item.properties.description}  pattern={item.properties.pattern} maxLength={item.properties.maxLength} minLength={item.properties.minLength}/>:
            item.properties.type==='dropDown'?<DropDown lable={item.lable} type={item.properties.type} arrayData={item.properties.enum}/>:
            item.properties.type==='radio'?
            <RadioButton type='radio' lable={item.lable} arrayData={item.properties.anyOf.enum}/>:
            item.properties.type==='checkBox'?<CheckBox lable={item.lable} type={item.properties.type} arrayData={item.properties.items.enum}/>:
            <Submit type={item.properties.type} title={item.properties.title}/>*/
          }

    </div>)

    return (
      <div className="App">
      <h2>React Form</h2>
      <form autoComplete="off"> 


      {
       dynamicComponents
      }


      </form>
      </div>
    );
  }
}

export default App;

在上面的代码中,我使用了开关盒-即-硬编码添加了组件,但是我不想硬编码。我想知道如何使它自动化? 我用过反应素。 其他组件是:

  1. CheckedBox.js

    import React from 'react';
    import {InputText} from 'primereact/components/inputtext/InputText'
    import {CheckBox, Checkbox} from 'primereact/components/checkbox/Checkbox';
    export class CheckedBox extends React.Component {
    
    constructor() {
        super();
        this.state = {
            checked:false,
            value: []
        };
        this.onLangChange = this.onLangChange.bind(this);
    }
    onLangChange(e) {
        let selectedLang = [...this.state.value];
    
        if(e.checked)
            selectedLang.push(e.value);
        else
            selectedLang.splice(selectedLang.indexOf(e.value), 1);
    
        this.setState({value: selectedLang});
    }
    
    
    
    render(){
        const options= this.props.arrayData.map((item,index) => (
        <span key={index}>
            <Checkbox className="p-checkbox-icon p-c pi pi-check" inputId={index} value={item} onChange={this.onLangChange} checked={this.state.value.indexOf(item) !== -1}></Checkbox> 
      {/*<InputText className="radio p-inputtext" onChange={/*(e) => this.setState({value1: e.target.value})this.onLangChange} type={this.props.type} name={item} value={item}/>  */}
        <label htmlFor={index} className="p-checkbox-label">{item}</label> <span>  </span>
       </span>
      ));
        return(
            <div>
              {this.props.lable} :  {options}
    
            </div>
        );
    }
    

    }

  2. DropDown.js

    import React from 'react';
    
    
    export class DropDown extends React.Component {
    
    render(){
        const options= this.props.arrayData.map((arrayData,index) => (
    
        <option key={index} value={arrayData}>{arrayData}</option>
    
      ));
        return(
            <div>
              {this.props.lable} : <span> </span><select> {options} </select>
            </div>
             );
         }
       }
    
  3. InputBox.js

    import React from 'react';
    import {InputText} from 'primereact/components/inputtext/InputText'
    export class InputBox extends React.Component{
    
    constructor() {
        super();
        this.state = {
            value: null
        };
    }
    
    render(){
        return(
            <div>
                {this.props.lable} :<span> </span> <InputText autoComplete="off" className="p-inputtext" required value={this.state.value1} onChange={(e) => this.setState({value1: e.target.value})} type={this.props.type} maxLength={this.props.maxLength} placeholder={this.props.placeholder} minLength={this.props.minLength} keyfilter={this.props.pattern}/>
            </div>
        );
      }
     }
    
  4. PasswordBox.js

    import React from 'react';
    import {Password} from 'primereact/components/password/Password'
    export class PasswordBox extends React.Component{
    
     constructor() {
        super();
        this.state = {
            value:''
        };
    }
    
    render(){
        return(
            <div>
                {this.props.lable} : <span> </span><Password autoComplete="off" promptLabel="" weakLabel="" mediumLabel="" strongLabel="" required value={this.state.value} onChange={(e) => this.setState({value: e.target.value})}  placeholder={this.props.placeholder}  />
            </div>
        );
      }
     }
    
  5. RadioButton.js

     import React from 'react';
     import {InputText} from 'primereact/components/inputtext/InputText'
     export class RadioButton extends React.Component {
    
    constructor() {
        super();
        this.state = {
            value: null
        };
    }
    
    render(){
        const options= this.props.arrayData.map((arrayData,index) => (
        /*<select>
                    <option label={this.props.lable} value={arrayData.value}>{arrayData.name}</option>
                </select>*/
                <span key={index}>
                 <InputText className="p-inputtext" value={this.state.value1} onChange={(e) => this.setState({value1: e.target.value})} type={this.props.type} name={this.props.lable} value={arrayData.value}/>{arrayData.name}
    
                {/* <RadioButton inputId={index} name={arrayData.name} value={arrayData.value} onChange={(e) => this.setState({value1: e.value})} checked={this.state.value === arrayData.value} /> */}
                </span> 
        ));
        return(
            <div>
              {this.props.lable} :  {options}
            </div>
        );
      }
    }
    
  6. Submit.js

    import React from 'react';
    import {Button} from  'primereact/components/button/Button'
    
      export class Submit extends React.Component {
    
    
    render(){
    
        return(
            <div>
    
              {/* <button type={this.props.type}>{this.props.title}</button> */}
              <Button className="p-button-raised p-button-rounded" label={this.props.title}/>
    
            </div>
        );
      }
    }
    
  7. dataService.js

    import axios from 'axios';
    
    export class dataService {
    getComponentData(){
        return axios.get("components/form.json").then(res => res.data.items);
        //.then(res => <ITreaties[]>res.data)
        //.then(data => { return data; });
    
      }
    
    
    }
    

0 个答案:

没有答案