Skip to content

Commit 16e2045

Browse files
authored
Put item at the top of picker result if there is an exact match with entity id (#25625)
1 parent 9c0ce41 commit 16e2045

File tree

4 files changed

+67
-5
lines changed

4 files changed

+67
-5
lines changed

src/components/entity/ha-entity-picker.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ import type { HomeAssistant } from "../../types";
2323
import "../ha-combo-box-item";
2424
import "../ha-generic-picker";
2525
import type { HaGenericPicker } from "../ha-generic-picker";
26-
import type { PickerComboBoxItem } from "../ha-picker-combo-box";
26+
import type {
27+
PickerComboBoxItem,
28+
PickerComboBoxSearchFn,
29+
} from "../ha-picker-combo-box";
2730
import type { PickerValueRenderer } from "../ha-picker-field";
2831
import "../ha-svg-icon";
2932
import "./state-badge";
@@ -406,13 +409,31 @@ export class HaEntityPicker extends LitElement {
406409
.getItems=${this._getItems}
407410
.getAdditionalItems=${this._getAdditionalItems}
408411
.hideClearIcon=${this.hideClearIcon}
412+
.searchFn=${this._searchFn}
409413
.valueRenderer=${this._valueRenderer}
410414
@value-changed=${this._valueChanged}
411415
>
412416
</ha-generic-picker>
413417
`;
414418
}
415419

420+
private _searchFn: PickerComboBoxSearchFn<EntityComboBoxItem> = (
421+
search,
422+
filteredItems
423+
) => {
424+
// If there is exact match for entity id, put it first
425+
const index = filteredItems.findIndex(
426+
(item) => item.stateObj?.entity_id === search
427+
);
428+
if (index === -1) {
429+
return filteredItems;
430+
}
431+
432+
const [exactMatch] = filteredItems.splice(index, 1);
433+
filteredItems.unshift(exactMatch);
434+
return filteredItems;
435+
};
436+
416437
public async open() {
417438
await this.updateComplete;
418439
await this._picker?.open();

src/components/entity/ha-statistic-picker.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ import "../ha-generic-picker";
2525
import type { HaGenericPicker } from "../ha-generic-picker";
2626
import "../ha-icon-button";
2727
import "../ha-input-helper-text";
28-
import type { PickerComboBoxItem } from "../ha-picker-combo-box";
28+
import type {
29+
PickerComboBoxItem,
30+
PickerComboBoxSearchFn,
31+
} from "../ha-picker-combo-box";
2932
import type { PickerValueRenderer } from "../ha-picker-field";
3033
import "../ha-svg-icon";
3134
import "./state-badge";
@@ -470,13 +473,32 @@ export class HaStatisticPicker extends LitElement {
470473
.getItems=${this._getItems}
471474
.getAdditionalItems=${this._getAdditionalItems}
472475
.hideClearIcon=${this.hideClearIcon}
476+
.searchFn=${this._searchFn}
473477
.valueRenderer=${this._valueRenderer}
474478
@value-changed=${this._valueChanged}
475479
>
476480
</ha-generic-picker>
477481
`;
478482
}
479483

484+
private _searchFn: PickerComboBoxSearchFn<StatisticComboBoxItem> = (
485+
search,
486+
filteredItems
487+
) => {
488+
// If there is exact match for entity id or statistic id, put it first
489+
const index = filteredItems.findIndex(
490+
(item) =>
491+
item.stateObj?.entity_id === search || item.statistic_id === search
492+
);
493+
if (index === -1) {
494+
return filteredItems;
495+
}
496+
497+
const [exactMatch] = filteredItems.splice(index, 1);
498+
filteredItems.unshift(exactMatch);
499+
return filteredItems;
500+
};
501+
480502
private _valueChanged(ev: ValueChangedEvent<string>) {
481503
ev.stopPropagation();
482504
const value = ev.detail.value;

src/components/ha-generic-picker.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import "./ha-picker-combo-box";
1212
import type {
1313
HaPickerComboBox,
1414
PickerComboBoxItem,
15+
PickerComboBoxSearchFn,
1516
} from "./ha-picker-combo-box";
1617
import "./ha-picker-field";
1718
import type { HaPickerField, PickerValueRenderer } from "./ha-picker-field";
@@ -57,6 +58,9 @@ export class HaGenericPicker extends LitElement {
5758
@property({ attribute: false })
5859
public valueRenderer?: PickerValueRenderer;
5960

61+
@property({ attribute: false })
62+
public searchFn?: PickerComboBoxSearchFn<PickerComboBoxItem>;
63+
6064
@property({ attribute: "not-found-label", type: String })
6165
public notFoundLabel?: string;
6266

@@ -102,6 +106,7 @@ export class HaGenericPicker extends LitElement {
102106
.notFoundLabel=${this.notFoundLabel}
103107
.getItems=${this.getItems}
104108
.getAdditionalItems=${this.getAdditionalItems}
109+
.searchFn=${this.searchFn}
105110
></ha-picker-combo-box>
106111
`}
107112
</div>

src/components/ha-picker-combo-box.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ const DEFAULT_ROW_RENDERER: ComboBoxLitRenderer<PickerComboBoxItem> = (
4949
</ha-combo-box-item>
5050
`;
5151

52+
export type PickerComboBoxSearchFn<T extends PickerComboBoxItem> = (
53+
search: string,
54+
filteredItems: T[],
55+
allItems: T[]
56+
) => T[];
57+
5258
@customElement("ha-picker-combo-box")
5359
export class HaPickerComboBox extends LitElement {
5460
@property({ attribute: false }) public hass!: HomeAssistant;
@@ -84,6 +90,9 @@ export class HaPickerComboBox extends LitElement {
8490
@property({ attribute: "not-found-label", type: String })
8591
public notFoundLabel?: string;
8692

93+
@property({ attribute: false })
94+
public searchFn?: PickerComboBoxSearchFn<PickerComboBoxItem>;
95+
8796
@state() private _opened = false;
8897

8998
@query("ha-combo-box", true) public comboBox!: HaComboBox;
@@ -237,6 +246,7 @@ export class HaPickerComboBox extends LitElement {
237246
const fuse = new HaFuse(this._items, { shouldSort: false }, index);
238247

239248
const results = fuse.multiTermsSearch(searchString);
249+
let filteredItems = this._items as PickerComboBoxItem[];
240250
if (results) {
241251
const items = results.map((result) => result.item);
242252
if (items.length === 0) {
@@ -246,10 +256,14 @@ export class HaPickerComboBox extends LitElement {
246256
}
247257
const additionalItems = this._getAdditionalItems(searchString);
248258
items.push(...additionalItems);
249-
target.filteredItems = items;
250-
} else {
251-
target.filteredItems = this._items;
259+
filteredItems = items;
252260
}
261+
262+
if (this.searchFn) {
263+
filteredItems = this.searchFn(searchString, filteredItems, this._items);
264+
}
265+
266+
target.filteredItems = filteredItems;
253267
}
254268

255269
private _setValue(value: string | undefined) {

0 commit comments

Comments
 (0)