ANDT PRO 高级表单,表单中含TableForm,如何获取TableForm的列表信息

ANTD-PRO 下载的页面如何获取TableForm信息

由于antd pro 下载下面的页面默认是函数组件的不能使用refs信息直接获取子组件的信息
react中提供的reactHook可以帮助我们获取到子组件的内容

下载antd模板中下载表单

在这里插入图片描述
下载之后看到的就是一个如图的页面,页面分为输入框和table,适用于开发一对多关系的业务,例如订单中的商品信息,一个订单包含多个商品
在这里插入图片描述
接下来的这个问题就是,我在点击新增table中的数据时候,始终提交的都是页面中之前的初始化数据,没有办法获得最新的数据,这个问题困扰了我2天,最终我发现这里面包含了2个参数,一个value,和一个onChange

  • value
    通过在控制台输出发现,这个就是我们在表单中给的默认值
initialValues={{ params: tableData }}
  • onChange
    这个是一个函数大家可以打印一下
const TableForm: FC<TableFormProps> = ({ value, onChange }) => {
...
}

解决办法

在TableForm组件中加入一个副作用,作用于是data发生变更时候
data在都不顶部有声明

useEffect(() => {
    //发生改变就传传递这个给调用的组件
    onChange && onChange(data);
  }, [data])

最后我把这2个完整的函数组件贴出来供大家参考
index.tsx

import { CloseCircleOutlined } from '@ant-design/icons';
import { Button, Card, Col, DatePicker, Form, Input, Popover, Row, Select } from 'antd';

import React, { FC, useState } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
//import { connect, Dispatch } from 'umi';
import TableForm from './components/TableForm';
import FooterToolbar from './components/FooterToolbar';
import styles from './style.less';
import { connect, Dispatch } from 'dva';

type InternalNamePath = (string | number)[];

const { Option } = Select;

const fieldLabels = {
  jobName: '定时任务编码',
  functionId: '执行功能',
  triggerType: '触发类型',
  description: '定时任务描述',
};

const tableData: any = [
  {
    key: `NEW_TEMP_ID_1`,
    paramName: 'siteCode',
    paramValue: 'LMS0001',
    paramType: 'string',
    paramIndex: 1,
    description: '服务平台',
  }
];

interface JobDefineAddProps {
  dispatch: Dispatch<any>;
  submitting: boolean;
}

interface ErrorField {
  name: InternalNamePath;
  errors: string[];
}

const JobDefineAdd: FC<JobDefineAddProps> = ({
  submitting,
  dispatch,
}) => {
  const [form] = Form.useForm();
  const [error, setError] = useState<ErrorField[]>([]);
  const [dataForm, setDataForm] = useState();
  const getErrorInfo = (errors: ErrorField[]) => {
    const errorCount = errors.filter((item) => item.errors.length > 0).length;
    if (!errors || errorCount === 0) {
      return null;
    }
    const scrollToField = (fieldKey: string) => {
      const labelNode = document.querySelector(`label[for="${fieldKey}"]`);
      if (labelNode) {
        labelNode.scrollIntoView(true);
      }
    };
    const errorList = errors.map((err) => {
      if (!err || err.errors.length === 0) {
        return null;
      }
      const key = err.name[0] as string;
      return (
        <li key={key} className={styles.errorListItem} onClick={() => scrollToField(key)}>
          <CloseCircleOutlined className={styles.errorIcon} />
          <div className={styles.errorMessage}>{err.errors[0]}</div>
          <div className={styles.errorField}>{fieldLabels[key]}</div>
        </li>
      );
    });
    return (
      <span className={styles.errorIcon}>
        <Popover
          title="表单校验信息"
          content={errorList}
          overlayClassName={styles.errorPopover}
          trigger="click"
          getPopupContainer={(trigger: HTMLElement) => {
            if (trigger && trigger.parentNode) {
              return trigger.parentNode as HTMLElement;
            }
            return trigger;
          }}
        >
          <CloseCircleOutlined />
        </Popover>
        {errorCount}
      </span>
    );
  };

  const onFinish = (values: { [key: string]: any }) => {
    setError([]);
    console.log('执行了这里');
    console.log('values', values);
    dispatch({
      type: 'jobAndJobDefineAdd/submitAdvancedForm',
      payload: values,
    });
  };

  const onFinishFailed = (errorInfo: any) => {
    setError(errorInfo.errorFields);
  };





  return (
    <Form
      form={form}
      layout="vertical"
      hideRequiredMark
      initialValues={{ params: tableData }}
      onFinish={onFinish}
      onFinishFailed={onFinishFailed}
      //fields={fields}
      onFieldsChange={(changedFields, allFields) => {
        //onChange(allFields);
        console.log(changedFields);
        console.log(allFields);
      }}

    >
      <PageHeaderWrapper content="此页面用于定义定时任务的已经定时任务的参数信息">
        <Card title="定时任务定义" className={styles.card} bordered={false}>
          <Row gutter={16}>
            <Col lg={6} md={12} sm={24}>
              <Form.Item
                label={fieldLabels.jobName}
                name="jobName"
                rules={[{ required: true, message: '请输入定时任务编码' }]}
              >
                <Input placeholder="请输入定时任务编码" />
              </Form.Item>
            </Col>

            <Col xl={{ span: 6, offset: 2 }} lg={{ span: 10 }} md={{ span: 24 }} sm={24}>
              <Form.Item
                label={fieldLabels.functionId}
                name="functionId"
                rules={[{ required: true, message: '请选择功能' }]}
              >
                <Select placeholder="请选择功能">
                  <Option value="xiao">付晓晓</Option>
                  <Option value="mao">周毛毛</Option>
                </Select>
              </Form.Item>
            </Col>

            <Col xl={{ span: 6, offset: 2 }} lg={{ span: 10 }} md={{ span: 24 }} sm={24}>
              <Form.Item
                label={fieldLabels.triggerType}
                name="triggerType"
                rules={[{ required: true, message: '请选择JOB类型' }]}
              >
                <Select placeholder="请请选择JOB类型">
                  <Option value="job">JAVA</Option>
                  <Option value="procedure">存储过程</Option>
                </Select>
              </Form.Item>
            </Col>
          </Row>
          <Row gutter={16}>
            <Col lg={6} md={12} sm={24}>
              <Form.Item
                label={fieldLabels.description}
                name="description"
                rules={[{ required: true, message: '定时任务描述' }]}
              >
                <Input placeholder="请输入定时任务描述" />
              </Form.Item>
            </Col>
          </Row>
        </Card>
        <Card title="定时任务参数" bordered={false}>
          <Form.Item name="params">
            <TableForm onChange={(datas: any) => {
              console.log(datas);
              //setDataForm(datas)
            }
            } />
          </Form.Item>
        </Card>
      </PageHeaderWrapper>
      <FooterToolbar>
        {getErrorInfo(error)}
        <Button type="primary" onClick={() => {
          console.log("dataForm的信息为", dataForm);
          form?.submit()
        }} loading={submitting}>
          提交
        </Button>
      </FooterToolbar>
    </Form>
  );
};

