Skip to content
This repository was archived by the owner on Mar 17, 2021. It is now read-only.

Commit b997b49

Browse files
committed
Added checkbox-group component
1 parent ee94262 commit b997b49

File tree

7 files changed

+203
-0
lines changed

7 files changed

+203
-0
lines changed

docs/.vuepress/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ module.exports = {
2525
'components/badge',
2626
'components/button',
2727
'components/checkbox',
28+
'components/checkbox-group',
2829
'components/radio',
2930
'components/radio-group',
3031
'components/tabs',

docs/components/checkbox-group.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Checkbox Group
2+
Set of checkbox's components
3+
4+
## Example
5+
<div class="p-3 border rounded-2 my-3">
6+
<v-checkbox-group
7+
class="mb-3"
8+
label="Favorites color"
9+
name="colors"
10+
:options="['White', 'Blue', 'Red']"
11+
v-model="group1"
12+
/>
13+
<v-checkbox-group
14+
label="Favorites color"
15+
name="colors-objects"
16+
:options="[
17+
{ id: 1, label: 'White', value: 'white' },
18+
{ id: 2, label: 'Blue', value: 'blue', disabled: true },
19+
{ id: 3, label: 'Red', value: 'red' },
20+
]"
21+
v-model="group2"
22+
/>
23+
</div>
24+
25+
26+
```html
27+
<!-- Array of string -->
28+
<v-checkbox-group
29+
label="Favorites color"
30+
name="colors-strings"
31+
:options="['White', 'Blue', 'Red']"
32+
v-model="group1"
33+
/>
34+
35+
<!-- Array of objects -->
36+
<v-checkbox-group
37+
label="Favorites color"
38+
name="colors-objects"
39+
:options="[
40+
{ id: 1, label: 'White', value: 'white' },
41+
{ id: 2, label: 'Blue', value: 'blue', disabled: true },
42+
{ id: 3, label: 'Red', value: 'red' },
43+
]"
44+
v-model="group1"
45+
/>
46+
```
47+
48+
## Props
49+
Name | Type | Description | Default | Required
50+
---------- | -------- | ----------- | ------- | --------
51+
name | String | The `name` attribute of each checkbox's input element. | false | false
52+
label | String | The checkbox group label. | None | false
53+
value, v-model | Array | The model that holds the checked option values. Can be set initially for default values. | None | true
54+
options | Array | An array of options to show to the user as checkboxes. The array can either be of strings or objects (but not both). | None | true
55+
keys | Object | Allows for redefining the option keys. The id, name, class and disabled keys are optional. Pass an object with custom keys if your data does not match the default keys. Note that if you redefine one key, you have to define all the others as well. | `{id: 'id',label: 'label',value: 'value',checked: 'checked',disabled: 'disabled' }` | false
56+
57+
<script>
58+
export default {
59+
data() {
60+
return { group1: [], group2: [] };
61+
},
62+
};
63+
</script>

