6-nestedBasicUsage.jsx 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import React, { useState, useRef } from 'react';
  2. import { Form, Col, Row, Button, ArrayField, Space, useFormState } from '@douyinfe/semi-ui';
  3. import { IconMinusCircle, IconPlusCircle, IconRefresh } from '@douyinfe/semi-icons';
  4. import { JSONTree } from 'react-json-tree';
  5. const FormStateTree = () => {
  6. const formState = useFormState();
  7. return (
  8. <JSONTree
  9. shouldExpandNodeInitially={() => true}
  10. hideRoot
  11. data={formState}
  12. />
  13. );
  14. };
  15. const NestDemo = () => {
  16. const formRef = useRef();
  17. const getFormApi = () => {
  18. const formApi = formRef.current.formApi;
  19. return formApi;
  20. };
  21. const formInitValues = {
  22. data: [
  23. {
  24. name: '0',
  25. rules: [
  26. { desc: '0-0-desc', type: '0-0-type' },
  27. { desc: '0-1-desc', type: '0-1-type' },
  28. ],
  29. },
  30. {
  31. name: '1',
  32. rules: [
  33. { desc: '1-0-desc', type: '1-0-type' }
  34. ],
  35. }
  36. ]
  37. };
  38. const setValueChangeOutSide = () => {
  39. const formApi = getFormApi();
  40. formApi.setValue('data', [
  41. {
  42. name: 'new-0',
  43. rules: [
  44. { desc: 'new-0-0-desc', type: 'new-0-0-type' },
  45. { desc: 'new-0-1-desc', type: 'new-0-1-type' },
  46. ],
  47. },
  48. {
  49. name: 'new-1',
  50. rules: [
  51. { desc: 'new-1-0-desc', type: 'new-1-0-type' },
  52. ],
  53. },
  54. {
  55. name: 'new-2',
  56. rules: [
  57. { desc: 'new-2-0-desc', type: 'new-2-0-type' },
  58. { desc: 'new-2-1-desc', type: 'new-2-1-type' },
  59. { desc: 'new-2-2-desc', type: 'new-2-2-type' },
  60. ],
  61. }
  62. ]);
  63. };
  64. const setValueChangeInside = () => {
  65. const formApi = getFormApi();
  66. formApi.setValue('data[0].rules', [{ desc: 'new-0-0-desc-in', type: 'new-0-0-type-in' }]);
  67. };
  68. const setValueChangeRow = () => {
  69. const formApi = getFormApi();
  70. formApi.setValue('data[0].rules[0]', { type: 'special-row-type', desc: 'special-row-desc' });
  71. };
  72. return (
  73. <Form
  74. ref={formRef}
  75. initValues={formInitValues}
  76. labelPosition='inset'
  77. >
  78. <ArrayField field='data'>
  79. {({ add, arrayFields, addWithInitValue }) => (
  80. <React.Fragment>
  81. <Space>
  82. <Button htmlType='reset' theme='solid' type='secondary' icon={<IconRefresh />}>Reset</Button>
  83. <Button id='changeOutSide' theme='solid' type='primary' onClick={() => setValueChangeOutSide()}>ChangeOutSide</Button>
  84. <Button id='changeInside' theme='solid' type='tertiary' onClick={() => setValueChangeInside()}>ChangeInsideSide</Button>
  85. <Button id='changeRow' theme='solid' type='tertiary' onClick={() => setValueChangeRow()}>ChangeSpecialRow</Button>
  86. </Space>
  87. {
  88. arrayFields.map(({ field, key, remove }, i) => (
  89. <div key={key} style={{ width: 1000, display: 'flex', flexWrap: 'wrap' }} id={`data-${i}`} className='line'>
  90. {key.slice(0, 10)}
  91. <Space>
  92. <Form.Input
  93. field={`${field}.name`}
  94. label={`${field}.name`}
  95. style={{ width: 700 }}
  96. id={`data-${i}-name`}
  97. >
  98. </Form.Input>
  99. <Button
  100. onClick={() => addWithInitValue({
  101. name: arrayFields.length,
  102. rules: [
  103. { desc: `${arrayFields.length}-0-desc`, type: `${arrayFields.length}-0-type` }
  104. ]
  105. })}
  106. icon={<IconPlusCircle/>}
  107. id={`data-${i}-add`}
  108. disabled={i !== arrayFields.length - 1}
  109. />
  110. <Button
  111. type='danger'
  112. onClick={remove}
  113. id={`data-${i}-remove`}
  114. icon={<IconMinusCircle />}
  115. />
  116. </Space>
  117. <ArrayField field={`${field}.rules`}>
  118. {({ add: addNested, arrayFields: nestedArrayFields, addWithInitValue: addNestedWithInitValue }, ) => (
  119. <React.Fragment>
  120. {
  121. nestedArrayFields.map(({ field: f, key: k, remove: r }, n) => (
  122. <section className='rules' key={k} style={{ display: 'flex', flexWrap: 'wrap', marginLeft: 36 }}>
  123. <Space>
  124. {k.slice(0, 10)}
  125. <Form.Input
  126. style={{ width: 300, marginRight: 12 }}
  127. field={`${f}.type`}
  128. label={`${f}.type`}
  129. id={`data-${i}-rule-${n}-type`}
  130. />
  131. <Form.Input
  132. style={{ width: 300 }}
  133. field={`${f}.desc`}
  134. label={`${f}.desc`}
  135. id={`data-${i}-rule-${n}-desc`}
  136. />
  137. <Button
  138. onClick={() => addNestedWithInitValue({ type: `${i}-${n+1}-type`, desc: `${i}-${n+1}-desc` })}
  139. icon={<IconPlusCircle/>}
  140. id={`data-${i}-rule-${n}-add`}
  141. disabled={n !== nestedArrayFields.length - 1}
  142. >
  143. add new line
  144. </Button>
  145. <Button
  146. type='danger'
  147. onClick={r}
  148. id={`data-${i}-rule-${n}-remove`}
  149. icon={<IconMinusCircle />}
  150. />
  151. </Space>
  152. </section>
  153. ))
  154. }
  155. </React.Fragment>
  156. )}
  157. </ArrayField>
  158. </div>
  159. ))
  160. }
  161. </React.Fragment>
  162. )}
  163. </ArrayField>
  164. <FormStateTree></FormStateTree>
  165. </Form>
  166. );
  167. };
  168. NestDemo.storyName = 'ArrayField-Nested Level 2';
  169. export default NestDemo;