Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(list): add filterProps property to specify which properties to filter against #9622

Merged
merged 3 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/calcite-components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3003,6 +3003,10 @@ export namespace Components {
* When `true`, a busy indicator is displayed.
*/
"loading": boolean;
/**
* Specifies the fields to match against when filtering. If not set, all fields will be matched.
*/
"matchFields": string[];
/**
* Use this property to override individual strings used by the component.
*/
Expand Down Expand Up @@ -10890,6 +10894,10 @@ declare namespace LocalJSX {
* When `true`, a busy indicator is displayed.
*/
"loading"?: boolean;
/**
* Specifies the fields to match against when filtering. If not set, all fields will be matched.
*/
"matchFields"?: string[];
/**
* Use this property to override individual strings used by the component.
*/
Expand Down
49 changes: 49 additions & 0 deletions packages/calcite-components/src/components/list/list.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ describe("calcite-list", () => {
propertyName: "dragEnabled",
defaultValue: false,
},
{
propertyName: "matchFields",
defaultValue: undefined,
},
]);
});

Expand Down Expand Up @@ -373,6 +377,51 @@ describe("calcite-list", () => {
expect(visibleItems.map((item) => item.id)).toEqual(["label-match", "description-match", "value-match"]);
});

it("filters initially with matchFields", async () => {
driskull marked this conversation as resolved.
Show resolved Hide resolved
const page = await newE2EPage();
await page.setContent(html`
<calcite-list filter-enabled filter-text="match">
<calcite-list-item
id="label-match"
label="match"
description="description-1"
value="value-1"
></calcite-list-item>
<calcite-list-item
id="description-match"
label="label-2"
description="match"
value="value-1"
></calcite-list-item>
<calcite-list-item
id="value-match"
label="label-3"
description="description-3"
value="match"
></calcite-list-item>
<calcite-list-item
id="no-match"
label="label-4"
description="description-4"
value="value-4"
></calcite-list-item>
</calcite-list>
`);

await page.waitForChanges();
const list = await page.find("calcite-list");
list.setProperty("matchFields", ["label", "description"]);
await page.waitForChanges();
await page.waitForTimeout(listDebounceTimeout);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an event we can listen for? This is fine for now, but we should start moving away from timeouts as puppeteer@22.2.0 removed page.waitForTimeout.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not currently, we would need some kind of event for when filteredItems is updated. Can you create an issue to add this so we can clean up these tests?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


expect(await list.getProperty("filteredItems")).toHaveLength(2);
expect(await list.getProperty("filteredData")).toHaveLength(2);

const visibleItems = await page.findAll("calcite-list-item:not([filter-hidden])");

expect(visibleItems.map((item) => item.id)).toEqual(["label-match", "description-match"]);
});

it("should support shift click to select multiple items", async () => {
const clickItemContent = (item: HTMLCalciteListItemElement, selector: string) => {
item.shadowRoot.querySelector(selector).dispatchEvent(new MouseEvent("click", { bubbles: true, shiftKey: true }));
Expand Down
15 changes: 14 additions & 1 deletion packages/calcite-components/src/components/list/list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,16 @@ export class List
*/
@Prop({ reflect: true }) loading = false;

/**
* Specifies the fields to match against when filtering. If not set, all fields will be matched.
driskull marked this conversation as resolved.
Show resolved Hide resolved
*/
@Prop() matchFields: string[];

@Watch("matchFields")
async handleMatchFieldsChange(): Promise<void> {
this.performFilter();
}

/**
* Use this property to override individual strings used by the component.
*/
Expand Down Expand Up @@ -517,6 +527,7 @@ export class List
hasFilterActionsStart,
hasFilterActionsEnd,
hasFilterNoResults,
matchFields,
} = this;
return (
<InteractiveContainer disabled={this.disabled}>
Expand Down Expand Up @@ -549,6 +560,7 @@ export class List
aria-label={filterPlaceholder}
disabled={disabled}
items={dataForFilter}
matchFields={matchFields}
onCalciteFilterChange={this.handleFilterChange}
placeholder={filterPlaceholder}
ref={this.setFilterEl}
Expand Down Expand Up @@ -804,13 +816,14 @@ export class List
}

private async performFilter(): Promise<void> {
const { filterEl, filterText } = this;
const { filterEl, filterText, matchFields } = this;

if (!filterEl) {
return;
}

filterEl.value = filterText;
filterEl.matchFields = matchFields;
await filterEl.filter(filterText);
this.updateFilteredData();
}
Expand Down
Loading