解决react/antd select插件只能返回一个或者一列返回值实属无奈自己参考网络上大佬写的半成品手噜了一个

前言

最近在做一个合同管理系统,需要选择多个附件(包括文件id/第三方模板id等信息),然后生成对应的网络签字页面。首先想的就是使用select多选方案解决,但是我这边使用的form是有封装的select选中后无法返回对象成为硬伤(由于后端想要接收多个值,不想为了一个值还去循环select数据库,当然这不考虑xxs问题的前提下尽量信任前端数据),最后实在没办法,就参考网络上大佬的半成品手撸了一个轮子。放出来供大家参考。

参考地址

http://www.icodebang.com/article/271436

解决方案

调用方


import AttachmentSelect from './AttachmentSelect';
//....
  onChangeMultipleTemplate = data => {
    this.props.form.setFieldsValue({
      attachments: data,
    });
    console.log(data);
  };
//....

  <Form.Item {...formItemLayout} label="附件"  name="attachments" >
    {getFieldDecorator('attachments', {
      initialValue: formData.attachments,
      rules: [
        {
          required: false,
          message: '请选择附件',
        },
      ],
    })(
    
    <>
    <AttachmentSelect onChange={this.onChangeMultipleTemplate} />
    </>
    )}
  </Form.Item>

AttachmentSelect.js

import React, { PureComponent } from 'react';
import { Select } from 'antd';
import { CheckOutlined } from '@ant-design/icons';
import './AttachmentSelect.less';

function parseValue(value) {
  if (!value) {
    return '';
  }
  return String(value);
}

export default class TemplateSelect extends PureComponent {
  constructor(props) {
    super(props);

    this.state = {
      value: parseValue(props.title),
      data: [],
      selectChecked: [],
    };
  }

  componentDidMount() {
  data=[{id:'1',title:"11"]}
      this.setState({ data: data || [] });
  }

  setselectChecked = data => {
    this.setState({
      selectChecked: data,
    });
  };

  onFocus = () => {
    // console.log('获取焦点');

    this.setState({
      isOnFocus: true,
    });
  };

  onBlur = () => {
    // console.log('失去焦点');
    this.setState({
      isOnFocus: false,
    });
  };

  checkSelect = data => {
    // this.onFocus()
    console.log(data);
    // 如果存在则删除,如果不存在则添加

    // selectChecked.push(data);
   let OptionsList=this.state.data
    let tempArr = this.state.selectChecked;
    let index = -1;
    for (let i = 0; i < tempArr.length; i++) {
      if (tempArr[i].title === data.title) {
        index = i;
        console.log('index:', index);
        break;
      }
    }

    if (index !== -1) {
      // 存在删除

      tempArr.splice(index, 1);
      this.setselectChecked([...tempArr]);

      OptionsList.map((item, index) => {
        if (item.title === data.title) {
          item.active = false;
        }
      });
    } else {
      // 不存在添加
      tempArr.push(data);
      this.setselectChecked([...tempArr]);
      OptionsList.map((item, index) => {
        if (item.title === data.title) {
          item.active = true;
        }
      });
    }

    this.setState({
      data:JSON.parse(JSON.stringify(OptionsList)),
    });

    this.triggerChange(tempArr)

  };

  // 删除选中的option
  areDeleteOption = value => {
    console.log('value:', value);
    let OptionsList=this.state.data
    let tempArr = this.state.selectChecked,
      index = -1;
    for (let i = 0; i < tempArr.length; i++) {
      if (tempArr[i].title === value.title) {
        index = i;
        console.log('index:', index);
        break;
      }
    }

    OptionsList.map((item, index) => {
      if (item.title === value.title) {
        item.active = false;
      }
    });

    if (index !== -1) {
      tempArr.splice(index, 1);
      this.setselectChecked([...tempArr]);
    }
    this.setState({
      data:JSON.parse(JSON.stringify(OptionsList)),
    });
    this.triggerChange(tempArr)
  };


  triggerChange = (data) => {
    const { onChange } = this.props;
    if (onChange) {
      onChange(data);
    }
  
    this.forceUpdate()
  };

