实现功能:勾选checkbox项,确定后,已勾选的checkbox项以tag标签的形式展示,tag标签可快捷删除。



实现过程:

  • 使用React。
  • 使用Ant Design的Checkbox、Tag组件。
  • 整个组件主要分为两个部分:多选框组和Tag标签组。

1. 多选框组

class AddInfo extends React.Component {
constructor(props) {
super(props);
this.state = {
checkedList: [], // checkbox已选择的选项
indeterminate: [], // 全选框-已有选择非全选
checkAll: {}, // checkbox group 的全部title状态true/false
tempList: [], // 临时存储checkbox已选择的选项
checkTitle: {} // checkbox group中已选择的title(全选)
};
} /* 确定勾选 */
handleOk = () => {
if (this.state.tempList.length > 0) {
// 将已选择信息传给Tags组件
this.props.getChecked({
checkedItem: this.state.tempList,
checkAll: this.state.checkAll,
indeterminate: this.state.indeterminate,
checkTitle: this.state.checkTitle
});
}
} /* checkbox单选 */
onChange = (allCheckArr, checkedList) => {
let checkAll = this.state.checkAll;
let indeterminate = [];
let checkTitle = {};
Object.keys(allCheckArr).forEach((title) => {
checkTitle[title] = 0;
for (let checkedItem of checkedList || []) {
if (allCheckArr[title].includes(checkedItem)) {
checkTitle[title]++;
checkAll[title] = checkTitle[title] === allCheckArr[title].length;
indeterminate[title] = !!checkTitle[title] && (checkTitle[title] < allCheckArr[title].length);
}
}
if (checkTitle[title] === 0) { // 选项组下仅有一个选项时取消选中
checkAll[title] = false;
}
});
this.setState({
checkedList,
tempList:checkedList,
indeterminate: indeterminate,
checkAll: checkAll,
checkTitle: checkTitle
});
} /* checkbox全选 */
onCheckAllChange = (allCheckArr, title, e) => {
this.state.checkAll[title] = e.target.checked;
let checkedListT = [];
checkedListT.push(...this.state.checkedList);
let indeterminate = this.state.indeterminate || [];
let checkTitle = this.state.checkTitle || {};
if (e.target.checked === true) { // 全选
checkedListT.push(...allCheckArr[title]);
checkedListT = Array.from(new Set(checkedListT)); // 去重(原先indeterminate为true的情况)
checkTitle[title] = allCheckArr[title].length;
} else { // 取消全选
let common = checkedListT.filter(v => allCheckArr[title].includes(v));
checkedListT = checkedListT.concat(common).filter(v => checkedListT.includes(v) && !common.includes(v));
checkTitle[title] = 0;
}
indeterminate[title] = false;
this.setState({
tempList: checkedListT,
checkedList: checkedListT,
indeterminate: indeterminate,
checkTitle: checkTitle
});
} render() {
const { checkedList, checkAll, indeterminate } = this.state;
const { allCheckArr } = this.props;
return (
<div className={styles.modalcontent} >
{
allCheckArr.map( ({ title, value }, key ) => (
<div className={styles.checksgroup}>
<div>
<Checkbox
indeterminate={indeterminate[title]}
onChange={this.onCheckAllChange.bind(this, allCheckArr, title)}
checked={checkAll[title]}
>
{title}
</Checkbox>
</div>
<br />
<CheckboxGroup className={styles.contents} options={value} value={checkedList} onChange={this.onChange.bind(this, allCheckArr)} />
</div>
))}
</div>
);
}
} export default AddInfo;
  • 由于Ant Design官网上checkbox group的示例代码只有一个check group,本组件是可以有多组的情况,因此主要通过checkedList,checkAll,indeterminate,checkTitle几个状态控制checkbox group与单个的checkbox的全勾选、半勾选、无勾选几种情况的联动。
  • checkbox单选的操作是传入当前选择的所有的选项,然后与原先的可选项对比,计算出checkAll,indeterminate,checkTitle的值。每次要先将checkAll,indeterminate,checkTitle置空,遍历所有的已选项和待选项。
  • checkbox全选的函数本来是可以复用单选的操作,但是全选之后得出checkAll,indeterminate,checkTitle的值的过程比单选更简单一些,不用遍历选项数组,所以重写了全选的逻辑,没有复用单选的函数,虽然代码量多几行,但是执行过程更简单一些。

2. Tag标签组

import React from 'react';
import { Tag } from 'antd';
import styles from './index.less'; class Tags extends React.Component {
constructor(props) {
super(props);
this.state = {
items: this.props.items, // 需要显示的tag数组
checkAll: this.props.checkAll, // 该tag所在的数组元素是否全部作为tag存在
indeterminate: this.props.indeterminate, // 该tag所在的数组元素是否部分作为tag存在
allCheckArr: this.props.allCheckArr, // 该tag所在的数组
checkTitle: this.props.checkTitle // 该tag所在的数组元素作为tag存在的数量
};
}
componentWillReceiveProps = ( value, nextState) => {
this.setState({
items: value.items,
checkAll: value.checkAll,
indeterminate: value.indeterminate,
allCheckArr: value.allCheckArr,
checkTitle: value.checkTitle
});
} delete = (key, value, e) => {
e.preventDefault();
let items = this.state.items;
let checkAll = this.state.checkAll;
let indeterminate = this.state.indeterminate;
let allCheckArr = this.state.allCheckArr;
let checkTitle = this.state.checkTitle;
items.splice(key, 1);
for (let title in allCheckArr) {
for (let item of allCheckArr[title]) {
if (item === value) {
checkTitle[title]--;
checkAll[title] = false;
if (checkTitle[title] === 0) { // 该选项组下的选项全部删除
indeterminate[title] = false;
} else {
indeterminate[title] = true;
}
}
}
}
this.setState({
items: items,
checkAll: checkAll,
indeterminate: indeterminate,
checkTitle: checkTitle
});
this.props.changeCheckeditems(items);
}
render() {
const items = this.state.items?this.state.items:[];
return (
<div>
{
items.map((value, key) => (
<Tag className={styles.singletag} closable key={key} onClose={this.delete.bind(this, key, value)}>{value}</Tag>
))}
</div>
);
}
} export default Tags;

在多选框组对选项勾选之后,将选择结果传入Tags标签组件,该组件以Tag标签将已勾选的选项展示出来。Tag标签可以点击右边的“x”快捷删除,删除后,多选框组中相应的选项也会取消勾选。

3. 组件使用

这两个组件放在同一个父组件中使用,实现值传递。

class parent extends React.Component {
/* 获取待选择选项 */
getAllCheckArr = () => {
...
this.setState({
allCheckArr
...
});
...
} /* 获取checkbox选择的选项 */
getChecked = (val) => {
this.setState({
checkedItem: val.checkedItem,
checkAll: val.checkAll,
indeterminate: val.indeterminate,
checkTitle: val.checkTitle
});
} /* 获取tags删除后的选项 */
changeChecked = (val) => {
...
this.setState({
changedItem: val
});
...
}
render() {
const { checkedItem, changedItem,, checkAll, indeterminate, checkTitle } = this.state;
return (
...
<AddInfo
checkList={this.state.checkedItem}
allCheckArr={this.state.allCheckArr|| []}
getChecked={this.getChecked.bind(this)}
/>
<Tags
allCheckArr={this.state.allCheckArr|| []}
checkAll={checkAll}
checkTitle={checkTitle}
indeterminate={indeterminate}
items={checkedItem}
changeChecked={this.changeChecked.bind(this)}
/>
...
);
}
}

代码经过了比较大程度的删改,删除了许多无关功能,只保留了组件功能的核心部分,因此直接copy可能会有报错。。。

