在ant design 的form组件中 能用于提交的组件比较少,所以我在这写了一个可以单选、多选标签提交的组件,调用非常简单。

代码:

 import React,{Fragment} from 'react';
import { Tag,Icon,Input } from 'antd';
export interface TagDataType{
data:string,
color:string,
key:string
}
export interface Props {
data:Array<TagDataType>,
click?:boolean,//是否可点击
defaultKey?:string | Array<string>,//默认选择tag的key
checkbox?:boolean,//多选
form?:any,//form表单
dataValidationName?:string,//设置提交名称,若用此参数提交则提交选中的data,用于菜单提交获取
keyValidationName?:string,//设置提交名称,若用此参数提交则提交选中的key,用于菜单提交获取
notNull?:boolean,//选项不能为空
} export interface State {
keys:string,//选中的标签的key,用','分割
datas:string,//选中的标签的data,用','分割
styleState:number | Array<number>,//选中的下标集
} class TagOpt extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
//验证传入数据的合法性
if(this.props.notNull && !!!this.props.defaultKey){
throw Error('TagOpt选中项为空,设置defaultKey!');
}
if(!!this.props.form && !!!this.props.keyValidationName && !!!this.props.dataValidationName){
throw Error('若要使用form提交,请设置keyValidationName或dataValidationName!');
}
this.state=this.setDefaultVal();
}
//鼠标点击标签事件
TagClick = (tagData:TagDataType,index:number) =>{
if(this.props.click !== undefined && this.props.click){
if(this.props.checkbox){
const optIf = this.optIf(index);
let styleState:Array<number> = new Array();;
if(typeof this.state.styleState === 'object'){
styleState = [...this.state.styleState];
}else{
styleState = [this.state.styleState];
}
if(optIf.state){
//点击已选择
//如果设置不为空且选中选项大于1或者没有设置不为空选项
//则清空
if(this.props.notNull && styleState.length>1 || !!!this.props.notNull){
styleState.splice(optIf.index,1);
this.setState({
keys:this.moveSubString(this.state.keys,tagData.key),
datas:this.moveSubString(this.state.datas,tagData.data),
styleState
},()=>{this.setVal(this.state.datas,'data');this.setVal(this.state.keys,'key')});
}
}else{
//点击未选择
styleState.splice(styleState.length,0,index);
this.setState({
keys:this.addSubString(this.state.keys,tagData.key),
datas:this.addSubString(this.state.datas,tagData.data),
styleState
},()=>{this.setVal(this.state.datas,'data');this.setVal(this.state.keys,'key')});
}
}else{
if(this.state.styleState === index){
//点击已选择
//若设置可以为空
//则清空
if(!!!this.props.notNull){
this.setState({keys:'',datas:'',styleState:this.props.data.length}
,()=>{this.setVal(this.state.datas,'data');this.setVal(this.state.keys,'key')});
}
}else{
//点击未选择
this.setState({keys:tagData.key,datas:tagData.data,styleState:index}
,()=>{this.setVal(this.state.datas,'data');this.setVal(this.state.keys,'key')});
}
}
}
}
//返回移出指定子串的字符串,移出所有重复子串
moveSubString = (str:string,subString:string):string => {
let array:Array<string> = str.split(',');
for(let i=0;i<array.length;i++){
if(array[i] === subString){
array.splice(i,1);
}
}
return array.toString();
}
//返回增加子串的字符串,重复则不增加
addSubString = (str:string,subString:string|Array<string>) =>{
if(typeof subString === 'string'){
let comma = str !==''?',':'';
return str +comma+subString;
}else{
let s:string = str;
for(let i=0;i<subString.length;i++){
let comma = s !==''?',':'';
s+=comma+subString[i];
}
return s;
}
}
//选择判断
optIf = (index:number):{state:boolean,index:number} => {
if(typeof this.state.styleState ==='number'){
return {state:this.state.styleState === index,index:0};
}else{
let falg:boolean = false;
const styleState = this.state.styleState;
let i=0;
for(;i<styleState.length;i++){
if(styleState[i] === index){
falg = true;
break;
}
}
return {state:falg,index:i};
}
}
//写入表单
setVal = (data:string,type:string) => {
if(this.props.form != undefined){
let json:object = {}
if(type === 'data'){
if(this.props.dataValidationName !== undefined){
json[this.props.dataValidationName] = data;
this.props.form.setFieldsValue(json);
}
}else if(type === 'key'){
if(this.props.keyValidationName !== undefined){
json[this.props.keyValidationName] = data;
this.props.form.setFieldsValue(json);
}
}
}
}
//默认值转换
setDefaultVal=():State=>{
if(this.props.checkbox){
//多选框,值为1个或数组
let styleState:Array<number> = new Array();
let keys:Array<string> = new Array();
let datas:Array<string> = new Array();
const {defaultKey,data} = this.props;
if(typeof defaultKey === 'object'){
for(let i=0;i<defaultKey.length;i++){
for(let j=0;j<data.length;j++){
if(defaultKey[i] === data[j].key){
styleState.push(i);
keys.push(data[j].key);
datas.push(data[j].data);
}
}
}
return {
keys:this.addSubString('',keys),
datas:this.addSubString('',datas),
styleState
}
}else{
let i:number = 0;
let key:string = '';
let dat:string = '';
for(;i<data.length;i++){
if(data[i].key === defaultKey){
key=data[i].key;
dat=data[i].data;
break;
}
}
return { keys:key,datas:dat,styleState: i };
}
}else if(this.props.checkbox === undefined && typeof this.props.defaultKey ==='string' ||
!this.props.checkbox && typeof this.props.defaultKey ==='string'){
//多选未设置且默认值为1个或单选且默认值为一个
let i:number = 0;
let key:string = '';
let dat:string = '';
if(this.props.defaultKey !== undefined){
const data = this.props.data;
for(;i<data.length;i++){
if(data[i].key === this.props.defaultKey){
key=data[i].key;
dat=data[i].data;
break;
}
}
}
return { keys:key,datas:dat,styleState: i };
}else if(this.props.defaultKey === undefined || this.props.defaultKey === '' || this.props.defaultKey === []){
if(this.props.checkbox){
return { keys:'',datas:'',styleState: [] };
}else{
return { keys:'',datas:'',styleState: this.props.data.length };
}
}else{
return {keys:'',datas:'',styleState: this.props.data.length};
}
}
render() {
const content:any = this.props.data.map((tagData:TagDataType,index:number)=>{
const cursor:any = this.props.click !== undefined && this.props.click ?'pointer':'default';
return(
<Tag color={tagData.color} key={tagData.key} onClick={this.TagClick.bind(this,tagData,index)} style={{cursor}}>
{tagData.data}
{this.optIf(index).state?<Icon type="check" />:undefined}
</Tag>
)
});
return (
<Fragment>
{content}
{
!!this.props.click && !!this.props.form && !!this.props.form.getFieldDecorator && !!this.props.keyValidationName?
this.props.form.getFieldDecorator(this.props.keyValidationName, {
initialValue:this.state.keys,
})(<Input type="hidden"/>)
:undefined
}
{
!!this.props.click && !!this.props.form &&!!this.props.form.getFieldDecorator && !!this.props.dataValidationName
&& !!!this.props.keyValidationName?
this.props.form.getFieldDecorator(this.props.dataValidationName, {
initialValue:this.state.datas,
})(<Input type="hidden"/>)
:undefined
}
</Fragment>
);
}
}
export default TagOpt;

