Skip to content

Commit

Permalink
feat(ui5-multi-combobox): introduce grouping functionality (#5250)
Browse files Browse the repository at this point in the history
* feat(ui5-multi-combobox): introduce grouping functionality

* feat(ui5-multi-combobox): resolve merge conflicts
  • Loading branch information
niyap authored May 26, 2022
1 parent 59a6a6e commit 597a6f2
Show file tree
Hide file tree
Showing 6 changed files with 432 additions and 10 deletions.
42 changes: 34 additions & 8 deletions packages/main/src/MultiComboBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import "@ui5/webcomponents-icons/dist/information.js";
import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js";
import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js";
import MultiComboBoxItem from "./MultiComboBoxItem.js";
import MultiComboBoxGroupItem from "./MultiComboBoxGroupItem.js";
import Tokenizer from "./Tokenizer.js";
import Token from "./Token.js";
import Icon from "./Icon.js";
Expand Down Expand Up @@ -407,7 +408,7 @@ const metadata = {
* @extends UI5Element
* @tagname ui5-multi-combobox
* @public
* @appenddocs MultiComboBoxItem
* @appenddocs MultiComboBoxItem MultiComboBoxGroupItem
* @since 0.11.0
*/
class MultiComboBox extends UI5Element {
Expand Down Expand Up @@ -438,6 +439,7 @@ class MultiComboBox extends UI5Element {
static get dependencies() {
return [
MultiComboBoxItem,
MultiComboBoxGroupItem,
Tokenizer,
Token,
Icon,
Expand Down Expand Up @@ -498,7 +500,8 @@ class MultiComboBox extends UI5Element {

filterSelectedItems(event) {
this.filterSelected = event.target.pressed;
this.selectedItems = this._filteredItems.filter(item => item.selected);
const selectedItems = this._filteredItems.filter(item => item.selected);
this.selectedItems = this.items.filter((item, idx, allItems) => MultiComboBox._groupItemFilter(item, ++idx, allItems, selectedItems) || selectedItems.indexOf(item) !== -1);
}

get _showAllItemsButtonPressed() {
Expand Down Expand Up @@ -943,11 +946,11 @@ class MultiComboBox extends UI5Element {

let currentItem = this.items[++this.currentItemIdx];

while (this.currentItemIdx < itemsCount - 1 && currentItem.selected) {
while ((this.currentItemIdx < itemsCount - 1 && currentItem.selected) || currentItem.isGroupItem) {
currentItem = this.items[++this.currentItemIdx];
}

if (currentItem.selected === true) {
if (currentItem.selected === true || currentItem.isGroupItem) {
this.currentItemIdx = previousItemIdx;
return;
}
Expand Down Expand Up @@ -976,15 +979,15 @@ class MultiComboBox extends UI5Element {

let currentItem = this.items[--this.currentItemIdx];

while (currentItem && currentItem.selected && this.currentItemIdx > 0) {
while ((currentItem && this.currentItemIdx > 0) && (currentItem.selected || currentItem.isGroupItem)) {
currentItem = this.items[--this.currentItemIdx];
}

if (!currentItem) {
return;
}

if (currentItem.selected) {
if (currentItem.selected || currentItem.isGroupItem) {
this.currentItemIdx = previousItemIdx;
return;
}
Expand Down Expand Up @@ -1082,7 +1085,29 @@ class MultiComboBox extends UI5Element {
}

_filterItems(str) {
return (Filters[this.filter] || Filters.StartsWithPerTerm)(str, this.items, "text");
const itemsToFilter = this.items.filter(item => !item.isGroupItem);
const filteredItems = (Filters[this.filter] || Filters.StartsWithPerTerm)(str, itemsToFilter, "text");

// Return the filtered items and their group items
return this.items.filter((item, idx, allItems) => MultiComboBox._groupItemFilter(item, ++idx, allItems, filteredItems) || filteredItems.indexOf(item) !== -1);
}

/**
* Returns true if the group header should be shown (if there is a filtered suggestion item for this group item)
*
* @private
*/
static _groupItemFilter(item, idx, allItems, filteredItems) {
if (item.isGroupItem) {
let groupHasFilteredItems;

while (allItems[idx] && !allItems[idx].isGroupItem && !groupHasFilteredItems) {
groupHasFilteredItems = filteredItems.indexOf(allItems[idx]) !== -1;
idx++;
}

return groupHasFilteredItems;
}
}

_afterOpenPicker() {
Expand Down Expand Up @@ -1189,7 +1214,8 @@ class MultiComboBox extends UI5Element {
this._valueBeforeOpen = this.value;

if (this.filterSelected) {
this.selectedItems = this._filteredItems.filter(item => item.selected);
const selectedItems = this._filteredItems.filter(item => item.selected);
this.selectedItems = this.items.filter((item, idx, allItems) => MultiComboBox._groupItemFilter(item, ++idx, allItems, selectedItems) || selectedItems.indexOf(item) !== -1);
}
}

Expand Down
67 changes: 67 additions & 0 deletions packages/main/src/MultiComboBoxGroupItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import GroupHeaderListItem from "./GroupHeaderListItem.js";

/**
* @public
*/
const metadata = {
tag: "ui5-mcb-group-item",
properties: /** @lends sap.ui.webcomponents.main.MultiComboBoxGroupItem.prototype */ {
/**
* Defines the text of the component.
*
* @type {string}
* @defaultvalue ""
* @public
*/
text: {
type: String,
},
},
slots: /** @lends sap.ui.webcomponents.main.MultiComboBoxGroupItem.prototype */ {
},
events: /** @lends sap.ui.webcomponents.main.MultiComboBoxGroupItem.prototype */ {
},
};

/**
* @class
* The <code>ui5-multi-combobox-group-item</code> is type of suggestion item,
* that can be used to split the <code>ui5-multi-combobox</code> suggestions into groups.
*
* @constructor
* @author SAP SE
* @alias sap.ui.webcomponents.main.MultiComboBoxGroupItem
* @extends UI5Element
* @tagname ui5-mcb-group-item
* @public
* @implements sap.ui.webcomponents.main.IMultiComboBoxItem
* @since 1.4.0
*/
class MultiComboBoxGroupItem extends UI5Element {
static get metadata() {
return metadata;
}

static get dependencies() {
return [
GroupHeaderListItem,
];
}

/**
* Used to avoid tag name checks
* @protected
*/
get isGroupItem() {
return true;
}

get stableDomRef() {
return this.getAttribute("stable-dom-ref") || `${this._id}-stable-dom-ref`;
}
}

MultiComboBoxGroupItem.define();

export default MultiComboBoxGroupItem;
12 changes: 10 additions & 2 deletions packages/main/src/MultiComboBoxPopover.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,21 @@
{{#if filterSelected}}
<ui5-list separators="None" mode="MultiSelect" class="ui5-multi-combobox-all-items-list">
{{#each selectedItems}}
{{> listItem}}
{{#if isGroupItem}}
<ui5-li-groupheader data-ui5-stable="{{this.stableDomRef}}" @keydown="{{../_onItemKeydown}}">{{ this.text }}</ui5-li-groupheader>
{{else}}
{{> listItem}}
{{/if}}
{{/each}}
</ui5-list>
{{else}}
<ui5-list separators="None" mode="MultiSelect" class="ui5-multi-combobox-all-items-list">
{{#each _filteredItems}}
{{> listItem}}
{{#if isGroupItem}}
<ui5-li-groupheader data-ui5-stable="{{this.stableDomRef}}" @keydown="{{../_onItemKeydown}}">{{ this.text }}</ui5-li-groupheader>
{{else}}
{{> listItem}}
{{/if}}
{{/each}}
</ui5-list>
{{/if}}
Expand Down
23 changes: 23 additions & 0 deletions packages/main/test/pages/MultiComboBox.html
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,29 @@
</ui5-multi-combobox>
</div>

<div class="demo-section">
<span>MultiComboBox with grouping</span>

<br>
<ui5-multi-combobox id="mcb-grouping" allow-custom-values placeholder="Select a country">
<ui5-mcb-group-item text="Asia"></ui5-mcb-group-item>
<ui5-mcb-item text="Afghanistan"></ui5-mcb-item>
<ui5-mcb-item text="China"></ui5-mcb-item>
<ui5-mcb-item text="India"></ui5-mcb-item>
<ui5-mcb-item text="Indonesia"></ui5-mcb-item>
<ui5-mcb-group-item text="Europe"></ui5-mcb-group-item>
<ui5-mcb-item text="Austria"></ui5-mcb-item>
<ui5-mcb-item text="Bulgaria"></ui5-mcb-item>
<ui5-mcb-item text="Germany"></ui5-mcb-item>
<ui5-mcb-item text="Italy"></ui5-mcb-item>
<ui5-mcb-group-item text="North America"></ui5-mcb-group-item>
<ui5-mcb-item text="Canada"></ui5-mcb-item>
<ui5-mcb-item text="Granada"></ui5-mcb-item>
<ui5-mcb-item text="Haiti"></ui5-mcb-item>
<ui5-mcb-item text="United States"></ui5-mcb-item>
</ui5-multi-combobox>
</div>


<hr class="demo-section">

Expand Down
46 changes: 46 additions & 0 deletions packages/main/test/samples/MultiComboBox.sample.html
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,50 @@ <h3>MultiComboBox with Value State</h3>
</xmp></pre>
</section>

<section>
<h3>MultiComboBox with Grouping of Items</h3>
<div class="snippet responsive-snippet">
<ui5-multi-combobox placeholder="Select a country">
<ui5-mcb-group-item text="Asia"></ui5-mcb-group-item>
<ui5-mcb-item text="Afghanistan"></ui5-mcb-item>
<ui5-mcb-item text="China"></ui5-mcb-item>
<ui5-mcb-item text="India"></ui5-mcb-item>
<ui5-mcb-item text="Indonesia"></ui5-mcb-item>
<ui5-mcb-group-item text="Europe"></ui5-mcb-group-item>
<ui5-mcb-item text="Austria"></ui5-mcb-item>
<ui5-mcb-item text="Bulgaria"></ui5-mcb-item>
<ui5-mcb-item text="Germany"></ui5-mcb-item>
<ui5-mcb-item text="Italy"></ui5-mcb-item>
<ui5-mcb-group-item text="North America"></ui5-mcb-group-item>
<ui5-mcb-item text="Canada"></ui5-mcb-item>
<ui5-mcb-item text="Granada"></ui5-mcb-item>
<ui5-mcb-item text="Haiti"></ui5-mcb-item>
<ui5-mcb-item text="United States"></ui5-mcb-item>
</ui5-multi-combobox>
</div>

<pre class="prettyprint lang-html"><xmp>

<ui5-multi-combobox placeholder="Select a country">
<ui5-mcb-group-item text="Asia"></ui5-mcb-group-item>
<ui5-mcb-item text="Afghanistan"></ui5-mcb-item>
<ui5-mcb-item text="China"></ui5-mcb-item>
<ui5-mcb-item text="India"></ui5-mcb-item>
<ui5-mcb-item text="Indonesia"></ui5-mcb-item>
<ui5-mcb-group-item text="Europe"></ui5-mcb-group-item>
<ui5-mcb-item text="Austria"></ui5-mcb-item>
<ui5-mcb-item text="Bulgaria"></ui5-mcb-item>
<ui5-mcb-item text="Germany"></ui5-mcb-item>
<ui5-mcb-item text="Italy"></ui5-mcb-item>
<ui5-mcb-group-item text="North America"></ui5-cb-group-item>
<ui5-mcb-item text="Canada"></ui5-mcb-item>
<ui5-mcb-item text="Granada"></ui5-mcb-item>
<ui5-mcb-item text="Haiti"></ui5-mcb-item>
<ui5-mcb-item text="United States"></ui5-mcb-item>
</ui5-multi-combobox>

</xmp></pre>

</section>

<!-- JSDoc marker -->
Loading

0 comments on commit 597a6f2

Please sign in to comment.