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

[RadioButton, Checkbox]: Unify output namings, refactor radio button and checkbox blur and change events #445

Merged
merged 11 commits into from
Sep 28, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export class CheckboxComponent implements OnInit, OnDestroy {
if ((event.relatedTarget as HTMLElement)?.getAttribute('name') !== this._checkboxGroup.id) {
setTimeout(() => {
if (document.activeElement?.getAttribute('name') !== this._checkboxGroup.id) {
this._checkboxGroup.handleBlur.emit(event);
this._checkboxGroup.setGroupBlurredOut(true);
}
}, 150);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { RadioButtonGroupComponent } from './radio-button-group.component';
import {
FudisRadioButtonGroupChangeEvent,
FudisRadioButtonChangeEvent,
FudisRadioButtonOption,
fudisInputSizeArray,
} from '../../../types/forms';
Expand Down Expand Up @@ -50,9 +50,9 @@ class MockContainerComponent {
{ value: 'capybara', label: 'Capybara', id: 'test-3' },
];

eventReceived: FudisRadioButtonGroupChangeEvent;
eventReceived: FudisRadioButtonChangeEvent;

handleRadioButtonClick(event: FudisRadioButtonGroupChangeEvent): void {
handleRadioButtonClick(event: FudisRadioButtonChangeEvent): void {
this.eventReceived = event;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
Optional,
Output,
} from '@angular/core';
import { FudisInputSize, FudisRadioButtonGroupChangeEvent } from '../../../types/forms';
import { FudisInputSize, FudisRadioButtonChangeEvent } from '../../../types/forms';
import { hasRequiredValidator } from '../../../utilities/form/getValidators';
import { FudisIdService } from '../../../services/id/id.service';
import { FormComponent } from '../form/form.component';
Expand Down Expand Up @@ -50,7 +50,7 @@ export class RadioButtonGroupComponent
/**
* Emit form control and changed option when one option is clicked
*/
@Output() handleChange = new EventEmitter<FudisRadioButtonGroupChangeEvent>();
@Output() handleChange = new EventEmitter<FudisRadioButtonChangeEvent>();

ngOnInit() {
this._setParentComponentId('radio-button-group');
Expand All @@ -75,7 +75,7 @@ export class RadioButtonGroupComponent
}

public triggerEmit(id: string, label: string): void {
const data: FudisRadioButtonGroupChangeEvent = {
const data: FudisRadioButtonChangeEvent = {
option: {
id: id,
label: label,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"
(focus)="_parentGroup.onFocus($event)"
(keyup)="_parentGroup.handleKeyUp.emit($event)"
(blur)="radioButtonBlur.emit(label); _parentGroup.handleBlur.emit($event)"
(blur)="_parentGroup.handleBlur.emit($event)"
(change)="_onChange()"
/>
<div class="fudis-radio-button__content">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { FudisTranslationService } from '../../../../services/translation/transl
import { RadioButtonComponent } from './radio-button.component';
import { FudisIdService } from '../../../../services/id/id.service';
import { RadioButtonGroupComponent } from '../radio-button-group.component';
import { FudisRadioButtonOption } from '../../../../types/forms';
import { FudisRadioButtonChangeEvent, FudisRadioButtonOption } from '../../../../types/forms';
import { FieldSetComponent } from '../../fieldset/fieldset.component';
import { ContentDirective } from '../../../../directives/content-projection/content/content.directive';
import { GridDirective } from '../../../../directives/grid/grid/grid.directive';
Expand All @@ -17,13 +17,15 @@ import { IconComponent } from '../../../icon/icon.component';
import { ValidatorErrorMessageComponent } from '../../error-message/validator-error-message/validator-error-message.component';
import { GuidanceComponent } from '../../guidance/guidance.component';
import { FudisValidators } from '../../../../utilities/form/validators';
import { By } from '@angular/platform-browser';
import { getElement } from '../../../../utilities/tests/utilities';

@Component({
selector: 'fudis-mock-component',
template: `<fudis-radio-button-group
[id]="'radio-button-test-group'"
[label]="'Choose a pet'"
[control]="_testControl"
[control]="testControl"
>
<fudis-radio-button
*ngFor="let option of _options"
Expand All @@ -32,8 +34,8 @@ import { FudisValidators } from '../../../../utilities/form/validators';
/>
</fudis-radio-button-group>`,
})
class MockContainerComponent {
protected _testControl: FormControl = new FormControl(
class MockComponent {
public testControl: FormControl = new FormControl(
null,
FudisValidators.required('You must choose an animal'),
);
Expand All @@ -46,12 +48,13 @@ class MockContainerComponent {
}

describe('RadioButtonComponent', () => {
let fixture: ComponentFixture<MockContainerComponent> | ComponentFixture<RadioButtonComponent>;
let fixture: ComponentFixture<MockComponent> | ComponentFixture<RadioButtonComponent>;
let component: MockComponent;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [
MockContainerComponent,
MockComponent,
RadioButtonComponent,
RadioButtonGroupComponent,
FieldSetComponent,
Expand All @@ -74,7 +77,9 @@ describe('RadioButtonComponent', () => {
});

beforeEach(() => {
fixture = TestBed.createComponent(MockContainerComponent);
fixture = TestBed.createComponent(MockComponent);

component = fixture.componentInstance;

fixture.detectChanges();
});
Expand Down Expand Up @@ -130,13 +135,34 @@ describe('RadioButtonComponent', () => {
});

describe('Interaction and logic when clicking', () => {
it('should have correct value', () => {
const input: HTMLInputElement = fixture.debugElement.nativeElement.querySelector(
'input#radio-button-test-group-item-1',
);
it('should have correct value and emit handleChange() when clicking component', () => {
const radioButtonComponentToSpy = fixture.debugElement.query(
By.directive(RadioButtonComponent),
).componentInstance;

const optionToMatch: FudisRadioButtonOption<object> = {
id: 'radio-button-test-group-item-1',
value: 'platypus',
label: 'Platypus',
};

let handleChangeTriggered = false;

radioButtonComponentToSpy.handleChange.subscribe((value: FudisRadioButtonChangeEvent) => {
if (value) {
handleChangeTriggered = true;
expect(value.option).toEqual(optionToMatch);
expect(value.control.value).toEqual('platypus');
}
});

const input = getElement(fixture, 'input#radio-button-test-group-item-1') as HTMLInputElement;

input.dispatchEvent(new MouseEvent('click'));

expect(component.testControl.value).toEqual('platypus');

const inputValue = input.getAttribute('ng-reflect-value');
expect(inputValue).toEqual('platypus');
expect(handleChangeTriggered).toBeTruthy();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from '@angular/core';

import { FudisIdService } from '../../../../services/id/id.service';
import { FudisRadioButtonChangeEvent, FudisRadioButtonOption } from '../../../../types/forms';
import { RadioButtonGroupComponent } from '../radio-button-group.component';

@Component({
Expand All @@ -34,9 +35,9 @@ export class RadioButtonComponent implements OnInit {
@Input({ required: true }) label: string;

/**
* Blur event output
* Emits changed Radio button option and form control.
*/
@Output() radioButtonBlur = new EventEmitter<string>();
@Output() handleChange = new EventEmitter<FudisRadioButtonChangeEvent>();

/**
* Id for single Radio Button
Expand All @@ -47,6 +48,17 @@ export class RadioButtonComponent implements OnInit {
* Selected Radio Button change
*/
protected _onChange(): void {
const optionToEmit: FudisRadioButtonOption<object> = {
id: this._id,
label: this.label,
value: this._parentGroup?.control.value,
};

/**
* This Radio button's emit
*/
this.handleChange.emit({ option: optionToEmit, control: this._parentGroup.control });

/**
* Call parent's function, which triggers Radio Button Group's emit
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
DialogCloseDirective,
} from './dialog-directives';
import { getElement } from '../../utilities/tests/utilities';
import { AlertGroupComponent } from '../../components/alert/alert-group/alert-group.component';

@Component({
selector: 'fudis-mock-dialog',
Expand Down Expand Up @@ -52,6 +53,7 @@ describe('DialogDirectives', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [
AlertGroupComponent,
BodyTextComponent,
ButtonComponent,
HeadingComponent,
Expand Down
2 changes: 1 addition & 1 deletion ngx-fudis/projects/ngx-fudis/src/lib/types/forms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export type FudisCheckboxGroupChangeEvent = {
formGroup: FormGroup<FudisCheckboxGroupFormGroup<object>>;
};

export type FudisRadioButtonGroupChangeEvent = {
export type FudisRadioButtonChangeEvent = {
option: FudisRadioButtonOption<object>;
control: FormControl<unknown>;
};
Expand Down
Loading