效果:

也可以在普通页面中调用:

获取值

效果:

封装一个漂亮的ant design form标签组件的更多相关文章

  1. 2017.11.6 - ant design table等组件的使用,以及 chrome 中 network 的使用

    一.今日主要任务 悉尼小程序后台管理开发: 景点管理页面: 获取已有数据列表,选取部分数据呈现在表格中,根据景点名称.分类过滤出对应的景点.   二.难点 1. 项目技术选取: ant design. ...

  2. 使用Ant Design的select组件时placeholder不生效/不起作用的解决办法

    先来说说使用Ant Design和Element-ui的感觉吧. 公司的项目开发中用的是vue+element-ui,使用了一通下来后,觉得element-ui虽然也有一些问题或坑,但这些小问题或坑凭 ...

  3. react的ant design的UI组件库

    PC官网:https://ant.design/ 移动端网址:https://mobile.ant.design/docs/react/introduce-cn antd-mobile :是 Ant ...

  4. 基于ant design form的二次封装

    // standardForm.js import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; ...

  5. ant design 的Table组件固定表头时不对齐

    现在有一个表格,里面的列数是不固定的(可以重复写入数据),且列数行数都可能很多,就带来一个问题: 必须要固定表头,但是antd 的表格组件设置了固定表格 scroll={{x:1000,y:300}} ...

  6. Ant Design 日期选择组件RangePicker 选择时间范围后计算范围内的天数。

    /** *需求:同年同月,同年不同月(两个月相减大于1,小于1),不同年(两个年相减大于1(是否为闰年),小于1),起止包含的月份及天 */ //首先引入组件 import { DatePicker} ...

  7. Ant Design of Vue 组件库的使用

    文档里面很清楚 安装步骤    这是全部引入的 1  有的组价涉及到汉化的问题 import moment from 'moment' import '../../../../node_modules ...

  8. 使用Ant Design写一个仿微软ToDo

    实习期的第一份活,自己看Ant Design的官网学习,然后用Ant Design写一个仿微软ToDo. 不做教学目的,只是记录一下. 1.学习 Ant Design 是个组件库,想要会用,至少要知道 ...

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

    使用场景,在一个列表中,点击每一行会弹出一个表单,通过修改表单数据并提交来修改这一行的数据,其中某个数据的填写需要通过Mention实现动态提示及自动补全的功能. 具体效果为: 遇到的问题: 1.希望 ...

