动态表单
image.png
https://github.com/Open-Federation/json-schema-editor-visual
https://github.com/ant-design/ant-design/discussions/37175
https://hellosean1025.github.io/json-schema-visual-editor/

antd动态增加删除表单

  1. antd动态新增表单:在list后新增一个空对象,让其多一条数据,再重新渲染
  2. 删除有所改变,首先,form 表单的 key
    1. 使用 data.0.name 这样的格式作为 某个表单的 key, 那么根据form的机制
    2. 会自动产生 data: [{name: ‘xx’}] 这样的数据格式;也不用我们再次处理了
  3. https://blog.csdn.net/zr15829039341/article/details/106052723/

props-this.props.png

删除bug

  1. 不管删除哪一个只会删除最后一个,原因:删除时,没有 setFieldsValue重新设置值
  2. 删除时:获取当前的所有表单值,是为了等会执行表单替换
  3. 循环这个获取的表单值,再找出删除的这个index,然后把后面的表单重新赋值,往前移动一个
  4. 删除获取的表单子,还要删除map的数组长度

Form组件setFieldsValue方法的时候警告

  1. https://zhuanlan.zhihu.com/p/67937366
  2. form.setFieldsValue传来的数据这个方法只能适用于field存在的前提下,即数据和field是一对一的关系
  1. import React from 'react';
  2. import { Form, Input, Button, Icon, Row, Col } from 'antd';
  3. const formLayout = {
  4. labelCol: { span: 8 },
  5. wrapperCol: { span: 16 },
  6. }
  7. const FormList = (props) => {
  8. const { getFieldDecorator, getFieldValue, setFieldsValue } = props.form
  9. const [list, setList] = React.useState([])
  10. const prefix = 'list' // 就是 useEffect里面的 const data
  11. const formData = ['name', 'phone', 'email'] // 就是字段的名称
  12. React.useEffect(() => {
  13. const data = [ // ajax获取的数组,用于编辑时回显到input框上
  14. { name: 'jim', phone: '18923095555', email: 'jim@live.com' },
  15. { name: 'lucy', phone: '13523456666', email: 'lucy@lucy.com' },
  16. { name: '珠珠', phone: '010-89097777', email: 'zhuzhu@zhu.com' },
  17. { name: '春风', phone: '13689898888', email: 'chunfeng@chun.com' },
  18. ]
  19. setList(data)
  20. }, []);
  21. const onDelete = (i) => {
  22. // 删除时,获取当前的所有表单值
  23. const lists = getFieldValue(prefix)
  24. console.log(prefix, i, lists, 'delete100')
  25. // 删除后替换
  26. for (let index in lists) {
  27. const nIndex = Number(index)
  28. // 循环这个表单list值,再找出删除的这个index,然后把后面的表单重新赋值,往前移动一个
  29. if (nIndex >= i && lists[nIndex + 1]) {
  30. // ["name", "phone"]
  31. formData.map(item => setFieldsValue({[`${prefix}.${index}.${item}`]: lists[nIndex + 1][item]}))
  32. }
  33. }
  34. // 删除循环数组的长度
  35. const newList = list.filter((row, idx) => idx !== i)
  36. setList(newList);
  37. }
  38. const onAdd = () => {
  39. const row = {name: '', phone: ''}
  40. setList([...list, row])
  41. }
  42. const onChange = (key, value, index) => {
  43. const data = JSON.parse(JSON.stringify(list))
  44. data[index][key] = value
  45. setList(data)
  46. console.log(key, value, index, list)
  47. }
  48. return (
  49. <Form>
  50. {
  51. list.map((item, index) => (
  52. <Row key={`table-${index}`} className="form-row">
  53. {/* item = {name: "jim", phone: "18923097888"} */}
  54. <Col span={10}>
  55. <Form.Item label="姓名" {...formLayout}>
  56. {getFieldDecorator(`${prefix}.${index}.name`, {
  57. rules: [{ required: true, message: '请填写姓名'}],
  58. initialValue: item.name
  59. })(<Input
  60. onChange={(ev) => onChange('name', ev.target.value, index)}
  61. maxLength={30}
  62. placeholder="请填写姓名" />)}
  63. </Form.Item>
  64. </Col>
  65. <Col span={10}>
  66. <Form.Item label="手机" {...formLayout}>
  67. {getFieldDecorator(`${prefix}.${index}.phone`, {
  68. rules: [{ required: true, message: '请填写手机'}],
  69. initialValue: item.phone
  70. })(<Input
  71. onChange={(ev) => onChange('phone', ev.target.value, index)}
  72. maxLength={30}
  73. placeholder="请填写手机" />)}
  74. </Form.Item>
  75. </Col>
  76. {
  77. // list && list.length > 1 &&
  78. <Col span={4}>
  79. <Button
  80. type="link"
  81. onClick={() => onDelete(index) }
  82. ><Icon type="minus-circle" /></Button>
  83. </Col>
  84. }
  85. </Row>
  86. ))
  87. }
  88. <Button
  89. style={{ width: '100%', marginTop: 8 }}
  90. type="dashed"
  91. icon="plus"
  92. onClick={onAdd}
  93. >
  94. 添加
  95. </Button>
  96. </Form>
  97. );
  98. };
  99. export default Form.create()(FormList)