Skip to content

Commit 073dd14

Browse files
fix(InputMenu/Select/SelectMenu): show falsy value when model value is falsy (#4882)
Co-authored-by: Benjamin Canac <[email protected]>
1 parent 81553e8 commit 073dd14

File tree

4 files changed

+179
-4
lines changed

4 files changed

+179
-4
lines changed

src/runtime/utils/index.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,17 +130,21 @@ export function getDisplayValue<T, V>(
130130
): string | undefined {
131131
const { valueKey, labelKey } = options
132132

133-
if (isEmpty(value)) {
134-
return undefined
135-
}
136-
137133
const foundItem = items.find((item) => {
138134
const itemValue = (typeof item === 'object' && item !== null && valueKey)
139135
? get(item, valueKey as string)
140136
: item
141137
return compare(itemValue, value)
142138
})
143139

140+
if (isEmpty(value) && foundItem) {
141+
return labelKey ? get(foundItem as Record<string, any>, labelKey as string) : undefined
142+
}
143+
144+
if (isEmpty(value)) {
145+
return undefined
146+
}
147+
144148
const source = foundItem ?? value
145149

146150
if (source === null || source === undefined) {

test/components/InputMenu.spec.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,63 @@ describe('InputMenu', () => {
117117
})
118118
})
119119

120+
describe('it should display correct label', () => {
121+
test.each([null, undefined, ''])('falsy model value %s should display placeholder', (modelValue) => {
122+
const wrapper = mount(InputMenu, {
123+
props: {
124+
items,
125+
modelValue,
126+
placeholder: 'Select an item'
127+
}
128+
})
129+
130+
expect(wrapper.find('input').attributes('placeholder')).toBe('Select an item')
131+
})
132+
133+
test('with string array and string value', () => {
134+
const wrapper = mount(InputMenu, {
135+
props: {
136+
items: ['Apple', 'Banana', 'Cherry'],
137+
modelValue: 'Banana'
138+
}
139+
})
140+
141+
expect(wrapper.find('input').element.value).toBe('Banana')
142+
})
143+
144+
test('with multiple and empty array value should display placeholder', () => {
145+
const wrapper = mount(InputMenu, {
146+
props: {
147+
items,
148+
multiple: true,
149+
modelValue: [],
150+
placeholder: 'Select items'
151+
}
152+
})
153+
expect(wrapper.find('input').attributes('placeholder')).toBe('Select items')
154+
})
155+
156+
test('with falsy modelValue and options items contain falsy', async () => {
157+
const wrapper = mount(InputMenu, {
158+
props: {
159+
items: [
160+
{
161+
label: 'John Doe',
162+
value: null
163+
},
164+
{
165+
label: 'John Lennon',
166+
value: 1
167+
}
168+
],
169+
valueKey: 'value',
170+
modelValue: null
171+
}
172+
})
173+
expect(wrapper.find('input').element.value).toBe('John Doe')
174+
})
175+
})
176+
120177
describe('form integration', async () => {
121178
async function createForm(validateOn?: FormInputEvents[]) {
122179
const wrapper = await renderForm({

test/components/Select.spec.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,63 @@ describe('Select', () => {
8484
expect(html).toMatchSnapshot()
8585
})
8686

87+
describe('it should display correct label', () => {
88+
test.each([null, undefined, ''])('falsy model value %s should display placeholder', (modelValue) => {
89+
const wrapper = mount(Select, {
90+
props: {
91+
items,
92+
modelValue,
93+
placeholder: 'Select an item'
94+
}
95+
})
96+
97+
expect(wrapper.text()).toBe('Select an item')
98+
})
99+
100+
test('with string array and string value', () => {
101+
const wrapper = mount(Select, {
102+
props: {
103+
items: ['Apple', 'Banana', 'Cherry'],
104+
modelValue: 'Banana'
105+
}
106+
})
107+
108+
expect(wrapper.text()).toBe('Banana')
109+
})
110+
111+
test('with multiple and empty array value should display placeholder', () => {
112+
const wrapper = mount(Select, {
113+
props: {
114+
items,
115+
multiple: true,
116+
modelValue: [],
117+
placeholder: 'Select items'
118+
}
119+
})
120+
expect(wrapper.text()).toBe('Select items')
121+
})
122+
123+
test('with falsy modelValue and options items contain falsy', () => {
124+
const wrapper = mount(Select, {
125+
props: {
126+
items: [
127+
{
128+
label: 'John Doe',
129+
value: null
130+
},
131+
{
132+
label: 'John Lennon',
133+
value: 1
134+
}
135+
],
136+
valueKey: 'value',
137+
modelValue: null
138+
}
139+
})
140+
expect(wrapper.text()).toBe('John Doe')
141+
})
142+
})
143+
87144
describe('emits', () => {
88145
test('update:modelValue event', async () => {
89146
const wrapper = mount(Select, { props: { items: ['Option 1', 'Option 2'] } })

test/components/SelectMenu.spec.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,63 @@ describe('SelectMenu', () => {
113113
})
114114
})
115115

116+
describe('it should display correct label', () => {
117+
test.each([null, undefined, ''])('falsy model value %s should display placeholder', (modelValue) => {
118+
const wrapper = mount(SelectMenu, {
119+
props: {
120+
items,
121+
modelValue,
122+
placeholder: 'Select an item'
123+
}
124+
})
125+
126+
expect(wrapper.text()).toBe('Select an item')
127+
})
128+
129+
test('with string array and string value', () => {
130+
const wrapper = mount(SelectMenu, {
131+
props: {
132+
items: ['Apple', 'Banana', 'Cherry'],
133+
modelValue: 'Banana'
134+
}
135+
})
136+
137+
expect(wrapper.text()).toBe('Banana')
138+
})
139+
140+
test('with multiple and empty array value should display placeholder', () => {
141+
const wrapper = mount(SelectMenu, {
142+
props: {
143+
items,
144+
multiple: true,
145+
modelValue: [],
146+
placeholder: 'Select items'
147+
}
148+
})
149+
expect(wrapper.text()).toBe('Select items')
150+
})
151+
152+
test('with falsy modelValue and options items contain falsy', () => {
153+
const wrapper = mount(SelectMenu, {
154+
props: {
155+
items: [
156+
{
157+
label: 'John Doe',
158+
value: null
159+
},
160+
{
161+
label: 'John Lennon',
162+
value: 1
163+
}
164+
],
165+
valueKey: 'value',
166+
modelValue: null
167+
}
168+
})
169+
expect(wrapper.text()).toBe('John Doe')
170+
})
171+
})
172+
116173
describe('form integration', async () => {
117174
async function createForm(validateOn?: FormInputEvents[]) {
118175
const wrapper = await renderForm({

0 commit comments

Comments
 (0)