随机推荐

  1. LightOJ-1370 Bi-shoe and Phi-shoe (欧拉函数+二分)

    Problem Description Bamboo Pole-vault is a massively popular sport in Xzhiland. And Master Phi-shoe ...

  2. python:创建文件

    #!/usr/bin/python# -*- coding:utf-8 -*- open('a.txt','w+')

  3. 如何把U盘的两个盘或者多个盘合成一个

    1.插入U盘,导出所有重要数据. 2.右击我的电脑,点管理打开设备管理器. 3.在设备管理器里找到磁盘管理. 4.在磁盘管理右侧出现下图: 5.如图是windows 7的界面. 6.找到U盘,图上是磁 ...

  4. Python2安装MySQLdb

    在http://www.lfd.uci.edu/~gohlke/pythonlibs/#mysql-python下载对应的包版本,如果是win7 64位2.7版本的python,就下载 MySQL_p ...

  5. centos下配置mongodb定期备份

    https://brickyang.github.io/2017/03/02/Linux-%E8%87%AA%E5%8A%A8%E5%A4%87%E4%BB%BD-MongoDB/ 1.创建备份脚本 ...

  6. Paper: A novel visibility graph transformation of time series into weighted networks

    1. Convert time series into weighted networks. 2. link prediction is used to evaluate the performanc ...

  7. Tomcat 加载外部dll时如何配置

    1.在myeclipse环境下配置 先将dll放置在c:\windows\system32中,然后在myEclipse中,window->Preferences->MyEclipse-&g ...

  8. XPath注入

    XPath基础 XPath 即为 XML 路径语言,是一门在XML文档中查找信息的语言.XPath 基于 XML 的树状结构,有不同类型的节点,包括元素节点,属性节点和文本节点,提供在数据结构树中找寻 ...

  9. 解决“(1146, "Table 'mydb.django_session' doesn't exist")”报错的方法

    执行 ./manage.py makemigrations sessions ./manage.py migrate sessions

  10. 题解 【Codeforces387B】George and Round

    以下选自官方题解: 考虑困难的需求数量,我们将覆盖这些困难, 然后我们将提出新的问题,并准备新的问题来覆盖其他需求. 很明显,如果我们决定满足从n中抽取i的要求,那么最好采用那些复杂性最小的要求. 让 ...