使用场景,在一个列表中,点击每一行会弹出一个表单,通过修改表单数据并提交来修改这一行的数据,其中某个数据的填写需要通过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={{ '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={{ '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>, 200 }, { title: '事件', dataIndex: 'event', key: 'event', render: (text, record, index) => <div> <span>{text}</span> </div>, 200 }, { title: '相关人员', dataIndex: 'person', key: 'person', 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={{ 600 }}/> <WrappedEditForm visible={this.state.visible} record={this.state.record} onCancel={this.onCancel} onSave={this.onSave} /> </div> ) } } export default EventTable