I've been trying to make use of list web components from ESRI Calcite Design System.
With the code snippet below I cannot manage to deselect an already-selected list item when it's clicked a second time.
I'm not stuck with using the Calcite Design System. I could use another web component library (e.g., Material Design) but I cannot find any examples.
"use strict";
const listNode = document.getElementById("point-list")
// Cannot use the event listener below because nothing's fired when already-selected item is clicked
//listNode.addEventListener("calciteListChange", onListClickHandler)
listNode.addEventListener("click", onListClickHandler)
const currentSelectedListItem = (function(){
let currentItemValue
return {
is_same: function(selectedItemValue) {
if (currentItemValue != selectedItemValue) {
currentItemValue = selectedItemValue
return false
}
else {
return true
}
},
reset: function() {
currentItemValue = null
}
}
})()
function onListClickHandler(event) {
const target = event.target
const targetId = target.value
if (currentSelectedListItem.is_same(targetId)) {
console.log("already selected")
// Test 1 (FAILS)
target.toggleSelected()
// Test 2 (FAILS)
// target.removeAttribute("selected")
// Test 4 (FAILS)
// Array.from(listNode.childNodes).forEach(item => item.selected = false)
// Test 5 (FAILS)
// const listItems = listNode.querySelectorAll("calcite-value-list-item")
// listItems.forEach(item => item.selected = false)
}
else {
console.log("new selection")
// Do some stuff
}
}
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"/>
<title>deselect already-selected value list item</title>
<script src="https://js.arcgis.com/4.25/"></script>
<link rel="stylesheet" href="https://js.arcgis.com/4.25/esri/themes/light/main.css"/>
<script type="module" src="https://js.arcgis.com/calcite-components/1.0.0-beta.99/calcite.esm.js"></script>
<link rel="stylesheet" type="text/css" href=https://js.arcgis.com/calcite-components/1.0.0-beta.99/calcite.css />
</head>
<body>
<calcite-shell class="calcite-tutorial">
<calcite-shell-panel slot="panel-end">
<calcite-panel heading="Point list">
<calcite-value-list id="point-list">
<calcite-value-list-item label="point 1" value="point_1" description="some description"></calcite-value-list-item>
<calcite-value-list-item label="point 2" value="point_2" description="some description"></calcite-value-list-item>
<calcite-value-list-item label="point 3" value="point_3" description="some description"></calcite-value-list-item>
</calcite-value-list>
</calcite-panel>
</calcite-shell-panel>
</calcite-shell>
</body>
</html>
Could you please help me?
I think the following example does what you want.
Note:
Here is my version:
"use strict";
const otherElement = document.getElementById("other-element");
const listNode = document.getElementById("point-list")
let lastSelectedItem;
let lastSelectedValue;
listNode.addEventListener("click", onListClickHandler)
function onListClickHandler(event) {
if (event.target.id === lastSelectedItem) {
event.target.selected = !lastSelectedValue;
// If you don't want to see the focus rectangle around the deselected item, then
// selected another focusable element, and optionally call blur() on the new active element.
if (event.target.selected == false) {
otherElement.focus();
document.activeElement.blur();
}
}
lastSelectedItem = event.target.id;
lastSelectedValue = event.target.selected
// Just updating the descriptions in this example to show the selected state of each list item.
for(let listItem of event.target.parentElement.children) {
listItem.description = listItem.selected ? "Selected" : "NOT Selected";
}
}
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"/>
<title>deselect already-selected value list item</title>
<script src="https://js.arcgis.com/4.25/"></script>
<link rel="stylesheet" href="https://js.arcgis.com/4.25/esri/themes/light/main.css"/>
<script type="module" src="https://js.arcgis.com/calcite-components/1.0.0-beta.99/calcite.esm.js"></script>
<link rel="stylesheet" type="text/css" href=https://js.arcgis.com/calcite-components/1.0.0-beta.99/calcite.css />
</head>
<body>
<calcite-shell class="calcite-tutorial">
<!-- Just adding another focusable element to show how to remove focus rectangle on deselected elements-->
<label tabIndex="1" id="other-element">Some other focusable element</label>
<calcite-shell-panel slot="panel-end">
<calcite-panel heading="Point list">
<calcite-value-list id="point-list">
<calcite-value-list-item id="item_1" label="point 1" value="point_1" description="some description"></calcite-value-list-item>
<calcite-value-list-item id="item_2" label="point 2" value="point_2" description="some description"></calcite-value-list-item>
<calcite-value-list-item id="item_3" label="point 3" value="point_3" description="some description"></calcite-value-list-item>
</calcite-value-list>
</calcite-panel>
</calcite-shell-panel>
</calcite-shell>
</body>
</html>