diff --git a/packages/ui-library/src/components/radio-group/index.ts b/packages/ui-library/src/components/radio-group/index.ts index 188cd0fc8..03065a904 100644 --- a/packages/ui-library/src/components/radio-group/index.ts +++ b/packages/ui-library/src/components/radio-group/index.ts @@ -10,7 +10,6 @@ import { InputSizesType, RadioGroupDirection } from '../../globals/types.js'; import { BlrFormCaptionGroupRenderFunction } from '../form-caption-group/renderFunction.js'; import { BlrFormCaptionRenderFunction } from '../form-caption/renderFunction.js'; import { TAG_NAME } from './renderFunction.js'; -import { TAG_NAME as RADIO_TAG_NAME } from '../radio/renderFunction.js'; import { LitElementCustom, ElementInterface } from '../../utils/lit/element.js'; import { BlrBlurEvent, @@ -18,6 +17,7 @@ import { BlrRadioGroupValueChangeEvent, createBlrRadioGroupValueChangeEvent, } from '../../globals/events.js'; +import { BlrRadio } from '../radio/index.js'; export type BlrRadioGroupEventHandlers = { blrFocus?: (event: BlrFocusEvent) => void; @@ -50,78 +50,63 @@ export class BlrRadioGroup extends LitElementCustom { @property() accessor legend: string | undefined; @property() accessor direction: RadioGroupDirection = 'horizontal'; @property() accessor theme: ThemeType = 'Light'; - protected _radioElements: Element[] | undefined; + protected _radioElements: BlrRadio[] | undefined; - protected handleRadioClick = (event: Event) => { - this._radioElements?.forEach((item) => { - const label = item.getAttribute('label'); - const radioInputElement = item.shadowRoot?.querySelector('input') as HTMLInputElement; + protected handleRadioCheckedEvent = (event: Event) => { + let currentlyCheckedRadio = (event?.target as HTMLInputElement).id; + + if (event.type === 'checkedChangeEvent') { + currentlyCheckedRadio = (event).detail.currentlyCheckedRadio.getAttribute('label'); + } - if (label === (event?.target as HTMLInputElement).id) { - radioInputElement.checked = true; + this._radioElements?.forEach((item: BlrRadio) => { + const label = item.getAttribute('label'); + if (label === currentlyCheckedRadio) { + item.checked = true; + } else { + item.checked = false; } }); + this.dispatchEvent( + createBlrRadioGroupValueChangeEvent({ + originalEvent: event, + selectedValue: (event?.target as HTMLInputElement).value, + }) + ); + event.preventDefault(); }; firstUpdated() { + this.addEventListener('checkedChangeEvent', this.handleRadioCheckedEvent); + } + + disconnectedCallback() { + this.removeEventListener('checkedChangeEvent', this.handleRadioCheckedEvent); + } + + handleSlotChange = () => { const slot = this.renderRoot?.querySelector('slot'); - this._radioElements = slot?.assignedElements({ flatten: false }); - - setTimeout(() => { - { - this._radioElements?.forEach((item, index, elements) => { - if (item.localName !== RADIO_TAG_NAME) { - throw new Error('child component of blr-radio-group must be blr-radio'); - } - - const radioElement = item.shadowRoot?.querySelector('input'); - const radioElementWrapper = item.shadowRoot?.querySelector('.blr-radio'); - - if (this.hasError) { - [radioElement, radioElementWrapper].forEach((element) => element.classList.add('error')); - } - - // eslint-disable-next-line - // @ts-expect-error - if (this.sizeVariant !== item.sizeVariant) item.sizeVariant = this.sizeVariant; - - radioElement.addEventListener('click', this.handleRadioClick); - - Object.defineProperty(radioElement, 'checked', { - set: function (value) { - if (value === false) { - return; - } - - // eslint-disable-next-line - // @ts-expect-error - item.setChecked(value); - elements.forEach((item) => { - const inputElement = item.shadowRoot?.querySelector('input') as HTMLInputElement; - if (inputElement.getAttribute('id') !== radioElement.getAttribute('id')) { - // eslint-disable-next-line - // @ts-expect-error - item.setChecked(false); - } - }); - - this.dispatchEvent( - createBlrRadioGroupValueChangeEvent({ - originalEvent: { ...new Event('change', { bubbles: true, cancelable: true }), target: radioElement }, - selectedValue: radioElement.value, - }) - ); - }, - get: function () { - return this.hasAttribute('checked'); - }, - }); - }); + this._radioElements = slot?.assignedElements({ flatten: false }) as HTMLElement[] & BlrRadio[]; + + this._radioElements?.forEach((item: BlrRadio) => { + if (item instanceof BlrRadio === false) { + throw new Error('child component of blr-radio-group must be blr-radio'); } - }, 0); - } + + const radioElement = item.shadowRoot?.querySelector('input'); + const radioElementWrapper = item.shadowRoot?.querySelector('.blr-radio'); + + if (this.hasError) { + [radioElement, radioElementWrapper].forEach((element) => element.classList.add('error')); + } + + if (this.sizeVariant !== item.sizeVariant) item.sizeVariant = this.sizeVariant; + + radioElement.addEventListener('click', this.handleRadioCheckedEvent); + }); + }; protected render() { if (!this.sizeVariant) { @@ -177,7 +162,7 @@ export class BlrRadioGroup extends LitElementCustom { ` : nothing}
- +
${this.hasHint || this.hasError diff --git a/packages/ui-library/src/components/radio/index.ts b/packages/ui-library/src/components/radio/index.ts index 32e21d21f..2b180235d 100644 --- a/packages/ui-library/src/components/radio/index.ts +++ b/packages/ui-library/src/components/radio/index.ts @@ -75,9 +75,27 @@ export class BlrRadio extends LitElementCustom { } } - protected setChecked = (status: boolean) => { - this.checked = status; - }; + firstUpdated() { + /* eslint-disable @typescript-eslint/no-this-alias */ + const _self = this; + Object.defineProperty(this._radioNode, 'checked', { + set: function (value) { + if (value === false) { + return; + } + _self.checked = value; + _self.dispatchEvent( + new CustomEvent('checkedChangeEvent', { + bubbles: true, + detail: { currentlyCheckedRadio: _self }, + }) + ); + }, + get: function () { + return this.hasAttribute('checked'); + }, + }); + } protected render() { if (this.sizeVariant) {