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

fix(core/select): check if value is defined, before updating selection #1557

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
5 changes: 5 additions & 0 deletions .changeset/lovely-garlics-pretend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@siemens/ix': patch
---

fix(core/select): check if value is defined, before updating selection
7 changes: 6 additions & 1 deletion packages/core/component-doc.json
Original file line number Diff line number Diff line change
Expand Up @@ -13413,6 +13413,11 @@
"capture": false,
"passive": false
},
{
"event": "ix-select-item:valueChange",
"capture": false,
"passive": false
},
{
"event": "ix-select-item:labelChange",
"capture": false,
Expand Down Expand Up @@ -13469,7 +13474,7 @@
"type": "string"
}
],
"optional": false,
"optional": true,
"required": false
},
{
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1923,7 +1923,7 @@ export namespace Components {
/**
* Displayed name of the item
*/
"label": string;
"label"?: string;
/**
* @param event
*/
Expand Down
16 changes: 10 additions & 6 deletions packages/core/src/components/dropdown/dropdown-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function hasDropdownItemWrapperImplemented(
item: unknown
): item is DropdownItemWrapper {
return (
item &&
item !== null &&
(item as DropdownItemWrapper).getDropdownItemElement !== undefined &&
typeof (item as DropdownItemWrapper).getDropdownItemElement === 'function'
);
Expand Down Expand Up @@ -91,7 +91,7 @@ class DropdownController {
}

present(dropdown: DropdownInterface) {
if (!dropdown.isPresent() && dropdown.willPresent()) {
if (!dropdown.isPresent() && dropdown.willPresent?.()) {
this.submenuIds[dropdown.getId()] = dropdown.getAssignedSubmenuIds();
dropdown.present();
}
Expand All @@ -100,12 +100,15 @@ class DropdownController {
dismissChildren(uid: string) {
const childIds = this.submenuIds[uid] || [];
for (const id of childIds) {
this.dismiss(this.dropdowns.get(id));
const dropdown = this.dropdowns.get(id);
if (dropdown) {
this.dismiss(dropdown);
}
}
}

dismiss(dropdown: DropdownInterface) {
if (dropdown.isPresent() && dropdown.willDismiss()) {
if (dropdown.isPresent() && dropdown.willDismiss?.()) {
this.dismissChildren(dropdown.getId());
dropdown.dismiss();
delete this.submenuIds[dropdown.getId()];
Expand Down Expand Up @@ -175,7 +178,8 @@ class DropdownController {

private pathIncludesDropdown(eventTargets: EventTarget[]) {
return !!eventTargets.find(
(element: HTMLElement) => element.tagName === 'IX-DROPDOWN'
(element: EventTarget) =>
(element as HTMLElement).tagName === 'IX-DROPDOWN'
);
}

Expand All @@ -196,7 +200,7 @@ class DropdownController {
private addOverlayListeners() {
this.isWindowListenerActive = true;

window.addEventListener('click', (event: PointerEvent) => {
window.addEventListener('click', (event: MouseEvent) => {
const hasTrigger = this.pathIncludesTrigger(event.composedPath());
const hasDropdown = this.pathIncludesDropdown(event.composedPath());

Expand Down
12 changes: 12 additions & 0 deletions packages/core/src/components/select-item/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,15 @@ export class IxSelectItemLabelChangeEvent extends CustomEvent<{
});
}
}

export class IxSelectItemValueChangeEvent extends CustomEvent<{
oldValue: string;
newValue: string;
}> {
constructor(detail: { oldValue: string; newValue: string }) {
super('ix-select-item:valueChange', {
bubbles: true,
detail,
});
}
}
42 changes: 31 additions & 11 deletions packages/core/src/components/select-item/select-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import {
Prop,
Watch,
} from '@stencil/core';
import { IxSelectItemLabelChangeEvent } from './events';
import {
IxSelectItemLabelChangeEvent,
IxSelectItemValueChangeEvent,
} from './events';
import { DropdownItemWrapper } from '../dropdown/dropdown-controller';

@Component({
Expand All @@ -27,12 +30,12 @@ import { DropdownItemWrapper } from '../dropdown/dropdown-controller';
shadow: true,
})
export class SelectItem implements DropdownItemWrapper {
@Element() hostElement: HTMLIxSelectItemElement;
@Element() hostElement!: HTMLIxSelectItemElement;

/**
* Displayed name of the item
*/
@Prop({ reflect: true }) label: string;
@Prop({ reflect: true }) label?: string;

/**
* The value of the item.
Expand All @@ -55,12 +58,14 @@ export class SelectItem implements DropdownItemWrapper {
/**
* Item clicked
*/
@Event() itemClick: EventEmitter<string>;
@Event() itemClick!: EventEmitter<string>;

private componentLoaded = false;

/** @internal */
@Method()
async getDropdownItemElement(): Promise<HTMLIxDropdownItemElement> {
return this.dropdownItem;
return this.dropdownItem!;
}

/**
Expand All @@ -83,16 +88,31 @@ export class SelectItem implements DropdownItemWrapper {
if (this.value === undefined || this.value === null) {
throw Error('ix-select-item must have a `value` property');
}
this.componentLoaded = true;
}

@Watch('value')
onValueChange(newValue: string, oldValue: string) {
if (this.componentLoaded) {
this.hostElement.dispatchEvent(
new IxSelectItemValueChangeEvent({
newValue: newValue,
oldValue: oldValue,
})
);
}
}

@Watch('label')
labelChange(newValue: string, oldValue: string) {
this.hostElement.dispatchEvent(
new IxSelectItemLabelChangeEvent({
newValue: newValue,
oldValue: oldValue,
})
);
if (this.componentLoaded) {
this.hostElement.dispatchEvent(
new IxSelectItemLabelChangeEvent({
newValue: newValue,
oldValue: oldValue,
})
);
}
}

render() {
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/components/select/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,10 @@ export class Select {

private arrowFocusController?: ArrowFocusController;

private itemObserver = createMutationObserver(() => {
private readonly itemObserver = createMutationObserver(() => {
if (!this.arrowFocusController) {
return;
}

this.arrowFocusController.items = this.visibleNonShadowItems;
});

Expand Down Expand Up @@ -326,7 +325,7 @@ export class Select {

this.items.forEach((item) => {
item.selected = ids.some((i) => {
if (typeof i !== typeof item.value) {
if (item.value !== undefined && typeof i !== typeof item.value) {
return i.toString() === item.value.toString();
} else {
return i === item.value;
Expand Down Expand Up @@ -375,6 +374,7 @@ export class Select {
this.updateSelection();
}

@Listen('ix-select-item:valueChange')
@Listen('ix-select-item:labelChange')
onLabelChange(event: IxSelectItemLabelChangeEvent) {
event.preventDefault();
Expand Down
Loading