order: 5 group: order: 3 title: 高级用法

toc: content

表单监听(watch)

有时我们需要根据特定表单数据的变动而时时触发一个 callback,FormRender 开放了 watch 变量,用于数据的监听的唤起回调。语法类似于 vue 的 watch。

注意 form-render 并未限制在 watch 的 callback 里能写的内容,请慎重使用。例如 path 是’#’ 则默认每次都会执行,要是在 callback 里写了任何对 formData、schema 的修改,就可能会陷入反复触发。所以请确保 watch 的逻辑符合真实联动使用逻辑。

值的联动

注意使用 form.setValueByPath 指定路径对值进行修改

  1. /**
  2. * transform: true
  3. * defaultShowCode: true
  4. */
  5. import React, { useEffect } from 'react';
  6. import { Button } from 'antd';
  7. import FormRender, { useForm } from 'form-render';
  8. const schema = {
  9. type: 'object',
  10. properties: {
  11. input1: {
  12. title: '简单输入框',
  13. type: 'string',
  14. required: true,
  15. placeholder: '尝试在此输入',
  16. },
  17. input2: {
  18. title: '简单输入框2',
  19. type: 'string',
  20. },
  21. },
  22. };
  23. const Demo = () => {
  24. const form = useForm();
  25. const watch = {
  26. // # 为全局
  27. '#': val => {
  28. console.log('表单的实时数据为:', val);
  29. },
  30. input1: val => {
  31. form.setValueByPath('input2', val);
  32. },
  33. };
  34. return <FormRender form={form} schema={schema} watch={watch} />;
  35. };
  36. export default Demo;

schema 的联动

form.setSchemaByPath 指定路径对 schema 进行修改

  1. /**
  2. * transform: true
  3. * defaultShowCode: true
  4. */
  5. import React, { useEffect } from 'react';
  6. import { Button } from 'antd';
  7. import FormRender, { useForm } from 'form-render';
  8. const schema = {
  9. type: 'object',
  10. properties: {
  11. input1: {
  12. title: '简单输入框',
  13. type: 'string',
  14. required: true,
  15. placeholder: '尝试在此输入',
  16. },
  17. input2: {
  18. title: '简单输入框2',
  19. type: 'string',
  20. },
  21. obj1: {
  22. title: '对象',
  23. description: '这是一个对象类型',
  24. type: 'object',
  25. properties: {
  26. select: {
  27. title: '单选',
  28. type: 'string',
  29. enum: ['a', 'b', 'c'],
  30. enumNames: ['早', '中', '晚'],
  31. widget: 'radio',
  32. },
  33. },
  34. },
  35. },
  36. };
  37. const Demo = () => {
  38. const form = useForm();
  39. const onFinish = (formData, errorFields) => {
  40. if (errorFields.length > 0) {
  41. alert('errorFields:' + JSON.stringify(errorFields));
  42. } else {
  43. alert('formData:' + JSON.stringify(formData, null, 2));
  44. }
  45. };
  46. const watch = {
  47. input1: val => {
  48. if (val && val.length > 2) {
  49. form.setSchemaByPath('obj1.select', ({ enumNames }) => {
  50. return {
  51. enumNames: enumNames.map(item => item + 'a'),
  52. };
  53. });
  54. } else {
  55. form.setSchemaByPath('obj1.select', { enumNames: ['早', '中', '晚'] });
  56. }
  57. },
  58. };
  59. return (
  60. <div>
  61. <FormRender
  62. form={form}
  63. schema={schema}
  64. onFinish={onFinish}
  65. watch={watch}
  66. />
  67. <Button
  68. type=""
  69. style={{ marginRight: 8 }}
  70. onClick={() =>
  71. form.setSchemaByPath('input2', {
  72. title: '编辑框',
  73. format: 'textarea',
  74. })
  75. }
  76. >
  77. input 改为 textarea
  78. </Button>
  79. <Button type="primary" onClick={form.submit}>
  80. 提交
  81. </Button>
  82. </div>
  83. );
  84. };
  85. export default Demo;

语法说明

watch 是一个对象,key 值为数据对应的“路径”,value 为 callback 函数,或者在复杂情况是个对象

  1. const watch = {
  2. // # 为全局
  3. '#': val => {
  4. console.log('表单的时时数据为:', val);
  5. },
  6. input1: val => {
  7. if (val !== undefined) {
  8. form.onItemChange('input2', val);
  9. }
  10. },
  11. 'object1.select2': {
  12. handler: val => {
  13. if (val === 'option1') {
  14. form.onItemChange('object1.input2', 'hello');
  15. }
  16. },
  17. immediate: true,
  18. },
  19. };

Option: immediate

  • 类型: boolean
  • 默认: false

immediate: true 会在首次加载时就执行一次 watch 的 handler

  1. const watch = {
  2. // # 为全局
  3. input1: {
  4. handler: val => {
  5. if (val !== undefined) {
  6. form.onItemChange('input2', val);
  7. }
  8. },
  9. immediate: true,
  10. },
  11. };