我有一个ReactJS应用程序
A)读取描述表单结构的JSON输入
B)动态从此JSON输入生成表单(使用document.createElement(..))
JSON看起来像这样:
{
formElements: [
{
id: “dd1”,
type: “dropdown”,
options: [ {value: “first”}, {value: “second”}]
},
{
id: “tf1”,
type: “textfield”,
showIf: “dd1 == ‘second’”
}
]
}
现在棘手的是,JSON输入文件不仅描述了哪些表单元素(例如下拉列表,单选按钮组,文本字段)等,而且还描述了每个元素的显示/隐藏逻辑。例如,如果选择了特定的下拉列表,则应显示文本字段(否则应保持隐藏状态)。
这通常是在jQuery中完成的,但我听说jQuery对React不是一个好主意。
如果这些是硬编码的表单元素,我可以轻松编写此显示/隐藏逻辑。问题是表单元素是动态生成的(通过读取该JSON文件),我需要动态地将这个show / hide逻辑应用于这些自动生成的表单元素。
我不知道该怎么做。
如果有人对这里的方法提出建议,特别是举例,那将非常感激。谢谢!
答案 0 :(得分:0)
您仍然可以将条件呈现逻辑应用于生成表单的JSX代码,但是您是否考虑过使用现有的表单库(如react-form或redux-forms)?如果你的反应比较新,那么这将是一个更容易获得你想要的结果的途径。我不能推荐一个特定的表单库,但是它会处理动态数据的反应表单。
这是我如何在不使用redux或内置表单库的情况下管理它的粗略草图。这是一个想象但从未执行过的草稿,所以把它当作伪代码对待它并且绝对没有优化:
//import base form components up here (input, checkbox, etc)
// Map the strings in your field object to the component imported or defined above
const fieldSelector = {
input : Input,
textarea: TextArea,
checkbox: CheckBox
}
Class CustomForm extends React.Component {
constructor(props) {
super(props);
const fields = {}
const byId = []
// Note if there is any asynchronous data, you might want to put this logic
// in componentDidMount
// Create an array with each 'id'
const byId = this.props.formData.map( item => item.id );
// Create a map object listing each field by its id
this.props.formData.forEach( (field) => {
fields[field.id] = field;
}
this.state = {
fields,
byId,
}
this.handleChange = this.handleChange.bind(this);
this.checkVisibility = this.checkVisibility.bind(this);
}
// Need to add some additional logic if you're using checkboxes
// Creates an event handler for each type of field
handleChange(id) {
return (event) => {
const updatedFields = {...this.state.fields};
updatedFields[id].value = event.target.value
this.state.byId.forEach( fieldId => {
updatedFields[fieldId].visible = checkVisibility(updatedFields, fieldId)};
}
this.setState({fields: updatedFields})
}
}
// You can either restructure your showIf or include a function above
// to parse our the elements of the expression.
checkVisibility(updatedFields, fieldId) {
const field = updatedFields[fieldId];
const showIfId = field.showIf.triggerFieldId;
const showIfValue = field.showIf.value;
const operator = field.showIf.operator;
switch(operator){
case '===':
return updatedFields[showIfId].value === ShowIfValue;
case '<':
return updatedFields[showIfId].value < ShowIfValue;
//...fill in rest of operators here
default:
return field.visible;
}
}
render() {
return this.state.byId.map( fieldId => {
const field = this.state.fields[fieldId];
const CustomField = FieldSelector[field.type]
return (
{field.visible &&
<CustomField {insert whatever props from field} />
}
);
});
}
}
export default CustomForm