  render() {
    const { value, data, selectChecked } = this.state;
    return (
      <>
        <div
          className={`select-body ${this.state.isOnFocus ? 'select-header-visited' : ''}`}
          suppressContentEditableWarning
          contentEditable="true"
          onFocus={this.onFocus}
          onBlur={this.onBlur}
          onKeyDown={e => {
            e.preventDefault();
          }}
        >
          <div className={`select-header `}  
          placeholder="请选择附件"
          suppressContentEditableWarning>
            {selectChecked.map((item, index) => {
              return (
                <span key={index} suppressContentEditableWarning contentEditable="false">
                  <span className={`card`}>
                    {item?.title}
                    <span
                      onMouseDown={e => {
                        e.preventDefault();
                      }}
                      onMouseUp={e => {
                        e.preventDefault();
                      }}
                      onClick={e => {
                        this.areDeleteOption(item);
                      }}
                    >
                      x
                    </span>
                  </span>
                </span>
              );
            })}
          </div>

          {this.state.isOnFocus ? (
            <>
          <div contentEditable="false" suppressContentEditableWarning className={`select-content`}>
            {data.map((item, index) => {
              return (
                <li
                  key={"select-centent"+index}
                  onClick={e => {
                    e.preventDefault();
                    this.checkSelect(item);
                  }}
                >
                  {item?.title} {item?.active ? <CheckOutlined key={"select-centent-icon"+index} /> : ''}  
                  
                </li>
              );
            })}
          </div>
          </>
          ) : (
            ''
          )}
        </div>
      </>
    );
  }
}

AttachmentSelect.less

@import '~antd/lib/style/themes/default.less';


/* 下拉框整体样式 */
.select-body {
  box-sizing: border-box;
  position: relative;
  display: inline-block;
  width: 100%;
  // height: 60px;
  margin: 0;
  padding: 0;
  color: #000000d9;
  font-size: 14px;
  border-radius: 2px;

  border: 1px solid #dad8d8;

  &:hover {
    border: 1px solid rgb(62, 165, 249);


  }

  &:focus {
    // color: transparent;
    // text-shadow: 0 0 0 #000;

    outline: none;
    border: none;

    .select-header {
      border: 1px solid rgb(62, 165, 249);
      border-radius: 2px;
    }

  }

  // [contenteditable]:focus {
  //   outline: none;
  //   border:0;
  //   background-color:yellow;
  // }


  /* 下拉框搜索框 */
  .select-header {
    width: 100%;
    min-height: 30px;
    position: relative;
    // padding: 5px;
    padding: 0 11px;
    // background-color: #fff;
    transition: all .3s cubic-bezier(.645, .045, .355, 1);
    cursor: text;

    &:empty::before {
      content: attr(placeholder);
      color:#b2b2b2;
    }




    .select-header-visited {
      border: 1px solid rgb(62, 165, 249);
      box-shadow: rgba(62, 165, 249, 0.5) 0px 0px 10px;
    }


    span.card {
      display: inline-block;
      padding: 0px 0px 0px 10px;
      margin: auto 2px;
      border: 1px solid #f0f0f0;
      border-radius: 2px;
      background-color: rgb(245, 245, 245);
      pointer-events: none;
      cursor: default;


      span {
        display: inline-block;
        margin-left: 2px;
        padding: 0 5px;
        color: rgba(0, 0, 0, 0.5);
        cursor: pointer;
        pointer-events: auto;
      }


      span:hover {
        color: rgba(0, 0, 0, 1);
      }

    }


  }


  /* 下拉框下拉列表 */

  .select-content {
    border-radius: 2px;
    border-left: 1px solid #ccc;
    border-bottom: 1px solid #ccc;
    border-right: 1px solid #ccc;
    box-shadow: 4px 4px 10px;

    li {
      width:100%;
      cursor: pointer;
      position: relative;
      padding-left: 15px;
    &::after{
      position:absolute;
      left: 3%;
      bottom: 0;
      content: " ";
      width:94%;
      height: 1px;
      background: #ccc;
    }


      // &.active{

      // }
    }
  }


}

解决react/antd select插件只能返回一个或者一列返回值实属无奈自己参考网络上大佬写的半成品手噜了一个_第1张图片

你可能感兴趣的:(react,react.js,javascript,前端)