From ebff4940f24d762d0abce8c796206e3e64f2bcb7 Mon Sep 17 00:00:00 2001 From: Woramat Ngamkham Date: Tue, 25 Oct 2022 14:56:06 +0700 Subject: [PATCH] refactor(form): implement `options` prop for Radio (#147) --- apps/demo/src/pages/index.astro | 5 +- apps/demo/src/pages/pizza-delivery.astro | 6 +- packages/common/types/control.types.ts | 5 +- .../form/components/controls/RadioGroup.astro | 4 +- packages/form/core/form-control.ts | 7 +++ packages/form/test/RadioGroup.astro.test.js | 58 ++++++++++++++++++- 6 files changed, 75 insertions(+), 10 deletions(-) diff --git a/apps/demo/src/pages/index.astro b/apps/demo/src/pages/index.astro index dd43a48..4446289 100644 --- a/apps/demo/src/pages/index.astro +++ b/apps/demo/src/pages/index.astro @@ -27,13 +27,14 @@ const form = new FormGroup([ name: "rating", label: "Rating", type: "radio", - value: ["1", "2", "3", "4", "5"], + value: "5", + options: ["1", "2", "3", "4", "5"], }, { name: "agreement", label: "Agreement", type: "radio", - value: [ + options: [ { label: "Agree", value: "yes", checked: true }, { label: "Disagree", value: "no" }, ], diff --git a/apps/demo/src/pages/pizza-delivery.astro b/apps/demo/src/pages/pizza-delivery.astro index 7a154bb..ce8b9e1 100644 --- a/apps/demo/src/pages/pizza-delivery.astro +++ b/apps/demo/src/pages/pizza-delivery.astro @@ -7,19 +7,19 @@ const baseForm = new FormGroup([ name: "crust", label: "Crust", type: "radio", - value: [{ label: "Garlic", value: "garlic" }], + options: [{ label: "Garlic", value: "garlic" }], }, { name: "size", label: "Size", type: "radio", - value: ["Small", "Medium", "Large"], + options: ["Small", "Medium", "Large"], }, { name: "sauce", label: "Sauce", type: "radio", - value: ["Tomato", "Barbeque"], + options: ["Tomato", "Barbeque"], }, ]); diff --git a/packages/common/types/control.types.ts b/packages/common/types/control.types.ts index 63daef4..f0f4dd1 100644 --- a/packages/common/types/control.types.ts +++ b/packages/common/types/control.types.ts @@ -34,6 +34,7 @@ export interface ControlBase { labelPosition?: "right" | "left"; placeholder?: string; validators?: string[]; // TODO: implement validator type + options?: string[] | RadioOption[]; // prevent build failed } export interface Checkbox extends ControlBase { @@ -43,13 +44,13 @@ export interface Checkbox extends ControlBase { export interface Radio extends Omit { type: "radio"; - value: string[] | RadioOption[]; + value?: string; + options: string[] | RadioOption[]; } export interface RadioOption { label: string; value: string; - checked?: boolean; } export interface Submit extends ControlBase { diff --git a/packages/form/components/controls/RadioGroup.astro b/packages/form/components/controls/RadioGroup.astro index 1961b18..34a7024 100644 --- a/packages/form/components/controls/RadioGroup.astro +++ b/packages/form/components/controls/RadioGroup.astro @@ -10,7 +10,7 @@ export interface Props { const { control } = Astro.props; -const options = control.value.map((option) => { +const options = control.options.map((option) => { if (typeof option === 'string') { return { label: option, @@ -24,7 +24,7 @@ const options = control.value.map((option) => { { options.map((option) => (
- {' '} + {' '} {option.label}
)) diff --git a/packages/form/core/form-control.ts b/packages/form/core/form-control.ts index 36ac819..4720a65 100644 --- a/packages/form/core/form-control.ts +++ b/packages/form/core/form-control.ts @@ -22,6 +22,7 @@ export class FormControl { private _placeholder: string | null = null; private _validators: string[] = []; private _errors: ValidationError[] = []; + private _options: string[] | RadioOption[] = []; private validate: (value: string, validators: string[]) => ValidationError[] = ( value: string, @@ -41,6 +42,7 @@ export class FormControl { labelPosition = 'left', placeholder = null, validators = [], + options = [], } = config; this._name = name; @@ -50,6 +52,7 @@ export class FormControl { this._labelPosition = labelPosition; this._placeholder = placeholder; this._validators = validators; + this._options = options; // TODO: implement independence // form should try to import validator, @@ -107,6 +110,10 @@ export class FormControl { return this._errors; } + get options() { + return this._options; + } + setValue(value: string) { this._value = value; this._isPristine = false; diff --git a/packages/form/test/RadioGroup.astro.test.js b/packages/form/test/RadioGroup.astro.test.js index ba0f74c..d8838d0 100644 --- a/packages/form/test/RadioGroup.astro.test.js +++ b/packages/form/test/RadioGroup.astro.test.js @@ -9,6 +9,7 @@ describe('RadioGroup.astro test', () => { beforeEach(() => { component = undefined; }); + it('Should render all radio options', async () => { // arrange const expectedOptions = 3; @@ -18,7 +19,7 @@ describe('RadioGroup.astro test', () => { label: 'FAKE LABEL', name: 'FAKE NAME', type: 'radio', - value: ['one', 'two', 'three'], + options: ['one', 'two', 'three'], }, showValidationHints: true, }; @@ -31,4 +32,59 @@ describe('RadioGroup.astro test', () => { // assert expect(matches.length).to.equal(expectedOptions); }); + + it('Should render a checked radio option from string[] correctly', async () => { + const expectedResult = ''; + const props = { + control: { + label: 'FAKE LABEL', + name: 'FAKE NAME', + type: 'radio', + value: 'two', + options: ['one', 'two', 'three'], + }, + showValidationHints: true, + }; + + // act + component = await getComponentOutput('./components/controls/RadioGroup.astro', props); + const actualResult = cleanString(component.html); + + // assert + expect(actualResult).to.contain(expectedResult); + }); + + it('Should render a checked radio option from RadioOption[] correctly', async () => { + const expectedResult = ''; + const props = { + control: { + label: 'FAKE LABEL', + name: 'FAKE NAME', + type: 'radio', + value: 'three', + options: [ + { + value: 'one', + label: '1', + }, + { + value: 'two', + label: '2', + }, + { + value: 'three', + label: '3', + }, + ], + }, + showValidationHints: true, + }; + + // act + component = await getComponentOutput('./components/controls/RadioGroup.astro', props); + const actualResult = cleanString(component.html); + + // assert + expect(actualResult).to.contain(expectedResult); + }); });