Skip to content

Commit

Permalink
fix(sbb-radio-button-group): radio group state update (#2138)
Browse files Browse the repository at this point in the history
  • Loading branch information
dauriamarco authored Nov 8, 2023
1 parent b048ad4 commit 3ae0902
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 16 deletions.
8 changes: 8 additions & 0 deletions src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3178,6 +3178,10 @@ declare namespace LocalJSX {
* @deprecated only used for React. Will probably be removed once React 19 is available.
*/
"onDidChange"?: (event: SbbCheckboxCustomEvent<any>) => void;
/**
* Internal event that emits when the input element is loaded.
*/
"onSbb-checkbox-loaded"?: (event: SbbCheckboxCustomEvent<void>) => void;
"onState-change"?: (event: SbbCheckboxCustomEvent<CheckboxStateChange>) => void;
/**
* Whether the checkbox is required.
Expand Down Expand Up @@ -4176,6 +4180,10 @@ declare namespace LocalJSX {
* Whether the radio button is disabled.
*/
"disabled"?: boolean;
/**
* Internal event that emits when the input element is loaded.
*/
"onSbb-radio-button-loaded"?: (event: SbbRadioButtonCustomEvent<void>) => void;
/**
* Internal event that emits whenever the state of the radio option in relation to the parent selection panel changes.
*/
Expand Down
7 changes: 4 additions & 3 deletions src/components/sbb-checkbox/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,10 @@ If you don't want the label to appear next to the checkbox, you can use `aria-la

## Events

| Event | Description | Type |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| `didChange` | <span style="color:red">**[DEPRECATED]**</span> only used for React. Will probably be removed once React 19 is available.<br/><br/> | `CustomEvent<any>` |
| Event | Description | Type |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
| `didChange` | <span style="color:red">**[DEPRECATED]**</span> only used for React. Will probably be removed once React 19 is available.<br/><br/> | `CustomEvent<any>` |
| `sbb-checkbox-loaded` | Internal event that emits when the input element is loaded. | `CustomEvent<void>` |


## Slots
Expand Down
1 change: 1 addition & 0 deletions src/components/sbb-checkbox/sbb-checkbox.events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
*/
export default {
didChange: 'didChange',
sbbCheckboxLoaded: 'sbb-checkbox-loaded',
stateChange: 'state-change',
};
10 changes: 10 additions & 0 deletions src/components/sbb-checkbox/sbb-checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ export class SbbCheckbox implements ComponentInterface {
})
public stateChange: EventEmitter<CheckboxStateChange>;

/**
* Internal event that emits when the input element is loaded.
*/
@Event({
bubbles: true,
eventName: 'sbb-checkbox-loaded',
})
public sbbCheckboxLoaded: EventEmitter<void>;

@Watch('checked')
public handleCheckedChange(currentValue: boolean, previousValue: boolean): void {
if (this._isSelectionPanelInput && currentValue !== previousValue) {
Expand Down Expand Up @@ -168,6 +177,7 @@ export class SbbCheckbox implements ComponentInterface {
!this._element.closest('sbb-selection-panel [slot="content"]');
this._handlerRepository.connect();
this._setupInitialStateAndAttributeObserver();
this._isSelectionPanelInput && this.sbbCheckboxLoaded.emit();
}

public componentDidLoad(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ describe('sbb-radio-button-group', () => {
'sbb-radio-button-group > sbb-radio-button#sbb-radio-3',
);

await element.setProperty('disabled', true);
element.setProperty('disabled', true);
await page.waitForChanges();

await disabledRadio.click();
Expand All @@ -82,7 +82,7 @@ describe('sbb-radio-button-group', () => {
await page.waitForChanges();
expect(secondRadio).not.toHaveAttribute('checked');

await element.setProperty('disabled', false);
element.setProperty('disabled', false);
await page.waitForChanges();

await disabledRadio.click();
Expand Down Expand Up @@ -146,5 +146,33 @@ describe('sbb-radio-button-group', () => {

expect(firstRadio).toHaveAttribute('checked');
});

it('sets the value correctly on slot change', async () => {
const firstRadio = await page.find('sbb-radio-button-group > sbb-radio-button#sbb-radio-1');

expect(firstRadio).toHaveAttribute('checked');
expect(await element.getProperty('value')).toBe('Value one');

await page.evaluate(() => {
const newRadios = ['New radio one', 'New radio two'];
const radioGroup = document.querySelector('sbb-radio-button-group');

// Remove all the radio buttons
while (radioGroup.firstChild) {
radioGroup.removeChild(radioGroup.firstChild);
}

// Add two new radios
newRadios.forEach(async (radio, i) => {
const newRadio = document.createElement('SBB-RADIO-BUTTON') as HTMLSbbRadioButtonElement;
newRadio.innerText = radio;
newRadio.value = radio;
newRadio.checked = i === 0;
radioGroup.appendChild(newRadio);
});
});

expect(await element.getProperty('value')).toBe('New radio one');
});
});
});
14 changes: 10 additions & 4 deletions src/components/sbb-radio-button-group/sbb-radio-button-group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export class SbbRadioButtonGroup implements ComponentInterface {
@Element() private _element!: HTMLElement;

private _hasSelectionPanel: boolean;
private _componentLoaded = false;

@Watch('value')
public valueChanged(value: any | undefined): void {
Expand Down Expand Up @@ -155,6 +156,11 @@ export class SbbRadioButtonGroup implements ComponentInterface {
this._hasSelectionPanel = !!this._element.querySelector('sbb-selection-panel');
toggleDatasetEntry(this._element, 'hasSelectionPanel', this._hasSelectionPanel);
this._handlerRepository.connect();
this._updateRadios(this.value);
}

public componentDidLoad(): void {
this._componentLoaded = true;
}

public disconnectedCallback(): void {
Expand All @@ -164,7 +170,7 @@ export class SbbRadioButtonGroup implements ComponentInterface {
@Listen('state-change', { passive: true })
public onRadioButtonSelect(event: CustomEvent<RadioButtonStateChange>): void {
event.stopPropagation();
if (event.detail.type !== 'checked') {
if (event.detail.type !== 'checked' || !this._componentLoaded) {
return;
}

Expand All @@ -185,11 +191,11 @@ export class SbbRadioButtonGroup implements ComponentInterface {
this.didChange.emit({ value });
}

private _updateRadios(): void {
const value = this.value ?? this._radioButtons.find((radio) => radio.checked)?.value;
private _updateRadios(initValue?: string): void {
this.value = initValue ?? this._radioButtons.find((radio) => radio.checked)?.value;

for (const radio of this._radioButtons) {
radio.checked = radio.value === value;
radio.checked = radio.value === this.value;
radio.size = this.size;
radio.allowEmptySelection = this.allowEmptySelection;

Expand Down
7 changes: 4 additions & 3 deletions src/components/sbb-radio-button/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,10 @@ The component has two different sizes, which can be changed using the `size` pro

## Events

| Event | Description | Type |
| -------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| `state-change` | Internal event that emits whenever the state of the radio option in relation to the parent selection panel changes. | `CustomEvent<RadioButtonStateChangeChecked \| RadioButtonStateChangeDisabled>` |
| Event | Description | Type |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| `sbb-radio-button-loaded` | Internal event that emits when the input element is loaded. | `CustomEvent<void>` |
| `state-change` | Internal event that emits whenever the state of the radio option in relation to the parent selection panel changes. | `CustomEvent<RadioButtonStateChangeChecked \| RadioButtonStateChangeDisabled>` |


## Methods
Expand Down
1 change: 1 addition & 0 deletions src/components/sbb-radio-button/sbb-radio-button.events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
* See stencil.config.ts in the root directory.
*/
export default {
sbbRadioButtonLoaded: 'sbb-radio-button-loaded',
stateChange: 'state-change',
};
10 changes: 10 additions & 0 deletions src/components/sbb-radio-button/sbb-radio-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@ export class SbbRadioButton implements ComponentInterface {
})
public stateChange: EventEmitter<RadioButtonStateChange>;

/**
* Internal event that emits when the input element is loaded.
*/
@Event({
bubbles: true,
eventName: 'sbb-radio-button-loaded',
})
public sbbRadioButtonLoaded: EventEmitter<void>;

@Watch('checked')
public handleCheckedChange(currentValue: boolean, previousValue: boolean): void {
if (currentValue !== previousValue) {
Expand Down Expand Up @@ -169,6 +178,7 @@ export class SbbRadioButton implements ComponentInterface {
!!this._selectionPanelElement &&
!this._element.closest('sbb-selection-panel [slot="content"]');
this._setupInitialStateAndAttributeObserver();
this._isSelectionPanelInput && this.sbbRadioButtonLoaded.emit();
}

public componentDidLoad(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('sbb-selection-panel', () => {
});

expect(root).toEqualHtml(`
<sbb-selection-panel data-has-content data-state="closed">
<sbb-selection-panel data-has-content>
<mock:shadow-root>
<div class="sbb-selection-panel">
<div class="sbb-selection-panel__badge">
Expand Down
12 changes: 9 additions & 3 deletions src/components/sbb-selection-panel/sbb-selection-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export class SbbSelectionPanel implements ComponentInterface {
);

private _contentElement: HTMLElement;
private _componentLoaded = false;

private get _input(): HTMLSbbCheckboxElement | HTMLSbbRadioButtonElement {
return this._element.querySelector('sbb-checkbox, sbb-radio-button') as
Expand All @@ -128,7 +129,7 @@ export class SbbSelectionPanel implements ComponentInterface {

@Listen('state-change', { passive: true })
public onInputChange(event: CustomEvent<RadioButtonStateChange | CheckboxStateChange>): void {
if (!this._state) {
if (!this._state || !this._componentLoaded) {
return;
}

Expand Down Expand Up @@ -157,15 +158,20 @@ export class SbbSelectionPanel implements ComponentInterface {
}

public connectedCallback(): void {
this._updateSelectionPanel();
this._handlerRepository.connect();
}

public componentDidLoad(): void {
this._componentLoaded = true;
}

public disconnectedCallback(): void {
this._handlerRepository.disconnect();
}

private _updateSelectionPanel(): void {
@Listen('sbb-checkbox-loaded')
@Listen('sbb-radio-button-loaded')
public updateSelectionPanel(): void {
this._checked = this._input?.checked;
this._state = this._checked || this.forceOpen ? 'opened' : 'closed';
this._disabled = this._input?.disabled;
Expand Down

0 comments on commit 3ae0902

Please sign in to comment.