Skip to content

Commit

Permalink
fix(combo): resolve #1229 #1238 #1260 (#1261)
Browse files Browse the repository at this point in the history
* fix(combo): resolve #1229 #1238 #1260
---------

Co-authored-by: Radoslav Karaivanov <rkaraivanov@infragistics.com>
  • Loading branch information
simeonoff and rkaraivanov committed Jun 25, 2024
1 parent 5ae7e50 commit 640670a
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Tree - setting `--ig-size` on the item `indicator` CSS Part will now change the size of the icon
- Date-time input - double emit of `igcChange` in certain scenarios
- Navigation drawer - mini variant is not initially rendered when not in an open state [#1266](https://github.com/IgniteUI/igniteui-webcomponents/issues/1266)
- Combo:
- Selecting an entry using the Enter key now correctly works in single selection mode [#1229](https://github.com/IgniteUI/igniteui-webcomponents/issues/1229)
- Turning on the `disableFiltering` option now clears any previously entered search term [#1238](https://github.com/IgniteUI/igniteui-webcomponents/issues/1238)
- Entering a search term in single selection mode that already matches the selected item now works correctly [#1260](https://github.com/IgniteUI/igniteui-webcomponents/issues/1260)

## [4.9.0] - 2024-04-30
### Added
Expand Down
66 changes: 59 additions & 7 deletions src/components/combo/combo.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -726,22 +726,39 @@ describe('Combo', () => {
expect(combo.open).to.be.true;
});

it('should select the active item and close the menu by pressing the Enter key', async () => {
combo.autofocusList = true;
it('should select the active item and close the menu by pressing Enter in single selection', async () => {
combo.singleSelect = true;
await elementUpdated(combo);

combo.show();
await Promise.all([elementUpdated(combo), list.layoutComplete]);

pressKey(options, 'ArrowDown', 1, { altKey: false });
pressKey(options, 'Enter', 1, { altKey: false });

await elementUpdated(combo);
await list.layoutComplete;

pressKey(options, 'ArrowDown', 2, { altKey: false });
expect(combo.value).to.eql(['BG01']);
expect(combo.open).to.be.false;
});

it("shouldn't deselect an item if it's already selected on Enter in single selection", async () => {
const selection = 'BG01';
combo.singleSelect = true;
await elementUpdated(combo);

combo.select(selection);
await elementUpdated(combo);

combo.show();
await Promise.all([elementUpdated(combo), list.layoutComplete]);

pressKey(options, 'ArrowDown', 1, { altKey: false });
pressKey(options, 'Enter', 1, { altKey: false });

await elementUpdated(combo);

const itms = items(combo);
expect(itms[1].active).to.be.false;
expect(itms[1].selected).to.be.true;
expect(combo.value).to.eql(['BG01']);
expect(combo.open).to.be.false;
});

Expand Down Expand Up @@ -859,6 +876,25 @@ describe('Combo', () => {
expect(items(combo)[2].selected).to.be.true;
});

it('should maintain value with repeated selection via input in single selection mode', async () => {
combo.singleSelect = true;
await elementUpdated(combo);

combo.select('BG01');
await elementUpdated(combo);

expect(input.value).to.equal('Sofia');

input.dispatchEvent(new CustomEvent('igcInput', { detail: 'sof' }));
await elementUpdated(combo);

pressKey(input, 'Enter');
await elementUpdated(combo);

expect(input.value).to.equal('Sofia');
expect(combo.value).to.deep.equal(['BG01']);
});

it('should clear selection upon changing the search term via input', async () => {
combo.singleSelect = true;
await elementUpdated(combo);
Expand Down Expand Up @@ -1208,6 +1244,22 @@ describe('Combo', () => {
comboHeadersLabel = headerItems(combo).map((header) => header.innerText);
expect(comboHeadersLabel).to.eql(['Méxícó', 'Ángel', 'México']);
});

it('should clear the search term upon toggling disableFiltering', async () => {
combo.show();
await elementUpdated(combo);
await list.layoutComplete;
expect(items(combo).length).to.equal(cities.length);

await filterCombo('sof');
expect(items(combo).length).to.equal(1);

combo.disableFiltering = true;
await elementUpdated(combo);
await list.layoutComplete;

expect(items(combo).length).to.equal(cities.length);
});
});

describe('Form integration', () => {
Expand Down
19 changes: 19 additions & 0 deletions src/components/combo/combo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,12 @@ export default class IgcComboComponent<
this._rootClickController.update();
}

@watch('disableFiltering')
protected updateOnDisableFiltering() {
this.resetSearchTerm();
this.pipeline();
}

private _rootClickController = addRootClickHandler(this, {
hideCallback: async () => {
if (!this.handleClosing()) return;
Expand Down Expand Up @@ -510,6 +516,10 @@ export default class IgcComboComponent<
.getValue(selected, this.displayKey!)
.join(', ');

if (this.target && this.singleSelect) {
this.target.value = this._displayValue;
}

this.setFormValue();
this.updateValidity();
this.setInvalidState();
Expand Down Expand Up @@ -758,6 +768,14 @@ export default class IgcComboComponent<
this.updateValue();
}

protected selectByIndex(index: number) {
const { dataIndex } = this.dataState.at(index)!;

this.selectionController.selectByIndex(dataIndex);
this.navigationController.active = index;
this.updateValue();
}

protected navigateTo(item: T) {
this.navigationController.navigateTo(item, this.list);
}
Expand Down Expand Up @@ -913,6 +931,7 @@ export default class IgcComboComponent<
?hidden=${this.disableFiltering || this.singleSelect}
>
<igc-input
.value=${this.dataController.searchTerm}
part="search-input"
placeholder=${this.placeholderSearch}
exportparts="input: search-input"
Expand Down
12 changes: 11 additions & 1 deletion src/components/combo/controllers/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ export class NavigationController<T extends object>
this.host.toggleSelect(index);
}

public select(index: number) {
// @ts-expect-error protected access
this.host.selectByIndex(index);
}

protected get currentItem() {
const item = this.active;
return item === START_INDEX ? START_INDEX : item;
Expand Down Expand Up @@ -148,7 +153,12 @@ export class NavigationController<T extends object>
return;
}

this.space();
const item = this.dataState[this.active];

if (!item.header && this.host.singleSelect) {
this.select(this.active);
}

this.hide();
requestAnimationFrame(() => this.input.select());
this.host.focus();
Expand Down
10 changes: 10 additions & 0 deletions src/components/combo/controllers/selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,16 @@ export class SelectionController<T extends object>
}
}

public selectByIndex(index: number) {
const item = this.data[index];

if (this.host.valueKey) {
this.select([item[this.host.valueKey]], true);
} else {
this.select([item], true);
}
}

constructor(protected host: ComboHost<T>) {
this.host.addController(this);
}
Expand Down

0 comments on commit 640670a

Please sign in to comment.