zoukankan      html  css  js  c++  java
  • 同时使用 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={{  '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
  • 相关阅读:
    Vue路由机制
    谷歌浏览器打不开应用商店的解决方法
    Vue报错——Component template should contain exactly one root element. If you are using vif on multiple elements, use velseif to chain them instead.
    Vue.js学习之——安装
    Vue使用axios无法读取data的解决办法
    关于localstorage存储JSON对象的问题
    2013年整体计划
    个人喜欢的警语收集
    Linux防火墙的关闭和开启
    Flex修改title 转载
  • 原文地址:https://www.cnblogs.com/wenruo/p/8041083.html
Copyright © 2011-2022 走看看