Skip to content

Commit d8ce8eb

Browse files
authored
fix: show placeholder in select when no items or renderer is set (#11085) (#11095)
1 parent e2b8cbe commit d8ce8eb

File tree

2 files changed

+88
-44
lines changed

2 files changed

+88
-44
lines changed

packages/select/src/vaadin-select-base-mixin.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ export const SelectBaseMixin = (superClass) =>
162162
static get observers() {
163163
return [
164164
'_updateAriaExpanded(opened, focusElement)',
165-
'_updateSelectedItem(value, _items, placeholder)',
165+
'_updateSelectedItem(value, _items, placeholder, focusElement)',
166166
'_openedChanged(opened, _overlayElement)',
167167
];
168168
}
@@ -538,7 +538,7 @@ export const SelectBaseMixin = (superClass) =>
538538

539539
valueButton.innerHTML = '';
540540

541-
const selected = this._items[this._menuElement.selected];
541+
const selected = this._items ? this._items[this._menuElement.selected] : undefined;
542542

543543
valueButton.removeAttribute('placeholder');
544544

@@ -579,7 +579,7 @@ export const SelectBaseMixin = (superClass) =>
579579
}
580580

581581
/** @private */
582-
_updateSelectedItem(value, items) {
582+
_updateSelectedItem(value, items, placeholder) {
583583
if (items) {
584584
const valueAsString = value == null ? value : value.toString();
585585
this._menuElement.selected = items.reduce((prev, item, idx) => {
@@ -590,6 +590,8 @@ export const SelectBaseMixin = (superClass) =>
590590
this.__updateValueButton();
591591
delete this._valueChanging;
592592
}
593+
} else if (placeholder) {
594+
this.__updateValueButton();
593595
}
594596
}
595597

packages/select/test/select.test.js

Lines changed: 83 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,89 @@ describe('vaadin-select', () => {
9090
});
9191
});
9292

93+
describe('placeholder', () => {
94+
let valueButton;
95+
96+
describe('no items', () => {
97+
beforeEach(async () => {
98+
select = fixtureSync('<vaadin-select placeholder="Select an item"></vaadin-select>');
99+
await nextRender();
100+
valueButton = select.querySelector('vaadin-select-value-button');
101+
});
102+
103+
it('should display placeholder when no items or renderer is set', () => {
104+
expect(valueButton.textContent).to.equal('Select an item');
105+
});
106+
});
107+
108+
describe('with items', () => {
109+
let items;
110+
111+
beforeEach(async () => {
112+
select = fixtureSync('<vaadin-select placeholder="Select an item"></vaadin-select>');
113+
await nextRender();
114+
select.renderer = (root) => {
115+
render(
116+
html`
117+
<vaadin-list-box>
118+
<vaadin-item>Option 1</vaadin-item>
119+
<vaadin-item value="v2" label="o2"><span>Option 2</span></vaadin-item>
120+
<vaadin-item value="">Option 3</vaadin-item>
121+
<vaadin-item></vaadin-item>
122+
<vaadin-item label="">Empty</vaadin-item>
123+
<vaadin-item value="5">A number</vaadin-item>
124+
<vaadin-item value="false">A boolean</vaadin-item>
125+
<vaadin-item label="foo"></vaadin-item>
126+
<vaadin-item>
127+
<img src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" alt="" />
128+
</vaadin-item>
129+
</vaadin-list-box>
130+
`,
131+
root,
132+
);
133+
};
134+
valueButton = select.querySelector('vaadin-select-value-button');
135+
await nextUpdate(select);
136+
items = select._items;
137+
});
138+
139+
it('should show placeholder when setting value property to null', async () => {
140+
select.value = null;
141+
await nextUpdate(select);
142+
expect(valueButton.textContent).to.equal('Select an item');
143+
});
144+
145+
it('should show placeholder when selecting an item with empty label', async () => {
146+
select.opened = true;
147+
await nextRender();
148+
click(items[4]);
149+
await nextUpdate(select);
150+
expect(valueButton.textContent).to.equal('Select an item');
151+
});
152+
153+
it('should show placeholder when selecting an item with empty text', async () => {
154+
select.opened = true;
155+
await nextRender();
156+
click(items[3]);
157+
await nextUpdate(select);
158+
expect(valueButton.textContent).to.equal('Select an item');
159+
});
160+
161+
it('should not show placeholder for items with label, text content or child elements', async () => {
162+
const emptyItems = [items[3], items[4]];
163+
const nonEmptyItems = items.filter((item) => !emptyItems.includes(item));
164+
165+
for (const item of nonEmptyItems) {
166+
select.opened = true;
167+
await nextRender();
168+
click(item);
169+
await nextUpdate(select);
170+
expect(valueButton.textContent).not.to.equal('Select an item');
171+
}
172+
});
173+
});
174+
});
175+
93176
describe('with items', () => {
94177
beforeEach(async () => {
95178
select = fixtureSync('<vaadin-select></vaadin-select>');
@@ -456,47 +539,6 @@ describe('vaadin-select', () => {
456539
});
457540
});
458541

459-
describe('placeholder', () => {
460-
beforeEach(() => {
461-
select.placeholder = 'Select an item';
462-
});
463-
464-
it('should set placeholder as a value node text content', async () => {
465-
select.value = null;
466-
await nextUpdate(select);
467-
expect(valueButton.textContent).to.equal('Select an item');
468-
});
469-
470-
it('should show placeholder when selecting an item with empty label', async () => {
471-
select.opened = true;
472-
await nextRender();
473-
click(select._items[4]);
474-
await nextUpdate(select);
475-
expect(valueButton.textContent).to.equal('Select an item');
476-
});
477-
478-
it('should show placeholder when selecting an item with empty text', async () => {
479-
select.opened = true;
480-
await nextRender();
481-
click(select._items[3]);
482-
await nextUpdate(select);
483-
expect(valueButton.textContent).to.equal('Select an item');
484-
});
485-
486-
it('should not show placeholder for items with label, text content or child elements', async () => {
487-
const emptyItems = [select._items[3], select._items[4]];
488-
const nonEmptyItems = select._items.filter((item) => !emptyItems.includes(item));
489-
490-
for (const item of nonEmptyItems) {
491-
select.opened = true;
492-
await nextRender();
493-
click(item);
494-
await nextUpdate(select);
495-
expect(valueButton.textContent).not.to.equal('Select an item');
496-
}
497-
});
498-
});
499-
500542
describe('has-value attribute', () => {
501543
it('should not be set by default', () => {
502544
expect(select.getAttribute('has-value')).to.be.null;

0 commit comments

Comments
 (0)