Skip to content

Commit

Permalink
fix(core/select): check if value is defined, before updating selection (
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiashader authored Nov 18, 2024
1 parent 1a13a46 commit dc59d67
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 22 deletions.
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

0 comments on commit dc59d67

Please sign in to comment.