docs/components/radio-group.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ Name | Description
6868
Name | Description
6969
---------- | ----------
7070
reset() | Call this method to reset the radio group's `value` to its initial `value`.
71+
7172
<script>
7273
export default {
7374
data() {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import CheckboxGroup from './main.vue';
2+
3+
// eslint-disable-next-line func-names
4+
CheckboxGroup.install = function (Vue) {
5+
Vue.component('VCheckboxGroup', CheckboxGroup);
6+
};
7+
8+
export default CheckboxGroup;
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<template>
2+
<div class="checkbox-group">
3+
<div class="checkbox-group__label">{{ label }}</div>
4+
<div class="checkbox-group__list">
5+
<div
6+
class="checkbox-group__item"
7+
:key="option[keys.id] || `${name}-${i}`"
8+
v-for="(option, i) in options"
9+
>
10+
<v-checkbox
11+
:id="option[keys.id] || `${name || option[keys.name]}-${i}`"
12+
:checked="isOptionCheckedByDefault(option)"
13+
:disabled="disabled || option[keys.disabled]"
14+
:key="option[keys.id]"
15+
:name="name || option[keys.name]"
16+
:label="option[keys.label] || option"
17+
18+
@blur="onBlur"
19+
@change="onChange(arguments, option)"
20+
@focus="onFocus"
21+
22+
v-model="checkboxValues[i]"
23+
/>
24+
</div>
25+
</div>
26+
</div>
27+
</template>
28+
29+
<script>
30+
import VCheckbox from '../Checkbox';
31+
import { looseIndexOf } from '../../helpers/util';
32+
33+
export default {
34+
name: 'VCheckboxGroup',
35+
props: {
36+
name: {
37+
type: String,
38+
},
39+
options: {
40+
type: Array,
41+
required: true,
42+
},
43+
value: {
44+
type: Array,
45+
required: true,
46+
},
47+
keys: {
48+
type: Object,
49+
default() {
50+
return {
51+
id: 'id',
52+
name: 'name',
53+
label: 'label',
54+
value: 'value',
55+
disabled: 'disabled',
56+
};
57+
},
58+
},
59+
label: {
60+
type: String,
61+
},
62+
disabled: {
63+
type: Boolean,
64+
default: false,
65+
},
66+
},
67+
data() {
68+
return {
69+
ignoreChange: false,
70+
checkboxValues: [],
71+
initialValue: JSON.parse(JSON.stringify(this.value)),
72+
};
73+
},
74+
methods: {
75+
reset() {
76+
this.ignoreChange = true;
77+
this.options.forEach((option, index) => {
78+
this.checkboxValues[index] = this.isOptionCheckedByDefault(option);
79+
});
80+
this.ignoreChange = false;
81+
this.$emit('input', (this.initialValue.length > 0) ? [].concat(this.initialValue) : []);
82+
},
83+
isOptionCheckedByDefault(option) {
84+
return looseIndexOf(this.initialValue, option[this.keys.value] || option) > -1;
85+
},
86+
onFocus(e) {
87+
this.isActive = true;
88+
this.$emit('focus', e);
89+
},
90+
onBlur(e) {
91+
this.isActive = false;
92+
this.$emit('blur', e);
93+
},
94+
onChange(args, option) {
95+
if (this.ignoreChange) {
96+
return;
97+
}
98+
const checked = args[0];
99+
const e = args[1];
100+
let value = [];
101+
const optionValue = option[this.keys.value] || option;
102+
const i = looseIndexOf(this.value, optionValue);
103+
if (checked && i < 0) {
104+
value = this.value.concat(optionValue);
105+
}
106+
if (!checked && i > -1) {
107+
value = this.value.slice(0, i).concat(this.value.slice(i + 1));
108+
}
109+
this.$emit('input', value);
110+
this.$emit('change', value, e);
111+
},
112+
},
113+
components: { VCheckbox },
114+
};
115+
</script>

src/components/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export { default as VAvatar } from './Avatar';
33
export { default as VBadge } from './Badge';
44
export { default as VButton } from './Button';
55
export { default as VCheckbox } from './Checkbox';
6+
export { default as VCheckboxGroup } from './CheckboxGroup';
67
export { default as VRadio } from './Radio';
78
export { default as VRadioGroup } from './RadioGroup';
89
export { default as VTab } from './Tab';

src/helpers/util.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,17 @@ export function looseEqual(a, b) {
1414
isObject(a) && isObject(b) ? JSON.stringify(a) === JSON.stringify(b) : false
1515
);
1616
}
17+
18+
/**
19+
* Check if a val exists in arr using looseEqual comparison
20+
*/
21+
export function looseIndexOf(arr, val) {
22+
// eslint-disable-next-line no-plusplus
23+
for (let i = 0; i < arr.length; i++) {
24+
if (looseEqual(arr[i], val)) {
25+
return i;
26+
}
27+
}
28+
29+
return -1;
30+
}

0 commit comments

Comments
 (0)