封装一个漂亮的ant design form标签组件
在ant design 的form组件中 能用于提交的组件比较少,所以我在这写了一个可以单选、多选标签提交的组件,调用非常简单。
代码:
1 import React,{Fragment} from 'react'; 2 import { Tag,Icon,Input } from 'antd'; 3 export interface TagDataType{ 4 data:string, 5 color:string, 6 key:string 7 } 8 export interface Props { 9 data:Array<TagDataType>, 10 click?:boolean,//是否可点击 11 defaultKey?:string | Array<string>,//默认选择tag的key 12 checkbox?:boolean,//多选 13 form?:any,//form表单 14 dataValidationName?:string,//设置提交名称,若用此参数提交则提交选中的data,用于菜单提交获取 15 keyValidationName?:string,//设置提交名称,若用此参数提交则提交选中的key,用于菜单提交获取 16 notNull?:boolean,//选项不能为空 17 } 18 19 export interface State { 20 keys:string,//选中的标签的key,用','分割 21 datas:string,//选中的标签的data,用','分割 22 styleState:number | Array<number>,//选中的下标集 23 } 24 25 class TagOpt extends React.Component<Props, State> { 26 constructor(props: Props) { 27 super(props); 28 //验证传入数据的合法性 29 if(this.props.notNull && !!!this.props.defaultKey){ 30 throw Error('TagOpt选中项为空,设置defaultKey!'); 31 } 32 if(!!this.props.form && !!!this.props.keyValidationName && !!!this.props.dataValidationName){ 33 throw Error('若要使用form提交,请设置keyValidationName或dataValidationName!'); 34 } 35 this.state=this.setDefaultVal(); 36 } 37 //鼠标点击标签事件 38 TagClick = (tagData:TagDataType,index:number) =>{ 39 if(this.props.click !== undefined && this.props.click){ 40 if(this.props.checkbox){ 41 const optIf = this.optIf(index); 42 let styleState:Array<number> = new Array();; 43 if(typeof this.state.styleState === 'object'){ 44 styleState = [...this.state.styleState]; 45 }else{ 46 styleState = [this.state.styleState]; 47 } 48 if(optIf.state){ 49 //点击已选择 50 //如果设置不为空且选中选项大于1或者没有设置不为空选项 51 //则清空 52 if(this.props.notNull && styleState.length>1 || !!!this.props.notNull){ 53 styleState.splice(optIf.index,1); 54 this.setState({ 55 keys:this.moveSubString(this.state.keys,tagData.key), 56 datas:this.moveSubString(this.state.datas,tagData.data), 57 styleState 58 },()=>{this.setVal(this.state.datas,'data');this.setVal(this.state.keys,'key')}); 59 } 60 }else{ 61 //点击未选择 62 styleState.splice(styleState.length,0,index); 63 this.setState({ 64 keys:this.addSubString(this.state.keys,tagData.key), 65 datas:this.addSubString(this.state.datas,tagData.data), 66 styleState 67 },()=>{this.setVal(this.state.datas,'data');this.setVal(this.state.keys,'key')}); 68 } 69 }else{ 70 if(this.state.styleState === index){ 71 //点击已选择 72 //若设置可以为空 73 //则清空 74 if(!!!this.props.notNull){ 75 this.setState({keys:'',datas:'',styleState:this.props.data.length} 76 ,()=>{this.setVal(this.state.datas,'data');this.setVal(this.state.keys,'key')}); 77 } 78 }else{ 79 //点击未选择 80 this.setState({keys:tagData.key,datas:tagData.data,styleState:index} 81 ,()=>{this.setVal(this.state.datas,'data');this.setVal(this.state.keys,'key')}); 82 } 83 } 84 } 85 } 86 //返回移出指定子串的字符串,移出所有重复子串 87 moveSubString = (str:string,subString:string):string => { 88 let array:Array<string> = str.split(','); 89 for(let i=0;i<array.length;i++){ 90 if(array[i] === subString){ 91 array.splice(i,1); 92 } 93 } 94 return array.toString(); 95 } 96 //返回增加子串的字符串,重复则不增加 97 addSubString = (str:string,subString:string|Array<string>) =>{ 98 if(typeof subString === 'string'){ 99 let comma = str !==''?',':''; 100 return str +comma+subString; 101 }else{ 102 let s:string = str; 103 for(let i=0;i<subString.length;i++){ 104 let comma = s !==''?',':''; 105 s+=comma+subString[i]; 106 } 107 return s; 108 } 109 } 110 //选择判断 111 optIf = (index:number):{state:boolean,index:number} => { 112 if(typeof this.state.styleState ==='number'){ 113 return {state:this.state.styleState === index,index:0}; 114 }else{ 115 let falg:boolean = false; 116 const styleState = this.state.styleState; 117 let i=0; 118 for(;i<styleState.length;i++){ 119 if(styleState[i] === index){ 120 falg = true; 121 break; 122 } 123 } 124 return {state:falg,index:i}; 125 } 126 } 127 //写入表单 128 setVal = (data:string,type:string) => { 129 if(this.props.form != undefined){ 130 let json:object = {} 131 if(type === 'data'){ 132 if(this.props.dataValidationName !== undefined){ 133 json[this.props.dataValidationName] = data; 134 this.props.form.setFieldsValue(json); 135 } 136 }else if(type === 'key'){ 137 if(this.props.keyValidationName !== undefined){ 138 json[this.props.keyValidationName] = data; 139 this.props.form.setFieldsValue(json); 140 } 141 } 142 } 143 } 144 //默认值转换 145 setDefaultVal=():State=>{ 146 if(this.props.checkbox){ 147 //多选框,值为1个或数组 148 let styleState:Array<number> = new Array(); 149 let keys:Array<string> = new Array(); 150 let datas:Array<string> = new Array(); 151 const {defaultKey,data} = this.props; 152 if(typeof defaultKey === 'object'){ 153 for(let i=0;i<defaultKey.length;i++){ 154 for(let j=0;j<data.length;j++){ 155 if(defaultKey[i] === data[j].key){ 156 styleState.push(i); 157 keys.push(data[j].key); 158 datas.push(data[j].data); 159 } 160 } 161 } 162 return { 163 keys:this.addSubString('',keys), 164 datas:this.addSubString('',datas), 165 styleState 166 } 167 }else{ 168 let i:number = 0; 169 let key:string = ''; 170 let dat:string = ''; 171 for(;i<data.length;i++){ 172 if(data[i].key === defaultKey){ 173 key=data[i].key; 174 dat=data[i].data; 175 break; 176 } 177 } 178 return { keys:key,datas:dat,styleState: i }; 179 } 180 }else if(this.props.checkbox === undefined && typeof this.props.defaultKey ==='string' || 181 !this.props.checkbox && typeof this.props.defaultKey ==='string'){ 182 //多选未设置且默认值为1个或单选且默认值为一个 183 let i:number = 0; 184 let key:string = ''; 185 let dat:string = ''; 186 if(this.props.defaultKey !== undefined){ 187 const data = this.props.data; 188 for(;i<data.length;i++){ 189 if(data[i].key === this.props.defaultKey){ 190 key=data[i].key; 191 dat=data[i].data; 192 break; 193 } 194 } 195 } 196 return { keys:key,datas:dat,styleState: i }; 197 }else if(this.props.defaultKey === undefined || this.props.defaultKey === '' || this.props.defaultKey === []){ 198 if(this.props.checkbox){ 199 return { keys:'',datas:'',styleState: [] }; 200 }else{ 201 return { keys:'',datas:'',styleState: this.props.data.length }; 202 } 203 }else{ 204 return {keys:'',datas:'',styleState: this.props.data.length}; 205 } 206 } 207 render() { 208 const content:any = this.props.data.map((tagData:TagDataType,index:number)=>{ 209 const cursor:any = this.props.click !== undefined && this.props.click ?'pointer':'default'; 210 return( 211 <Tag color={tagData.color} key={tagData.key} onClick={this.TagClick.bind(this,tagData,index)} style={{cursor}}> 212 {tagData.data} 213 {this.optIf(index).state?<Icon type="check" />:undefined} 214 </Tag> 215 ) 216 }); 217 return ( 218 <Fragment> 219 {content} 220 { 221 !!this.props.click && !!this.props.form && !!this.props.form.getFieldDecorator && !!this.props.keyValidationName? 222 this.props.form.getFieldDecorator(this.props.keyValidationName, { 223 initialValue:this.state.keys, 224 })(<Input type="hidden"/>) 225 :undefined 226 } 227 { 228 !!this.props.click && !!this.props.form &&!!this.props.form.getFieldDecorator && !!this.props.dataValidationName 229 && !!!this.props.keyValidationName? 230 this.props.form.getFieldDecorator(this.props.dataValidationName, { 231 initialValue:this.state.datas, 232 })(<Input type="hidden"/>) 233 :undefined 234 } 235 </Fragment> 236 ); 237 } 238 } 239 export default TagOpt;
效果:
也可以在普通页面中调用:
获取值
效果: