React实现checkbox group多组选项和标签组显示的联动
实现功能:勾选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多组选项和标签组显示的联动的更多相关文章
- 关于 ant Checkbox.Group 数组checked 设置失效问题
最近在频繁使用ant UI框架.在使用到checkbox的时候,需要从后台获取数组显示,然后发现数组设置了checked:true,并不能使多选框处于选中状态,阅读 Checkbox Group 的属 ...
- 浅谈 Checkbox Group 的双向数据绑定
前言 不曾想在忙碌的工作面前,写一篇技术博客也成了奢求. Checkbox 作为表单中最常见的一类元素,使用方式分为单值和多值,其中单值的绑定很简单,就是 true 和 false,但是多值(Chec ...
- 【翻译】从Store生成Checkbox Group
原文:Ext JS: Generating a Checkbox Group from a Store Ext JS的checkbox group可以用来将复选框组合成一个单一的逻辑字段.由于复选框时 ...
- 重新想象 Windows 8 Store Apps (12) - 控件之 GridView 特性: 拖动项, 项尺寸可变, 分组显示
原文:重新想象 Windows 8 Store Apps (12) - 控件之 GridView 特性: 拖动项, 项尺寸可变, 分组显示 [源码下载] 重新想象 Windows 8 Store Ap ...
- 含有GROUP BY子句的查询中如何显示COUNT()为0的成果(分享)
在SQL Server数据库查询中,为了对查询成果进行对比.解析,我们经常会用到GROUP BY子句以及COUNT()函数来对查询成果进行分类.统计等.然则我们在应用的过程中往往会存在一些题目,本文我 ...
- group by分组后获得每组中符合条件的那条记录
当group by单独使用时,只显示出每组的第一条记录.如下,未分组时查询出两条记录 SELECT info.id, info.switch_id, info.port_id, info.mac_ad ...
- JS判断checkbox至少选择一项
function Check() { if(checkboxs("checkboxname") == false){ // checkboxname: checkbox的名字 al ...
- CheckBox只选择一项
最近做一个问卷的页面,客户那边说要使用checkbox而且只能选择一项 就写了下面的代码 <html xmlns="http://www.w3.org/1999/xhtml" ...
- checkbox 最多选两项
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
随机推荐
- 开源分享三(炫酷的Android Loading动画)
开源分享三(炫酷的Android Loading动画) 分享GitHub上的一些Loading,为了提升产品用户体验,一个好的Loading必然是不可缺少的,对于一些耗时需要用户等待的页面来说会转移用 ...
- Swift3.0 功能二 (表情键盘与图文混排)
随着iOS越来越多表情键盘以及图文混排的需求,本文运用Swift3.0系统的实现其功能以及封装调用方法,写的不好,如有错误望各位提出宝贵意见,多谢 项目源码地址: 相关知识点都有标识 项目源码地址 废 ...
- JavaWeb网站技术架构
JavaWeb网站技术架构总结 题记 工作也有几多年了,无论是身边遇到的还是耳间闻到的,多多少少也积攒了自己的一些经验和思考,当然,博主并没有太多接触高大上的分布式架构实践,相对比较零碎,随时补充 ...
- form表单嵌套,用标签的form属性来解决表单嵌套的问题
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- [Recompose] Add Local State to a Functional Stateless Component using Recompose
Learn how to use the 'withState' and 'withHandlers' higher order components to easily add local stat ...
- ios开发网络学习五:MiMEType ,多线程下载文件思路,文件的压缩和解压缩
一:MiMEType:一般可以再百度上搜索到相应文件的MiMEType,或是利用c语言的api去获取文件的MiMEType : //对该文件发送一个异步请求,拿到文件的MIMEType - (void ...
- TextView之一:子类的常用属性 分类: H1_ANDROID 2013-10-30 15:14 770人阅读 评论(0) 收藏
TextView常见的子类包括EditText,Button,CheckBox, RadioButton等. 1.EditText EditText继承自TextView,因此TextView所有属性 ...
- 关于LayoutParams 分类: H1_ANDROID 2013-10-27 20:34 776人阅读 评论(0) 收藏
每一个布局均有一个叫LayoutParams的内部类,如: LinearLayout.LayoutParams RelativeLayout.LayoutParams AbsoluteLayout ...
- Seagate-保修验证(za25shrx)
保修验证 http://support.seagate.com/customer/zh-CN/warranty_validation.jsp Seagate 保修验证 End User ...
- java 多线程(三)条件对象
转载请注明出处:http://blog.csdn.net/xingjiarong/article/details/47417383 在上一篇博客中,我们学会了用ReentrantLock来控制线程訪问 ...