Skip to content

Commit

Permalink
feat(core/categroy-filter): add filter cleared event (#1562)
Browse files Browse the repository at this point in the history
Co-authored-by: Daniel Leroux <[email protected]>
  • Loading branch information
nuke-ellington and danielleroux authored Nov 25, 2024
1 parent 720fb53 commit 70ea07d
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 31 deletions.
7 changes: 7 additions & 0 deletions .changeset/large-cherries-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@siemens/ix-angular": minor
"@siemens/ix": minor
"@siemens/ix-vue": minor
---

Add filter cleared event to ix-categroy-filter.
6 changes: 5 additions & 1 deletion packages/angular/src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ export class IxCategoryFilter {
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
c.detach();
this.el = r.nativeElement;
proxyOutputs(this, this.el, ['categoryChanged', 'inputChanged', 'filterChanged']);
proxyOutputs(this, this.el, ['categoryChanged', 'inputChanged', 'filterChanged', 'filterCleared']);
}
}

Expand All @@ -385,6 +385,10 @@ export declare interface IxCategoryFilter extends Components.IxCategoryFilter {
* Event dispatched whenever the filter state changes.
*/
filterChanged: EventEmitter<CustomEvent<IIxCategoryFilterFilterState>>;
/**
* Event dispatched whenever the filter gets cleared.
*/
filterCleared: EventEmitter<CustomEvent<void>>;
}