React实现checkbox group多组选项和标签组显示的联动的更多相关文章

  1. 关于 ant Checkbox.Group 数组checked 设置失效问题

    最近在频繁使用ant UI框架.在使用到checkbox的时候,需要从后台获取数组显示,然后发现数组设置了checked:true,并不能使多选框处于选中状态,阅读 Checkbox Group 的属 ...

  2. 浅谈 Checkbox Group 的双向数据绑定

    前言 不曾想在忙碌的工作面前,写一篇技术博客也成了奢求. Checkbox 作为表单中最常见的一类元素,使用方式分为单值和多值,其中单值的绑定很简单,就是 true 和 false,但是多值(Chec ...

  3. 【翻译】从Store生成Checkbox Group

    原文:Ext JS: Generating a Checkbox Group from a Store Ext JS的checkbox group可以用来将复选框组合成一个单一的逻辑字段.由于复选框时 ...

  4. 重新想象 Windows 8 Store Apps (12) - 控件之 GridView 特性: 拖动项, 项尺寸可变, 分组显示

    原文:重新想象 Windows 8 Store Apps (12) - 控件之 GridView 特性: 拖动项, 项尺寸可变, 分组显示 [源码下载] 重新想象 Windows 8 Store Ap ...

  5. 含有GROUP BY子句的查询中如何显示COUNT()为0的成果(分享)

    在SQL Server数据库查询中,为了对查询成果进行对比.解析,我们经常会用到GROUP BY子句以及COUNT()函数来对查询成果进行分类.统计等.然则我们在应用的过程中往往会存在一些题目,本文我 ...

  6. group by分组后获得每组中符合条件的那条记录

    当group by单独使用时,只显示出每组的第一条记录.如下,未分组时查询出两条记录 SELECT info.id, info.switch_id, info.port_id, info.mac_ad ...

  7. JS判断checkbox至少选择一项

    function Check() { if(checkboxs("checkboxname") == false){ // checkboxname: checkbox的名字 al ...

  8. CheckBox只选择一项

    最近做一个问卷的页面,客户那边说要使用checkbox而且只能选择一项 就写了下面的代码 <html xmlns="http://www.w3.org/1999/xhtml" ...

  9. checkbox 最多选两项

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

随机推荐

  1. thinkphp3.2.3 excel导出,下载文件,包含图片

    关于导出后出错的问题 https://segmentfault.com/q/1010000005330214 https://blog.csdn.net/ohmygirl/article/detail ...

  2. 使用Opencv中matchTemplate模板匹配方法跟踪移动目标

    模板匹配是一种在图像中定位目标的方法,通过把输入图像在实际图像上逐像素点滑动,计算特征相似性,以此来判断当前滑块图像所在位置是目标图像的概率. 在Opencv中,模板匹配定义了6种相似性对比方式: C ...

  3. mysqldump备份脚本

    #!/bin/bash # 10 23 * * * /bin/bash /data/script/backup_mysqldump.sh BDATE=`date +%Y%m%d%H%M%S`BPATH ...

  4. php实现 求int型数据在内存中存储时1的个数(函数都可自己实现)

    php实现 求int型数据在内存中存储时1的个数(函数都可自己实现) 一.总结 一句话总结:函数我们自己都可以实现,尤其是很多基础函数,没有工具的时候自己写. 1.php进制转换函数? base_co ...

  5. js进阶正则表达式9量词2(^和&作用:/^HTML5$/g匹配不到aHTML5b中的HTML5,不然是可以匹配到的)(/\d+(?=cm)/g)((?!cm))

    js进阶正则表达式9量词2(^和&作用:/^HTML5$/g匹配不到aHTML5b中的HTML5,不然是可以匹配到的)(/\d+(?=cm)/g)((?!cm)) 一.总结 ^和&作用 ...

  6. kindeditor4跨域上传图片解决

    项目中正在使用kindeditor, 版本号4.1.10 非常多公司的图片会走CDN,须要单独的一台图片上传服务如:(upload.268xue.com) kindeditor上传图片的简单内部流程: ...

  7. [DevExpress]DevExpress 中 汉化包 汉化方法

    第一步: 在Debug 下加入 zh-CN 汉化包(自行下载) 第二步: 在 Program.cs中加入下面代码 : System.Threading.Thread.CurrentThread.Cur ...

  8. tensorflow 的使用流程

    1. optimizer.minimize 与 global_step optimizer = tf.train.**(learning_rate) global_step = tf.Variable ...

  9. 开源库Fab-Transformation简单使用解析

    转载请注明出处王亟亟的大牛之路 相似于IPhone的悬浮按钮的操作,仅仅只是是固定的,当然经过自己的改动也能够动.这边仅仅是给伸手党一个福祉,外加加上一些自己的理解.让大家能够拿来就用.看了就懂,废话 ...

  10. 学习鸟哥的Linux私房菜笔记(1)——Linux系统入门

    今天在阿里云申请了一个centos系统的云服务器,以前对linux了解的只是皮毛,记了几个命令还给忘了,整了半天都弄不好,作为一个做过javaweb开发的coder实在是惭愧啊,决定从今天开始学习Li ...