同时使用 Ant Design of React 中 Mention 和 Form

使用场景,在一个列表中,点击每一行会弹出一个表单,通过修改表单数据并提交来修改这一行的数据,其中某个数据的填写需要通过Mention实现动态提示及自动补全的功能。

具体效果为:

 

遇到的问题:

1、希望所需要的提示和自动补全的内容不同,实际场景类似于ide中函数提示(包含参数和返回值以及用法等提示)和函数补全(只补全函数名)的功能。

Ant Design的Mention组件提供了Nav可以实现这个功能,但是实际使用中发现会报错,经查发现为Ant Design的一个bug,升级版本解决。

2、然后遇到问题,发现suggestions使用了Nav数组之后,不能通过输入自动动态查询,具体表现为

 

经查原因为,将生成suggestions的计算写到了引用Mention的地方:

const suggestions = [
  {children:'张三 男 18 会计', value:'张三'},
  {children:'李四 女 21 审计', value:'李四'},
  {children:'王五 男 33 总监', value:'王五'}
]
<Mention
  style={{ width: '100%' }}
  suggestions={ suggestions.map( (x) => <Nav {...x} />) }
/>

解决方法,将计算过程提到外面去……

3、点击不同数据行的时候,弹出表单数据不更新,也就是表单的 initialValue 不生效

在 react 生命周期 componentWillReceiveProps(nextProps) 中把 Mention 的数据更新。

 

需要注意的地方是 Mention 的 value 不是 string,需要在多处通过 toString 和 toContentState 进行转换。

 

行吧,困扰了两天的bug好像写出来也没什么东西……QAQ怪我蠢……

 

完整代码:

import React from 'react';
import { Table, Icon, Button, Form, Input, Modal, Mention } from 'antd';
const FormItem = Form.Item;
const { toString, toContentState, Nav } = Mention;

const suggestions = [
  <Nav children='张三 男 18 会计' value='张三' />,
  <Nav children='李四 女 21 审计' value='李四' />,
  <Nav children='王五 男 33 总监' value='王五' />
]


class EditForm extends React.Component {
  onSave = () => {
    this.props.form.validateFields((err, values) => {
      if (!err) {
        this.props.onSave({ ...values, person: toString(values.person) })
        this.props.form.resetFields()
        this.props.form.setFieldsValue({person: toContentState('')})
        console.log(toString(this.props.form.getFieldValue('person')))
      }
    });
  }
  onCancel = () => {
    this.props.onCancel()
    // 重置为初始值 initialValue 防止点击不同区域出现数据不刷新的情况(although...i dont know why...
    this.props.form.resetFields()
  }
  // 在接受 props 时调用 无论 nextProps 和 this.props 是否相等
  // 首先要在表单隐藏变为显示的时候赋值 其次 只有当前已经存在显示值的时候才调用 否则没意义 也会存在 getFiledsValue 未注册情况
  componentWillReceiveProps(nextProps) {
    if (nextProps.visible === true && this.props.visible === false && this.props.record) {
      this.props.form.setFieldsValue({person: toContentState(nextProps.record.person)})
    }
  }
  render() {
    // console.log(this.props)
    const { record, visible, onCancel  } = this.props;
    if (!record) return null;
    const { getFieldDecorator } = this.props.form;
    return (
      <Modal
        visible={visible}
        title="编辑事件"
        okText="保存"
        onCancel={this.onCancel}
        onOk={this.onSave}
      >
        <Form layout="vertical" onSubmit={this.handleSubmit}>
          <FormItem>
            {getFieldDecorator('event', {
              rules: [{ required: true, message: '请输入事件!' }],
              initialValue: record.event
            })(
              <Input />
            )}
          </FormItem>
          <FormItem>
            {getFieldDecorator('person', {
              initialValue: toContentState(record.person),
              rules: [{ required: true, message: '请输入相关人员!' }],
            })(
              <Mention
                style={{ width: '100%' }}
                suggestions={ suggestions }
              />
            )}
          </FormItem>
        </Form>
      </Modal>
    );
  }
}

const WrappedEditForm = Form.create()(EditForm);


class EventTable extends React.Component {
  state = {
    visible: false,
    record: null,
    index: 0
  }
  columns = [
    {
      title: '操作',
      key: 'action',
      render: (text, record, index) => 
        <div>
          <Button onClick={()=>{ this.setState({
            visible: true,
            record,
            index
          }) }}>编辑</Button>
        </div>,
        width: 200
    }, 
    {
      title: '事件',
      dataIndex: 'event',
      key: 'event',
      render: (text, record, index) => 
        <div>
          <span>{text}</span>
        </div>,
        width: 200
    },
    {
      title: '相关人员',
      dataIndex: 'person',
      key: 'person',
      width: 200
    }
  ];
  data = [
    {
      key: '1',
      event: '早餐',
      person: '@组长',
    }, {
      key: '2',
      event: '午餐',
      person: '@组长',
    }, {
      key: '3',
      event: '晚餐',
      person: '@组长',
    }
  ];
  onCancel = () => {
    this.setState({visible: false})
  }
  onSave = (values) => {
    this.setState({visible: false})
    this.data[this.state.index].event = values.event
    this.data[this.state.index].person = values.person
  }
  render() {
    return (
      <div>
        <Table columns={this.columns} dataSource={this.data} style={{ width: 600 }}/>
        <WrappedEditForm visible={this.state.visible} record={this.state.record} 
          onCancel={this.onCancel} onSave={this.onSave} />
      </div>
    )
  }
}

export default EventTable

 

posted @ 2017-12-15 02:58  我不吃饼干呀  阅读(1891)  评论(0编辑  收藏  举报