Expand Down
14 changes: 14 additions & 0 deletions packages/core/component-doc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2490,6 +2490,20 @@
"docs": "Event dispatched whenever the filter state changes.",
"docsTags": []
},
{
"event": "filterCleared",
"detail": "void",
"bubbles": true,
"complexType": {
"original": "void",
"resolved": "void",
"references": {}
},
"cancelable": true,
"composed": true,
"docs": "Event dispatched whenever the filter gets cleared.",
"docsTags": []
},
{
"event": "inputChanged",
"detail": "InputState",
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3630,6 +3630,7 @@ declare global {
"categoryChanged": string;
"inputChanged": InputState;
"filterChanged": FilterState;
"filterCleared": void;
}
interface HTMLIxCategoryFilterElement extends Components.IxCategoryFilter, HTMLStencilElement {
addEventListener<K extends keyof HTMLIxCategoryFilterElementEventMap>(type: K, listener: (this: HTMLIxCategoryFilterElement, ev: IxCategoryFilterCustomEvent<HTMLIxCategoryFilterElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
Expand Down Expand Up @@ -5450,6 +5451,10 @@ declare namespace LocalJSX {
* Event dispatched whenever the filter state changes.
*/
"onFilterChanged"?: (event: IxCategoryFilterCustomEvent<FilterState>) => void;
/**
* Event dispatched whenever the filter gets cleared.
*/
"onFilterCleared"?: (event: IxCategoryFilterCustomEvent<void>) => void;
/**
* Event dispatched whenever the text input changes.
*/
Expand Down
63 changes: 45 additions & 18 deletions packages/core/src/components/category-filter/category-filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ export class CategoryFilter {
*/
@Event() filterChanged!: EventEmitter<FilterState>;

/**
* Event dispatched whenever the filter gets cleared.
*/
@Event() filterCleared!: EventEmitter<void>;

get dropdown() {
return this.hostElement.shadowRoot!.querySelector('ix-dropdown');
}
Expand Down Expand Up @@ -213,7 +218,8 @@ export class CategoryFilter {
this.formKeyDownListener = addDisposableEventListener(
this.formElement,
'keydown',
() => this.handleFormElementKeyDown
((e: KeyboardEvent) =>
this.handleFormElementKeyDown(e)) as EventListener
);

this.preventDefaultListener = addDisposableEventListener(
Expand All @@ -233,7 +239,7 @@ export class CategoryFilter {
this.inputKeyDownListener = addDisposableEventListener(
this.textInput.current,
'keydown',
() => this.handleInputElementKeyDown
((e: KeyboardEvent) => this.handleInputElementKeyDown(e)) as EventListener
);

this.focusInListener = addDisposableEventListener(
Expand Down Expand Up @@ -354,24 +360,35 @@ export class CategoryFilter {
}
}

private focusElement(selector: string): boolean {
const item = this.hostElement.shadowRoot!.querySelector(selector);
if (item instanceof HTMLElement) {
item.focus();
return true;
}
return false;
}

private onArrowDown(e: KeyboardEvent) {
const baseSelector = `.category-item-${
this.category !== '' ? 'value' : 'id'
}`;
const fallbackSelector = '.category-item';

if (this.focusElement(baseSelector)) {
e.stopPropagation();
return;
}

if (this.suggestions?.length && this.focusElement(fallbackSelector)) {
e.stopPropagation();
}
}

private handleInputElementKeyDown(e: KeyboardEvent) {
switch (e.code) {
case 'ArrowDown': {
const selector = `.category-item-${
this.category !== '' ? 'value' : 'id'
}`;
let item = this.hostElement.shadowRoot!.querySelector(selector);

if (item instanceof HTMLElement) {
item.focus();
e.stopPropagation();
} else if (this.suggestions?.length) {
item = this.hostElement.shadowRoot!.querySelector('.category-item');
if (item instanceof HTMLElement) {
item.focus();
e.stopPropagation();
}
}
this.onArrowDown(e);
break;
}

Expand All @@ -393,7 +410,10 @@ export class CategoryFilter {

case 'Enter':
case 'NumpadEnter':
this.addToken(this.inputValue, this.category);
this.addToken(
this.inputValue,
this.category || this.ID_CUSTOM_FILTER_VALUE
);
e.preventDefault();
break;
}
Expand Down Expand Up @@ -482,13 +502,20 @@ export class CategoryFilter {
}

private resetFilter(e: Event) {
const { defaultPrevented } = this.filterCleared.emit();

if (defaultPrevented) {
return;
}

e.stopPropagation();
this.closeDropdown();
this.filterTokens = [];
if (this.category) {
this.category = '';
this.categoryChanged.emit(undefined);
}

this.emitFilterEvent();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,33 @@ test.describe('category-preview test', () => {
});
});

test('clear category-preview', async ({ page }) => {
test('add token', async ({ page }) => {
const token = 'Test';
await page.waitForSelector('ix-category-filter');
await page.locator('input').first().click();
await page.locator('.category-item').first().click();
const input = await page.locator('input').first();
await input.click();
await input.fill(token);
await page.keyboard.press('Enter');
const chip = await page.locator('ix-filter-chip').first();
await expect(chip).toContainText(token);
});

const categoryPreviewPromise = page.evaluate(() => {
return new Promise((resolve) => {
function onCategoryChanged(event) {
resolve(event.detail);
}
test('clear category-preview', async ({ page }) => {
const categoryFilter = page.locator('ix-category-filter');
await categoryFilter.locator('input').first().click();
await categoryFilter.locator('.category-item').first().click();

document.addEventListener('categoryChanged', onCategoryChanged);
});
});
const categoryPreviewPromise = categoryFilter.evaluate(
(element: HTMLIxCategoryFilterElement) => {
return new Promise((resolve) => {
function onCategoryChanged(event: CustomEvent) {
resolve(event.detail);
}

element.addEventListener('categoryChanged', onCategoryChanged);
});
}
);

await page.locator('ix-icon-button').first().click();
const categoryPreview = await categoryPreviewPromise;
Expand Down
3 changes: 2 additions & 1 deletion packages/vue/src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ export const IxCategoryFilter = /*@__PURE__*/ defineContainer<JSX.IxCategoryFilt
'i18nPlainText',
'categoryChanged',
'inputChanged',
'filterChanged'
'filterChanged',
'filterCleared'
]);


Expand Down

0 comments on commit 70ea07d

Please sign in to comment.