diff --git a/packages/calcite-components/src/components/filter/filter.e2e.ts b/packages/calcite-components/src/components/filter/filter.e2e.ts
index aec61bf27f3..03a0e6c996b 100644
--- a/packages/calcite-components/src/components/filter/filter.e2e.ts
+++ b/packages/calcite-components/src/components/filter/filter.e2e.ts
@@ -272,6 +272,52 @@ describe("calcite-filter", () => {
});
});
+ describe("filter method", () => {
+ let page: E2EPage;
+
+ beforeEach(async () => {
+ page = await newE2EPage();
+ await page.setContent(``);
+ await page.evaluate(() => {
+ const filter = document.querySelector("calcite-filter");
+ filter.items = [
+ {
+ name: "Harry",
+ description: "developer",
+ value: "harry",
+ metadata: { haircolor: "red", favoriteBand: "MetallicA" }
+ },
+ {
+ name: "Matt",
+ description: "developer",
+ value: "matt",
+ metadata: { haircolor: "black", favoriteBand: "Radiohead" }
+ }
+ ];
+ });
+ });
+
+ it("should filter with value argument", async () => {
+ const filter = await page.find("calcite-filter");
+ const filterChangeSpy = await page.spyOnEvent("calciteFilterChange");
+ await filter.callMethod("filter", "Matt");
+ await page.waitForChanges();
+ expect(filterChangeSpy).toHaveReceivedEventTimes(0);
+ assertMatchingItems(await filter.getProperty("filteredItems"), ["matt"]);
+ });
+
+ it("should filter without value argument", async () => {
+ const filter = await page.find("calcite-filter");
+ filter.setProperty("value", "harry");
+ await page.waitForChanges();
+ const filterChangeSpy = await page.spyOnEvent("calciteFilterChange");
+ await filter.callMethod("filter");
+ await page.waitForChanges();
+ expect(filterChangeSpy).toHaveReceivedEventTimes(0);
+ assertMatchingItems(await filter.getProperty("filteredItems"), ["harry"]);
+ });
+ });
+
describe("translation support", () => {
t9n("calcite-filter");
});
diff --git a/packages/calcite-components/src/components/filter/filter.tsx b/packages/calcite-components/src/components/filter/filter.tsx
index 882c55b1742..1f154adc990 100644
--- a/packages/calcite-components/src/components/filter/filter.tsx
+++ b/packages/calcite-components/src/components/filter/filter.tsx
@@ -61,7 +61,7 @@ export class Filter
@Watch("items")
watchItemsHandler(): void {
- this.filter(this.value);
+ this.filterDebounced(this.value);
}
/**
@@ -112,7 +112,7 @@ export class Filter
@Watch("value")
valueHandler(value: string): void {
- this.filter(value);
+ this.filterDebounced(value);
}
// --------------------------------------------------------------------------
@@ -169,6 +169,7 @@ export class Filter
disconnectedCallback(): void {
disconnectLocalized(this);
disconnectMessages(this);
+ this.filterDebounced.cancel();
}
componentDidLoad(): void {
@@ -181,6 +182,22 @@ export class Filter
//
// --------------------------------------------------------------------------
+ /**
+ * Performs a filter on the component.
+ *
+ * This method can be useful because filtering is delayed and asynchronous.
+ *
+ * @param {string} value - The filter text value.
+ * @returns {Promise}
+ */
+ @Method()
+ async filter(value: string = this.value): Promise {
+ return new Promise((resolve) => {
+ this.value = value;
+ this.filterDebounced(value, false, resolve);
+ });
+ }
+
/** Sets focus on the component. */
@Method()
async setFocus(): Promise {
@@ -195,15 +212,16 @@ export class Filter
//
// --------------------------------------------------------------------------
- private filter = debounce(
- (value: string, emit = false): void => this.updateFiltered(filter(this.items, value), emit),
+ private filterDebounced = debounce(
+ (value: string, emit = false, onFilter?: () => void): void =>
+ this.updateFiltered(filter(this.items, value), emit, onFilter),
DEBOUNCE_TIMEOUT
);
inputHandler = (event: CustomEvent): void => {
const target = event.target as HTMLCalciteInputElement;
this.value = target.value;
- this.filter(target.value, true);
+ this.filterDebounced(target.value, true);
};
keyDownHandler = (event: KeyboardEvent): void => {
@@ -219,16 +237,16 @@ export class Filter
clear = (): void => {
this.value = "";
- this.filter("", true);
+ this.filterDebounced("", true);
this.setFocus();
};
- updateFiltered(filtered: any[], emit = false): void {
- this.filteredItems.length = 0;
- this.filteredItems = this.filteredItems.concat(filtered);
+ updateFiltered(filtered: object[], emit = false, callback?: () => void): void {
+ this.filteredItems = filtered;
if (emit) {
this.calciteFilterChange.emit();
}
+ callback?.();
}
// --------------------------------------------------------------------------