Skip to content

Commit 3d18420

Browse files
authored
fix(ui5-select): preselect first item if none is selected (#358)
- pressing escape now reverts the selection before opening the picker - focusing out the popover now triggers a change event (if selection is changed) Fixes: #339
1 parent 96a0517 commit 3d18420

File tree

3 files changed

+118
-7
lines changed

3 files changed

+118
-7
lines changed

packages/main/src/Select.js

+33-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
isUp,
66
isDown,
77
isEnter,
8+
isEscape,
89
} from "@ui5/webcomponents-base/src/events/PseudoEvents.js";
910
import KeyCodes from "@ui5/webcomponents-core/dist/sap/ui/events/KeyCodes.js";
1011
import ValueState from "@ui5/webcomponents-base/src/types/ValueState.js";
@@ -154,6 +155,10 @@ class Select extends UI5Element {
154155
super();
155156

156157
this._closing = false; // Flag for handling open/close on space
158+
this._selectedItemBeforeOpen = null; // Stores the selected item before opening the picker
159+
this._escapePressed = false; // Identifies if the escape is pressed when picker is open
160+
161+
157162
this._setSelectedItem(null);
158163
this._setPreviewedItem(null);
159164
this.Suggestions = new Suggestions(this, "items", true /* move focus with arrow keys */);
@@ -201,6 +206,15 @@ class Select extends UI5Element {
201206
this.Suggestions.onEnter(event);
202207
}
203208

209+
if (isEscape(event) && this._opened && this._selectedItemBeforeOpen) {
210+
this.items.forEach(item => {
211+
item.selected = false;
212+
});
213+
214+
this._select(this._selectedItemBeforeOpen, this.items.indexOf(this._selectedItemBeforeOpen));
215+
this._escapePressed = true;
216+
}
217+
204218
const key = event.which;
205219

206220
if (key === KeyCodes.F4 || (event.altKey && Select.ARROWS.includes(key))) {
@@ -232,7 +246,6 @@ class Select extends UI5Element {
232246
}
233247

234248
this._select(item);
235-
this._fireChange(item);
236249
}
237250

238251
onItemPreviewed(item) {
@@ -241,21 +254,30 @@ class Select extends UI5Element {
241254
}
242255

243256
onOpen() {
244-
this._opened = true;// invalidating property
257+
this._opened = true; // invalidating property
258+
259+
const selectedItem = this._getSelectedItem();
260+
261+
if (selectedItem) {
262+
this._selectedItemBeforeOpen = selectedItem;
263+
selectedItem.focus();
264+
}
245265
}
246266

247267
onClose() {
248-
this._opened = false;// invalidating property
268+
this._opened = false; // invalidating property
249269

250-
if (this._isSelectionChanged()) {
251-
const previewedItem = this._getPreviewedItem();
270+
if ((this._getSelectedItem() !== this._selectedItemBeforeOpen) && !this._escapePressed) {
271+
const previewedItem = this._getSelectedItem();
252272
this._fireChange(previewedItem);
253273
}
274+
275+
this._escapePressed = false;
254276
}
255277

256278
/* Private methods */
257279
_validateSelection() {
258-
if (this._isOpened()) {
280+
if (this._isOpened() || !this.items.length) {
259281
return;
260282
}
261283

@@ -272,6 +294,11 @@ class Select extends UI5Element {
272294
}
273295
});
274296

297+
if (!selectedItem) {
298+
selectedItem = this.items[0];
299+
selectedItemPos = 0;
300+
}
301+
275302
if (this._getSelectedItem() !== selectedItem) {
276303
this._select(selectedItem, selectedItemPos);
277304
}

packages/main/test/sap/ui/webcomponents/main/pages/Select.html

+23
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@
1515

1616
<body>
1717
<ui5-togglebutton id="myBtn">turn lights</ui5-togglebutton>
18+
<ui5-button id="add-items-btn">Add new Items</ui5-button>
19+
<ui5-button id="restore-items-btn">Restore Items</ui5-button>
1820
<ui5-button id="myBtn2">click</ui5-button>
1921

22+
2023
<h2>Content size</h2>
2124
<ui5-label id="lblResult"></ui5-label>
2225
<ui5-select id="mySelect">
@@ -50,6 +53,8 @@ <h2> Change event counter holder</h2>
5053
var sap_database_entries = [{ key: "Afg", text: "Afghanistan" }, { key: "Arg", text: "Argentina" }, { key: "Alb", text: "Albania" }, { key: "Arm", text: "Armenia" }, { key: "Alg", text: "Algeria" }, { key: "And", text: "Andorra" }, { key: "Ang", text: "Angola" }, { key: "Ast", text: "Austria" }, { key: "Aus", text: "Australia" }, { key: "Aze", text: "Azerbaijan" }, { key: "Aruba", text: "Aruba" }, { key: "Antigua", text: "Antigua and Barbuda" }, { key: "Bel", text: "Belarus" }, { key: "Bel", text: "Belgium" }, { key: "Bg", text: "Bulgaria" }, { key: "Bra", text: "Brazil" }, { key: "Ch", text: "China" }, { key: "Cub", text: "Cuba" }, { key: "Chil", text: "Chili" }, { key: "Lat", text: "Latvia" }, { key: "Lit", text: "Litva" }, { key: "Prt", text: "Portugal" }, { key: "Sen", text: "Senegal" }, { key: "Ser", text: "Serbia" }, { key: "Afg", text: "Seychelles" }, { key: "Sierra", text: "Sierra Leone" }, { key: "Sgp", text: "Singapore" }, { key: "Sint", text: "Sint Maarten" }, { key: "Slv", text: "Slovakia" }, { key: "Slo", text: "Slovenia" }];
5154

5255
var btn = document.getElementById('myBtn');
56+
var addItemsBtn = document.getElementById('add-items-btn');
57+
var restoreItemsBtn = document.getElementById('restore-items-btn');
5358
var input = document.getElementById('myInput');
5459
var inputResult = document.getElementById('inputResult');
5560
var select = document.getElementById('mySelect');
@@ -117,6 +122,24 @@ <h2> Change event counter holder</h2>
117122
li.textContent = item.text;
118123
select3.appendChild(li);
119124
});
125+
126+
var initialItemsHTML = "";
127+
128+
addItemsBtn.addEventListener("press", event => {
129+
initialItemsHTML = select.innerHTML;
130+
131+
var li = document.createElement('ui5-li');
132+
133+
li.type = "Active";
134+
li.textContent = "New";
135+
136+
select.innerHTML = "";
137+
select.appendChild(li);
138+
});
139+
140+
restoreItemsBtn.addEventListener("press", event => {
141+
select.innerHTML = initialItemsHTML;
142+
});
120143
</script>
121144
</body>
122145
</html>

packages/main/test/specs/Select.spec.js

+62-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ describe("Select general interaction", () => {
111111

112112
it("toggles upon ALT + DOWN", () => {
113113
const btn = $("#myBtn2");
114-
const select = $("#mySelect");
115114
const popover = browser.findElementDeep("#mySelect >>> ui5-popover >>> .sapMPopover");
116115

117116
btn.click();
@@ -123,4 +122,66 @@ describe("Select general interaction", () => {
123122
browser.keys(["Alt", "ArrowDown", "NULL"]);
124123
assert.ok(!popover.isDisplayedInViewport(), "Select is closed.");
125124
});
125+
126+
it("adds unselected only items to select", () => {
127+
const addItemsBtn = $("#add-items-btn");
128+
const restoreItemsBtn = $("#restore-items-btn");
129+
130+
addItemsBtn.click();
131+
132+
const firstItem = $("#mySelect ui5-li[slot=items-1]");
133+
134+
assert.ok(firstItem.getProperty("selected"), "First Item should be selected");
135+
136+
restoreItemsBtn.click();
137+
});
138+
139+
it("reverts value before open after clicking on escape", () => {
140+
const select = $("#mySelect");
141+
const selectText = browser.findElementDeep("#mySelect >>> ui5-label").getHTML(false);
142+
const inputResult = browser.findElementDeep("#inputResult >>> input");
143+
144+
select.click();
145+
select.keys("ArrowDown");
146+
select.keys("Escape");
147+
148+
const selectedItem = $("#mySelect ui5-li[selected]");
149+
const selectTextAfterEscape = browser.findElementDeep("#mySelect >>> ui5-label").getHTML(false);
150+
151+
assert.ok(selectedItem.getProperty("selected"), "Initially selected item should remain selected");
152+
assert.strictEqual(inputResult.getProperty("value"), "5", "Change event should not be fired");
153+
assert.strictEqual(selectTextAfterEscape, selectText, "Initially selected item should remain selected");
154+
});
155+
156+
it("fires change event after selection is change and picker if focussed out", () => {
157+
const select = $("#mySelect");
158+
const inputResult = browser.findElementDeep("#inputResult >>> input");
159+
const btn = $("#myBtn2");
160+
161+
select.click();
162+
select.keys("ArrowDown");
163+
select.keys("ArrowDown");
164+
165+
// focus out select
166+
btn.click();
167+
168+
assert.strictEqual(inputResult.getProperty("value"), "6", "Change event should be fired");
169+
});
170+
171+
it("fires change event after selecting a previewed item", () => {
172+
const select = $("#mySelect");
173+
const inputResult = browser.findElementDeep("#inputResult >>> input");
174+
175+
select.click();
176+
select.keys("ArrowDown");
177+
178+
select.keys("Escape");
179+
180+
select.click();
181+
const firstItem = $("#mySelect ui5-li[slot=items-1]");
182+
183+
firstItem.click();
184+
185+
assert.strictEqual(inputResult.getProperty("value"), "7", "Change event should be fired");
186+
});
126187
});

0 commit comments

Comments
 (0)