mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-30 02:58:05 +08:00
Merge pull request #3463 from lghxuelang/feat-checkbox
feat: checkbox组件升级
This commit is contained in:
commit
bb4538b9f1
@ -199,7 +199,7 @@ exports[`options:linkage 2`] = `
|
||||
class="cxd-RadiosControl cxd-Form-control is-inline"
|
||||
>
|
||||
<label
|
||||
class="cxd-Checkbox cxd-Checkbox--radio cxd-Checkbox--full"
|
||||
class="cxd-Checkbox cxd-Checkbox--radio cxd-Checkbox--full cxd-Checkbox--button--disabled--unchecked"
|
||||
>
|
||||
<input
|
||||
disabled=""
|
||||
|
@ -67,12 +67,31 @@ order: 8
|
||||
|
||||
勾选上例中的勾选框,观察数据域变化,会发现勾选后值为`1`,而取消勾选后为`0`
|
||||
|
||||
## 按钮模式
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "form",
|
||||
"debug": true,
|
||||
"body": [
|
||||
{
|
||||
"name": "checkbox",
|
||||
"type": "checkbox",
|
||||
"label": "勾选框",
|
||||
"trueValue": true,
|
||||
"falseValue": false,
|
||||
"optionType": "button",
|
||||
"checked": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
## 属性表
|
||||
|
||||
除了支持 [普通表单项属性表](./formitem#%E5%B1%9E%E6%80%A7%E8%A1%A8) 中的配置以外,还支持下面一些配置
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 ## 二级标题 |
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
| ---------- | -------- | --------- | ---------------- |
|
||||
| option | `string` | | 选项说明 |
|
||||
| trueValue | `any` | `true` | 标识真值 |
|
||||
| falseValue | `any` | `"false"` | 标识假值 |
|
||||
| trueValue | `string|number|boolean` | `true` | 标识真值 |
|
||||
| falseValue | `string|number|boolean` | `false` | 标识假值 |
|
||||
| optionType | `default|button` | `default` | 设置option类型 |
|
||||
|
@ -43,6 +43,40 @@ order: 9
|
||||
]
|
||||
}
|
||||
```
|
||||
## 按钮模式
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "form",
|
||||
"api": "/api/mock2/form/saveForm",
|
||||
"body": [
|
||||
{
|
||||
"name": "checkboxes",
|
||||
"type": "checkboxes",
|
||||
"label": "复选框",
|
||||
"optionType": "button",
|
||||
"options": [
|
||||
{
|
||||
"label": "OptionA",
|
||||
"value": "a"
|
||||
},
|
||||
{
|
||||
"label": "OptionB",
|
||||
"value": "b"
|
||||
},
|
||||
{
|
||||
"label": "OptionC",
|
||||
"value": "c"
|
||||
},
|
||||
{
|
||||
"label": "OptionD",
|
||||
"value": "d"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 按列显示
|
||||
|
||||
|
@ -493,6 +493,12 @@
|
||||
--Checkbox-onHover-color: var(--info);
|
||||
--Checkbox-onDisabled-bg: #e5e7eb;
|
||||
--Checkbox-onDisabled-color: var(--text--muted-color);
|
||||
--Checkbox-inner-onDisabled-bg: #D4D6D9;
|
||||
--Checkbox-disabled-unchecked-bg: #F2F3F3;
|
||||
--Checkbox-border-width: var(--Form-input-borderWidth);
|
||||
--Checkbox-paddingX: #{px2rem(12px)};
|
||||
--Checkbox-button-height: #{px2rem(32px)};
|
||||
--Checkbox-button-line-height: #{px2rem(30px)};
|
||||
|
||||
--ColorPicker-bg: var(--white);
|
||||
--ColorPicker-borderColor: var(--Form-input-borderColor);
|
||||
|
@ -152,12 +152,123 @@
|
||||
transition: width var(--animation-duration),
|
||||
height var(--animation-duration), transform var(--animation-duration);
|
||||
border-width: 0 0 px2rem(2px) px2rem(2px);
|
||||
transform: translate(-50%, -60%) rotate(-40deg);
|
||||
transform: translate(-50%, -90%) rotate(-40deg);
|
||||
border-style: solid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&--partial.#{$ns}Checkbox--checkbox {
|
||||
input {
|
||||
margin-left: calc(var(--Checkbox-size) * -1);
|
||||
|
||||
& + i {
|
||||
border-color: var(--Checkbox-onHover-color);
|
||||
|
||||
&:before {
|
||||
width: var(--Checkbox-inner-size);
|
||||
height: var(--Checkbox-inner-size);
|
||||
background: var(--Checkbox-onHover-color);
|
||||
}
|
||||
}
|
||||
|
||||
&[disabled] + i {
|
||||
border-color: var(--Checkbox-onDisabled-color);
|
||||
|
||||
&:before {
|
||||
width: var(--Checkbox-inner-size);
|
||||
height: var(--Checkbox-inner-size);
|
||||
background: var(--Checkbox-inner-onDisabled-bg);
|
||||
}
|
||||
}
|
||||
|
||||
&:checked[disabled] + i{
|
||||
width: var(--Checkbox-inner-size);
|
||||
height: var(--Checkbox-inner-size);
|
||||
background: var(--Checkbox-onDisabled-bg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
&--button.#{$ns}Checkbox--checkbox {
|
||||
text-align: center;
|
||||
height: var(--Checkbox-button-height);
|
||||
line-height: var(--Checkbox-button-line-height);
|
||||
padding-left: var(--Checkbox-paddingX);
|
||||
padding-right: var(--Checkbox-paddingX);
|
||||
font-size: var(--fontSizeSm);
|
||||
border: var(--Checkbox-border-width) solid;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
background-color: var(--Checkbox-gb);
|
||||
border-color: var(--Checkbox-color);
|
||||
margin-right: 0;
|
||||
|
||||
&:hover:not(:disabled){
|
||||
color: var(--Checkbox-onHover-color);
|
||||
}
|
||||
|
||||
input {
|
||||
&:checked + i {
|
||||
background: transparent;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-width: px2rem(8px);
|
||||
border-color: var(--Checkbox-onHover-color) transparent transparent var(--Checkbox-onHover-color);
|
||||
border-radius: 0;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: px2rem(8px);
|
||||
height: px2rem(6px);
|
||||
transform: translate(-80%, -120%) rotate(-50deg);
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&[disabled] + i {
|
||||
border-color: var(--Checkbox-onDisabled-color);
|
||||
background: transparent;
|
||||
&:before {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&:checked[disabled] + i {
|
||||
background: transparent;
|
||||
border-width: px2rem(8px);
|
||||
border-color: var(--Checkbox-onHover-color) transparent transparent var(--Checkbox-onHover-color);
|
||||
}
|
||||
}
|
||||
> i {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left:0;
|
||||
margin-left: 0;
|
||||
border: 0;
|
||||
border-style: solid;
|
||||
|
||||
+ span {
|
||||
max-width: px2rem(100px);
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
&--button--checked.#{$ns}Checkbox--checkbox {
|
||||
border-color: var(--Checkbox-onHover-color);
|
||||
color: var(--Checkbox-onHover-color);
|
||||
}
|
||||
&--button--disabled--unchecked.#{$ns}Checkbox--checkbox {
|
||||
background: var(--Checkbox-disabled-unchecked-bg);
|
||||
}
|
||||
&--radio {
|
||||
padding-left: var(--Radio-size);
|
||||
|
||||
@ -266,10 +377,20 @@
|
||||
margin-bottom: var(--Form-label-paddingTop);
|
||||
}
|
||||
|
||||
.#{$ns}Checkbox--button {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&.is-inline .#{$ns}Checkbox {
|
||||
display: inline-block;
|
||||
margin-right: var(--gap-md);
|
||||
}
|
||||
|
||||
&.is-inline .#{$ns}Checkbox--button {
|
||||
display: inline-block;
|
||||
margin-right: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.#{$ns}RadiosControl-group,
|
||||
|
@ -16,10 +16,10 @@ interface CheckboxProps {
|
||||
labelClassName?: string;
|
||||
className?: string;
|
||||
onChange?: (value: any, shift?: boolean) => void;
|
||||
value?: any;
|
||||
value?: boolean | string | number;
|
||||
inline?: boolean;
|
||||
trueValue?: any;
|
||||
falseValue?: any;
|
||||
trueValue?: boolean | string | number;
|
||||
falseValue?: boolean | string | number;
|
||||
disabled?: boolean;
|
||||
readOnly?: boolean;
|
||||
checked?: boolean;
|
||||
@ -28,6 +28,7 @@ interface CheckboxProps {
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
partial?: boolean;
|
||||
optionType?: 'default' | 'button';
|
||||
}
|
||||
|
||||
export class Checkbox extends React.Component<CheckboxProps, any> {
|
||||
@ -70,14 +71,19 @@ export class Checkbox extends React.Component<CheckboxProps, any> {
|
||||
checked,
|
||||
type,
|
||||
name,
|
||||
labelClassName
|
||||
labelClassName,
|
||||
optionType
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<label
|
||||
className={cx(`Checkbox Checkbox--${type}`, className, {
|
||||
'Checkbox--full': !partial,
|
||||
[`Checkbox--${size}`]: size
|
||||
'Checkbox--partial': partial,
|
||||
[`Checkbox--${size}`]: size,
|
||||
'Checkbox--button': optionType === 'button',
|
||||
'Checkbox--button--checked': optionType === 'button' && checked,
|
||||
'Checkbox--button--disabled--unchecked': disabled && !checked
|
||||
})}
|
||||
>
|
||||
<input
|
||||
|
@ -19,12 +19,12 @@ export interface CheckboxControlSchema extends FormBaseControl {
|
||||
/**
|
||||
* 勾选值
|
||||
*/
|
||||
trueValue?: any;
|
||||
trueValue?: boolean | string | number;
|
||||
|
||||
/**
|
||||
* 未勾选值
|
||||
*/
|
||||
falseValue?: any;
|
||||
falseValue?: boolean | string | number;
|
||||
|
||||
/**
|
||||
* 选项说明
|
||||
@ -35,6 +35,9 @@ export interface CheckboxControlSchema extends FormBaseControl {
|
||||
* 角标
|
||||
*/
|
||||
badge?: BadgeSchema;
|
||||
partial?: boolean;
|
||||
optionType?: 'default' | 'button';
|
||||
checked?: boolean;
|
||||
}
|
||||
|
||||
export interface CheckboxProps
|
||||
@ -89,6 +92,9 @@ export default class CheckboxControl extends React.Component<
|
||||
onChange,
|
||||
disabled,
|
||||
render,
|
||||
partial,
|
||||
optionType,
|
||||
checked,
|
||||
classPrefix: ns
|
||||
} = this.props;
|
||||
|
||||
@ -101,6 +107,9 @@ export default class CheckboxControl extends React.Component<
|
||||
falseValue={falseValue}
|
||||
disabled={disabled}
|
||||
onChange={(value: any) => this.dispatchChangeEvent(value)}
|
||||
partial={partial}
|
||||
optionType={optionType}
|
||||
checked={checked}
|
||||
>
|
||||
{option ? render('option', option) : null}
|
||||
</Checkbox>
|
||||
|
@ -56,6 +56,7 @@ export interface CheckboxesProps
|
||||
createBtnLabel: string;
|
||||
editable?: boolean;
|
||||
removable?: boolean;
|
||||
optionType?: 'default' | 'button'
|
||||
}
|
||||
|
||||
export default class CheckboxesControl extends React.Component<
|
||||
@ -68,7 +69,8 @@ export default class CheckboxesControl extends React.Component<
|
||||
placeholder: 'placeholder.noOption',
|
||||
creatable: false,
|
||||
inline: true,
|
||||
createBtnLabel: 'Select.createLabel'
|
||||
createBtnLabel: 'Select.createLabel',
|
||||
optionType: 'default'
|
||||
};
|
||||
|
||||
reload() {
|
||||
@ -98,6 +100,97 @@ export default class CheckboxesControl extends React.Component<
|
||||
onDelete && onDelete(item);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateBorderStyle();
|
||||
window.addEventListener('resize', this.updateBorderStyle);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
window.removeEventListener('resize', this.updateBorderStyle);
|
||||
}
|
||||
|
||||
@autobind
|
||||
updateBorderStyle() {
|
||||
if (this.props.optionType !== 'button') {
|
||||
return;
|
||||
}
|
||||
const wrapDom = this.refs.checkboxRef as HTMLElement;
|
||||
const wrapWidth = wrapDom.clientWidth;
|
||||
const childs = Array.from(wrapDom.children) as HTMLElement[];
|
||||
|
||||
childs.forEach(child => {
|
||||
child.style.borderRadius = '0';
|
||||
child.style.borderLeftWidth = '1px';
|
||||
child.style.borderTopWidth = '1px';
|
||||
});
|
||||
const childTotalWidth = childs.reduce((pre, next) =>
|
||||
pre + next.clientWidth, 0);
|
||||
if (childTotalWidth <= wrapWidth) {
|
||||
if (childs.length === 1) {
|
||||
childs[0].style.borderRadius = "4px";
|
||||
}
|
||||
else {
|
||||
childs[0].style.borderRadius = "4px 0 0 4px";
|
||||
childs[childs.length - 1].style.borderRadius = "0 4px 4px 0";
|
||||
childs.forEach((child, idx) => {
|
||||
idx !== 0 && (child.style.borderLeftWidth = '0');
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
let curRowWidth = 0;
|
||||
let curRow = 0;
|
||||
const rowNum = Math.floor(childTotalWidth / wrapWidth);
|
||||
const rowColArr: any[] = [];
|
||||
for (let i = 0; i <= rowNum; i++) {
|
||||
const arr: HTMLElement[] = [];
|
||||
rowColArr[i] = arr;
|
||||
}
|
||||
childs.forEach((child: HTMLElement, idx: number) => {
|
||||
curRowWidth += child.clientWidth;
|
||||
if (curRowWidth > wrapWidth) {
|
||||
curRowWidth = child.clientWidth;
|
||||
curRow++;
|
||||
}
|
||||
if (curRow > rowNum) {
|
||||
return;
|
||||
}
|
||||
rowColArr[curRow].push(child);
|
||||
});
|
||||
|
||||
rowColArr.forEach((row: HTMLElement[], rowIdx: number) => {
|
||||
if (rowIdx === 0) {
|
||||
row.forEach((r: HTMLElement, colIdx: number) => {
|
||||
r.style.borderRadius = '0';
|
||||
colIdx !== 0 && (r.style.borderLeftWidth = '0');
|
||||
row.length > rowColArr[rowIdx + 1].length
|
||||
&& (row[row.length - 1].style.borderBottomRightRadius = "4px");
|
||||
});
|
||||
row[0].style.borderTopLeftRadius = "4px";
|
||||
row[row.length - 1].style.borderTopRightRadius = "4px";
|
||||
}
|
||||
else if (rowIdx === rowNum) {
|
||||
row.forEach((r: HTMLElement, colIdx: number) => {
|
||||
r.style.borderRadius = '0';
|
||||
colIdx !== 0 && (r.style.borderLeftWidth = '0');
|
||||
r.style.borderTopWidth = '0';
|
||||
row[0].style.borderBottomLeftRadius = "4px";
|
||||
row[row.length - 1].style.borderBottomRightRadius = "4px";
|
||||
});
|
||||
}
|
||||
else {
|
||||
row.forEach((r: HTMLElement, colIdx: number) => {
|
||||
r.style.borderRadius = '0';
|
||||
colIdx !== 0 && (r.style.borderLeftWidth = '0');
|
||||
r.style.borderTopWidth = '0';
|
||||
row.length > rowColArr[rowIdx + 1].length
|
||||
&& (row[row.length - 1].style.borderBottomRightRadius = "4px");
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
renderGroup(option: Option, index: number) {
|
||||
const {classnames: cx, labelField} = this.props;
|
||||
|
||||
@ -136,7 +229,8 @@ export default class CheckboxesControl extends React.Component<
|
||||
labelField,
|
||||
removable,
|
||||
editable,
|
||||
translate: __
|
||||
translate: __,
|
||||
optionType
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
@ -149,6 +243,7 @@ export default class CheckboxesControl extends React.Component<
|
||||
inline={inline}
|
||||
labelClassName={labelClassName}
|
||||
description={option.description}
|
||||
optionType={optionType}
|
||||
>
|
||||
{String(option[labelField || 'label'])}
|
||||
{removable && hasAbility(option, 'removable') ? (
|
||||
@ -191,7 +286,8 @@ export default class CheckboxesControl extends React.Component<
|
||||
creatable,
|
||||
addApi,
|
||||
createBtnLabel,
|
||||
translate: __
|
||||
translate: __,
|
||||
optionType
|
||||
} = this.props;
|
||||
|
||||
let body: Array<React.ReactNode> = [];
|
||||
@ -200,7 +296,7 @@ export default class CheckboxesControl extends React.Component<
|
||||
body = options.map((option, key) => this.renderItem(option, key));
|
||||
}
|
||||
|
||||
if (checkAll && body.length) {
|
||||
if (checkAll && body.length && optionType === 'default') {
|
||||
body.unshift(
|
||||
<Checkbox
|
||||
key="checkall"
|
||||
@ -225,7 +321,7 @@ export default class CheckboxesControl extends React.Component<
|
||||
body = columnsSplit(body, cx, columnsCount);
|
||||
|
||||
return (
|
||||
<div className={cx(`CheckboxesControl`, className)}>
|
||||
<div className={cx(`CheckboxesControl`, className)} ref="checkboxRef">
|
||||
{body && body.length ? (
|
||||
body
|
||||
) : (
|
||||
|
Loading…
Reference in New Issue
Block a user