export default connect(({ loading }: { loading: { effects: { [key: string]: boolean } } }) => ({
  submitting: loading.effects['jobAndJobDefineAdd/submitAdvancedForm'],
}))(JobDefineAdd);

  • TableForm.tsx
import { PlusOutlined } from '@ant-design/icons';
import { Button, Divider, Input, Popconfirm, Table, message } from 'antd';
import React, { FC, useState, useEffect } from 'react';

import styles from '../style.less';

interface TableFormDateType {
  key: string;
  workId?: string;
  name?: string;
  department?: string;
  isNew?: boolean;
  editable?: boolean;
}
interface TableFormProps {
  value?: TableFormDateType[];
  onChange?: (value: TableFormDateType[]) => void;
}

const TableForm: FC<TableFormProps> = ({ value, onChange }) => {
  const [clickedCancel, setClickedCancel] = useState(false);
  const [loading, setLoading] = useState(false);
  const [index, setIndex] = useState(0);
  const [cacheOriginData, setCacheOriginData] = useState({});
  const [data, setData] = useState(value);


  const getRowByKey = (key: string, newData?: TableFormDateType[]) =>
    (newData || data)?.filter((item) => item.key === key)[0];

  const toggleEditable = (e: React.MouseEvent | React.KeyboardEvent, key: string) => {
    e.preventDefault();
    const newData = data?.map((item) => ({ ...item }));
    const target = getRowByKey(key, newData);
    if (target) {
      // 进入编辑状态时保存原始数据
      if (!target.editable) {
        cacheOriginData[key] = { ...target };
        setCacheOriginData(cacheOriginData);
      }
      target.editable = !target.editable;
      setData(newData);
    }
  };
  const newMember = () => {
    const newData = data?.map((item) => ({ ...item })) || [];

    newData.push({
      key: `NEW_TEMP_ID_${index}`,
      paramName: '',
      paramValue: '',
      paramType: '',
      paramIndex: `${index + 1}`,
      description: '',
      editable: true,
      isNew: true,
    });

    setIndex(index + 1);
    setData(newData);
  };

  const remove = (key: string) => {
    const newData = data?.filter((item) => item.key !== key) as TableFormDateType[];
    setData(newData);
    if (onChange) {
      onChange(newData);
    }
  };

  const handleFieldChange = (
    e: React.ChangeEvent<HTMLInputElement>,
    fieldName: string,
    key: string,
  ) => {
    const newData = [...(data as TableFormDateType[])];
    const target = getRowByKey(key, newData);
    if (target) {
      target[fieldName] = e.target.value;
      setData(newData);
    }
  };

  const saveRow = (e: React.MouseEvent | React.KeyboardEvent, key: string) => {
    e.persist();
    setLoading(true);
    setTimeout(() => {
      if (clickedCancel) {
        setClickedCancel(false);
        return;
      }
      const target = getRowByKey(key) || ({} as any);
      console.info(target);
      if (!target.paramName || !target.paramValue || !target.paramType) {
        message.error('请填写完整JOB变量');
        (e.target as HTMLInputElement).focus();
        setLoading(false);
        return;
      }
      delete target.isNew;
      toggleEditable(e, key);
      if (onChange) {
        onChange(data as TableFormDateType[]);
      }
      setLoading(false);
    }, 500);
  };



  const handleKeyPress = (e: React.KeyboardEvent, key: string) => {
    if (e.key === 'Enter') {
      saveRow(e, key);
    }
  };

  useEffect(() => {
    //一家在就传传递这个给调用的组件
    onChange && onChange(data);
  }, [data])

  const cancel = (e: React.MouseEvent, key: string) => {
    setClickedCancel(true);
    e.preventDefault();
    const newData = [...(data as TableFormDateType[])];
    // 编辑前的原始数据
    let cacheData = [];
    cacheData = newData.map((item) => {
      if (item.key === key) {
        if (cacheOriginData[key]) {
          const originItem = {
            ...item,
            ...cacheOriginData[key],
            editable: false,
          };
          delete cacheOriginData[key];
          setCacheOriginData(cacheOriginData);
          return originItem;
        }
      }
      return item;
    });
    setData(cacheData);
    setClickedCancel(false);
  };

  const columns = [
    {
      title: '变量索引',
      dataIndex: 'paramIndex',
      key: 'paramIndex',
      width: '8%',
      render: (text: string, record: TableFormDateType) => {
        if (record.editable) {
          return (
            <Input
              value={text}
              autoFocus
              onChange={(e) => handleFieldChange(e, 'paramIndex', record.key)}
              onKeyPress={(e) => handleKeyPress(e, record.key)}
              placeholder="paramIndex"
            />
          );
        }
        return text;
      },
    },
    {
      title: '变量名称',
      dataIndex: 'paramName',
      key: 'paramName',
      width: '20%',
      render: (text: string, record: TableFormDateType) => {
        if (record.editable) {
          return (
            <Input
              value={text}
              autoFocus
              onChange={(e) => handleFieldChange(e, 'paramName', record.key)}
              onKeyPress={(e) => handleKeyPress(e, record.key)}
              placeholder="变量名称"
            />
          );
        }
        return text;
      },
    },
    {
      title: '值',
      dataIndex: 'paramValue',
      key: 'paramValue',
      width: '20%',
      render: (text: string, record: TableFormDateType) => {
        if (record.editable) {
          return (
            <Input
              value={text}
              onChange={(e) => handleFieldChange(e, 'paramValue', record.key)}
              onKeyPress={(e) => handleKeyPress(e, record.key)}
              placeholder="请输入变量值"
            />
          );
        }
        return text;
      },
    },
    {
      title: '变量类型',
      dataIndex: 'paramType',
      key: 'paramType',
      width: '10%',
      render: (text: string, record: TableFormDateType) => {
        if (record.editable) {
          return (
            <Input
              value={text}
              onChange={(e) => handleFieldChange(e, 'paramType', record.key)}
              onKeyPress={(e) => handleKeyPress(e, record.key)}
              placeholder="请选择变量类型"
            />
          );
        }
        return text;
      },
    },
    {
      title: '变量描述',
      dataIndex: 'description',
      key: 'description',
      width: '20%',
      render: (text: string, record: TableFormDateType) => {
        if (record.editable) {
          return (
            <Input
              value={text}
              onChange={(e) => handleFieldChange(e, 'description', record.key)}
              onKeyPress={(e) => handleKeyPress(e, record.key)}
              placeholder="请选择变量描述"
            />
          );
        }
        return text;
      },
    },
    {
      title: '操作',
      key: 'action',
      render: (text: string, record: TableFormDateType) => {
        if (!!record.editable && loading) {
          return null;
        }
        if (record.editable) {
          if (record.isNew) {
            return (
              <span>
                <a onClick={(e) => saveRow(e, record.key)}>添加</a>
                <Divider type="vertical" />
                <Popconfirm title="是否要删除此行?" onConfirm={() => remove(record.key)}>
                  <a>删除</a>
                </Popconfirm>
              </span>
            );
          }
          return (
            <span>
              <a onClick={(e) => saveRow(e, record.key)}>保存</a>
              <Divider type="vertical" />
              <a onClick={(e) => cancel(e, record.key)}>取消</a>
            </span>
          );
        }
        return (
          <span>
            <a onClick={(e) => toggleEditable(e, record.key)}>编辑</a>
            <Divider type="vertical" />
            <Popconfirm title="是否要删除此行?" onConfirm={() => remove(record.key)}>
              <a>删除</a>
            </Popconfirm>
          </span>
        );
      },
    },
  ];

  return (
    <>
      <Table<TableFormDateType>
        loading={loading}
        columns={columns}
        dataSource={data}
        pagination={false}
        rowClassName={(record) => (record.editable ? styles.editable : '')}
      />
      <Button
        style={{ width: '100%', marginTop: 16, marginBottom: 8 }}
        type="dashed"
        onClick={newMember}
      >
        <PlusOutlined />
        新增变量
      </Button>
    </>
  );
};

export default TableForm;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值