Skip to content

Commit af899f5

Browse files
committed
feat: add CInputRadioGroup component
1 parent 269128b commit af899f5

File tree

5 files changed

+182
-0
lines changed

5 files changed

+182
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<template>
2+
<div>
3+
<CInputRadio
4+
v-for="({value, label, props}, key) in computedOptions"
5+
:key="key"
6+
:label="label"
7+
:name="groupName"
8+
:value="value"
9+
:checked="checked === value"
10+
@change="change($event, value)"
11+
:custom="custom"
12+
v-bind="props"
13+
/>
14+
</div>
15+
</template>
16+
17+
<script>
18+
import CInputRadio from './CInputRadio'
19+
export default {
20+
name: 'CInputRadioGroup',
21+
components: {
22+
CInputRadio
23+
},
24+
props: {
25+
options: {
26+
type: Array,
27+
required: true
28+
},
29+
checked: String,
30+
name: String,
31+
custom: Boolean
32+
},
33+
computed: {
34+
computedOptions () {
35+
return this.options.map(option => {
36+
if (typeof option !== 'object') {
37+
return {
38+
label: option,
39+
value: option
40+
}
41+
}
42+
return option
43+
})
44+
},
45+
groupName () {
46+
return this.name || 'radio' + this._uid
47+
}
48+
},
49+
methods: {
50+
change (e, option) {
51+
this.$emit('update:checked', option, e)
52+
}
53+
}
54+
}
55+
</script>

src/components/form/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import CInput from './CInput'
44
import CInputCheckbox from './CInputCheckbox'
55
import CInputFile from './CInputFile'
66
import CInputRadio from './CInputRadio'
7+
import CInputRadioGroup from './CInputRadioGroup'
78
import CSelect from './CSelect'
89
import CTextarea from './CTextarea'
910

@@ -14,6 +15,7 @@ export {
1415
CInputCheckbox,
1516
CInputFile,
1617
CInputRadio,
18+
CInputRadioGroup,
1719
CSelect,
1820
CTextarea
1921
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { mount } from '@vue/test-utils'
2+
import Component from '../CInputRadioGroup'
3+
4+
const ComponentName = 'CInputRadio'
5+
const customWrapper = mount(Component, {
6+
propsData: {
7+
name: 'custom',
8+
options: [
9+
{ value: 'option 1', label: 'label1', props: { id: 'id1' }},
10+
{ value: 'option 2', label: 'label2', props: { description: 'description', id: 'id2' }}
11+
],
12+
checked: 'option 2',
13+
custom: true
14+
},
15+
atts: {
16+
class: 'add-class'
17+
}
18+
})
19+
20+
describe(ComponentName, () => {
21+
it('has a name', () => {
22+
expect(Component.name).toMatch(ComponentName)
23+
})
24+
it('renders correctly', () => {
25+
expect(customWrapper.element).toMatchSnapshot()
26+
})
27+
it('assigns name automatically when not passed', () => {
28+
customWrapper.setProps({
29+
name: ''
30+
})
31+
expect(customWrapper.findAll('input').at(0).attributes().name).not.toBe('')
32+
})
33+
it('properly renders input radio from string', () => {
34+
const currentOptions = customWrapper.vm.options
35+
customWrapper.setProps({ options: [...currentOptions, 'option 3']})
36+
expect(customWrapper.findAll('label').at(2).text()).toBe('option 3')
37+
expect(customWrapper.findAll('input').at(2).attributes().value).toBe('option 3')
38+
})
39+
it('renders correctly', () => {
40+
customWrapper.find('input').setChecked(true)
41+
expect(customWrapper.emitted()['update:checked']).toBeTruthy()
42+
expect(customWrapper.emitted()['update:checked'][0][1] instanceof Event).toBeTruthy()
43+
})
44+
})
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`CInputRadio renders correctly 1`] = `
4+
<div>
5+
<div
6+
class="custom-control custom-radio"
7+
role="group"
8+
>
9+
10+
<!---->
11+
12+
<input
13+
class="custom-control-input"
14+
id="id1"
15+
name="custom"
16+
type="radio"
17+
value="option 1"
18+
/>
19+
20+
<label
21+
class="custom-control-label"
22+
for="id1"
23+
>
24+
25+
label1
26+
27+
</label>
28+
29+
<!---->
30+
31+
<!---->
32+
33+
<!---->
34+
35+
<!---->
36+
</div>
37+
<div
38+
class="custom-control custom-radio"
39+
role="group"
40+
>
41+
42+
<!---->
43+
44+
<input
45+
class="custom-control-input"
46+
id="id2"
47+
name="custom"
48+
type="radio"
49+
value="option 2"
50+
/>
51+
52+
<label
53+
class="custom-control-label"
54+
for="id2"
55+
>
56+
57+
label2
58+
59+
</label>
60+
61+
<!---->
62+
63+
<!---->
64+
65+
<!---->
66+
67+
<small
68+
class="form-text text-muted w-100"
69+
>
70+
description
71+
</small>
72+
</div>
73+
</div>
74+
`;

src/components/index.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,13 @@ export declare class CInputRadio extends formSharedProps {
228228
inline: boolean
229229
}
230230

231+
export declare class CInputRadioGroup {
232+
name?: string
233+
options: [string | { label: string, value: string, props?: object }]
234+
checked?: string
235+
custom?: boolean
236+
}
237+
231238
export declare class CInputCheckbox extends CInputRadio {}
232239

233240
export declare class CSelect extends formSharedProps {

0 commit comments

Comments
 (0)