Skip to content

Commit 10aeb7d

Browse files
committed
fix: non interctive form stages
BREAKING CHANGE: options, min & max moved to forminput type & definition
1 parent f7cb732 commit 10aeb7d

File tree

10 files changed

+183
-88
lines changed

10 files changed

+183
-88
lines changed

packages/common-helpers/src/form/input.ts

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -63,48 +63,39 @@ function getDefault<V extends iFormValue = iFormValue>(
6363
}
6464
}
6565

66+
function isChoiceType(type: eFormTypeSimple | eFormTypeComplex): boolean {
67+
const types: (eFormTypeSimple | eFormTypeComplex)[] = [
68+
eFormType.CHOICE,
69+
eFormType.SELECT,
70+
eFormType.SELECT_FILTER,
71+
];
72+
73+
return types.includes(type);
74+
}
75+
6676
export class FormInputDefault<T extends eFormTypeSimple | eFormTypeComplex = eFormTypeSimple>
6777
implements iFormInputDefault<T>
6878
{
69-
// private
70-
private _options!: iSelectOption[];
7179
// public
7280
public type!: T;
7381
// public readonly
7482
public readonly required!: boolean;
7583
public readonly placeholder!: string;
7684
public readonly icon!: tFormIcon;
7785
public readonly autocomplete!: tFormAutocomplete;
78-
public min!: number;
79-
public max!: number;
8086

8187
constructor(
8288
formInput: iFormInputDefault<T>,
8389
private _rerender?: (fi?: Partial<iFormInputDefault<T>>) => void
8490
) {
8591
this.required = formInput.required ?? false;
86-
this._options = formInput.options?.map(toOption) ?? [];
87-
this.min = formInput.min ?? 1;
88-
89-
// max cannot be lower than min or more than options if they exist
90-
const maxValue = this.options.length || formInput.max || 9e9;
91-
92-
this.max = maxValue < this.min ? this.min : maxValue;
9392

9493
if (formInput.type) this.type = formInput.type;
9594
if (formInput.placeholder) this.placeholder = formInput.placeholder;
9695
if (formInput.icon) this.icon = getIcon(formInput.icon, formInput.type);
9796
if (formInput.autocomplete) this.autocomplete = formInput.autocomplete;
9897
}
9998

100-
get options(): iSelectOption[] {
101-
return this._options;
102-
}
103-
set options(updatedOptions: iSelectOption[] | undefined) {
104-
this._options = updatedOptions || [];
105-
this.rerender();
106-
}
107-
10899
/** Rerender component */
109100
public rerender(): void {
110101
this._rerender?.(this);
@@ -125,12 +116,15 @@ export class FormInput<V extends iFormValue = iFormValue>
125116
implements iFormInput<V>
126117
{
127118
// private
119+
private _options!: iSelectOption[];
128120
private _values!: (V | V[])[];
129121
private _defaults?: [iFormInputDefault, iFormInputDefault, ...iFormInputDefault[]];
130122
// public readonly
131123
public readonly name!: string;
132124
public readonly title!: string;
133125
public readonly multiple!: boolean;
126+
public readonly min!: number;
127+
public readonly max!: number;
134128

135129
/**
136130
* Form input constructor
@@ -144,16 +138,51 @@ export class FormInput<V extends iFormValue = iFormValue>
144138
) {
145139
super(formInput, rerender);
146140

141+
this._options = formInput.options?.map(toOption) ?? [];
142+
this.min = formInput.min ?? 1;
143+
144+
// max cannot be lower than min or more than options if they exist
145+
const maxValue = this._options.length || formInput.max || 9e9;
146+
147+
this.max = maxValue < this.min ? this.min : maxValue;
148+
147149
const values = Array(this.min).fill(getDefault(formInput.type, formInput.defaults));
148150

149-
this._values = formInput.values ?? values;
151+
this._values = formInput.values?.length ? formInput.values : values;
152+
153+
// autoset single value
154+
if (
155+
isChoiceType(this.type) &&
156+
this.options.length === 1 &&
157+
this._values[0] !== this.options[0].value
158+
) {
159+
this._values = [this.options[0].value as V];
160+
}
161+
150162
this.name = formInput.name;
151163
this.multiple = formInput.multiple ?? false;
152164

153165
if (formInput.defaults) this._defaults = formInput.defaults;
154166
if (formInput.title) this.title = formInput.title;
155167
}
156168

169+
get options(): iSelectOption[] {
170+
return this._options;
171+
}
172+
set options(updatedOptions: iSelectOption[] | undefined) {
173+
this._options = updatedOptions || [];
174+
175+
if (
176+
isChoiceType(this.type) &&
177+
this.options.length === 1 &&
178+
this.values[0] !== this.options[0].value
179+
) {
180+
this.values = [this.options[0].value as V];
181+
}
182+
183+
this.rerender();
184+
}
185+
157186
get values(): (V | V[])[] {
158187
return this._values;
159188
}
@@ -257,6 +286,10 @@ export class FormInput<V extends iFormValue = iFormValue>
257286
}
258287

259288
export interface iForm {
289+
/**
290+
* Optional form key
291+
*/
292+
key?: string | number;
260293
title?: string;
261294
inputs: FormInput[];
262295
listen?: boolean;

packages/common-types/src/form.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,21 +103,12 @@ export type iFormValue = string | number | boolean | File;
103103
export interface iFormInputDefault<T extends eFormTypeSimple | eFormTypeComplex = eFormTypeSimple> {
104104
required?: boolean;
105105
type?: T;
106-
options?: (string | number | iFormOption)[];
107106
/**
108107
* String without the dots
109108
*/
110109
placeholder?: string;
111110
icon?: IconName | tFormIcon;
112111
autocomplete?: tFormAutocomplete;
113-
/**
114-
* if muliple is set to true this optional value would be the required minimun amount of values
115-
*/
116-
min?: number;
117-
/**
118-
* if multiple is set to true this optional value would be the mandatory maximun amount of values
119-
*/
120-
max?: number;
121112
}
122113

123114
/**
@@ -126,6 +117,7 @@ export interface iFormInputDefault<T extends eFormTypeSimple | eFormTypeComplex
126117
export interface iFormInput<V extends iFormValue = iFormValue>
127118
extends iFormInputDefault<eFormTypeSimple | eFormTypeComplex> {
128119
name: string;
120+
options?: (string | number | iFormOption)[];
129121
/**
130122
* An array of values to simplify validation
131123
*
@@ -144,6 +136,14 @@ export interface iFormInput<V extends iFormValue = iFormValue>
144136
* Ex: { multiple: true, min:3, max:3 } would make 3 values a requirement
145137
*/
146138
multiple?: boolean;
139+
/**
140+
* if muliple is set to true this optional value would be the required minimun amount of values
141+
*/
142+
min?: number;
143+
/**
144+
* if multiple is set to true this optional value would be the mandatory maximun amount of values
145+
*/
146+
max?: number;
147147
}
148148

149149
/**

packages/components-vue/src/components/form/Input.vue

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
<FormInputLoop
7373
v-else
7474
v-slot="{ i }"
75+
:key="input.options.length + models.length"
7576
:models="models"
7677
:input="input"
7778
:theme="theme"
@@ -86,9 +87,12 @@
8687
<Input
8788
v-for="(model, index) in models[i].value"
8889
:key="
89-
input.defaults?.[index].placeholder ||
90-
input.defaults?.[index].type ||
91-
index
90+
[
91+
input.options.length,
92+
input.defaults?.[i]?.placeholder,
93+
input.defaults?.[i]?.type,
94+
i + index,
95+
].join('-')
9296
"
9397
:input="
9498
input

packages/components-vue/src/components/form/InputLoop.vue

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
<template>
2-
<div
3-
v-for="(model, i) in models"
4-
:key="input.defaults?.[i]?.placeholder || input.defaults?.[i]?.type || i"
5-
class="--width"
6-
>
2+
<div v-for="(model, i) in models" :key="i" class="--width">
73
<div class="flx --flxRow --flx-start-center --gap-5">
84
<slot v-bind="{ i }"></slot>
95
<ActionLink

packages/components-vue/src/components/form/Simple.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<BaseErrorBoundary :theme="theme">
33
<LoaderContentFetch
4-
v-if="modelValue?.length"
4+
v-if="model.length"
55
v-slot="{ content }"
66
:theme="theme"
77
:label="t('form_loading_countries')"

packages/components-vue/src/components/form/Stages.stories.ts

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,22 @@ export const stages: iForm[][] = [
3333
}),
3434
new FormInput({
3535
required: true,
36-
options: [{ value: 1, alias: "Payment on Delivery" }],
36+
options: [
37+
{ value: 1, alias: "Payment on Delivery" },
38+
{ value: 2, alias: "Paypal" },
39+
{ value: 3, alias: "Credit card" },
40+
],
3741
type: eFormType.SELECT_FILTER,
38-
placeholder: "Search payment methods",
42+
placeholder: "Search payment method",
3943
icon: "credit-card",
4044
autocomplete: "off",
41-
name: "paymentMethodIds",
42-
multiple: true,
43-
title: "Choose one or several payment methods",
45+
name: "paymentMethodId",
46+
title: "Choose one payment method",
4447
}),
4548
],
4649
},
50+
],
51+
[
4752
{
4853
title: "UI component",
4954
inputs: [
@@ -63,21 +68,6 @@ export const stages: iForm[][] = [
6368
],
6469
listen: true,
6570
},
66-
],
67-
[
68-
{
69-
title: "Children",
70-
inputs: [
71-
new FormInput({
72-
type: eFormType.SELECT_FILTER,
73-
placeholder: "Search offer fields",
74-
title: "Choose offer fields",
75-
icon: ["align-left", {}],
76-
name: "offerFieldChildrenIds",
77-
multiple: true,
78-
}),
79-
],
80-
},
8171
{
8272
title: "Offer field values",
8373
inputs: [
@@ -96,7 +86,11 @@ export const stages: iForm[][] = [
9686
async function submitFn(inputs: FormInput[]): Promise<boolean | iInvalidInput[]> {
9787
const { utils } = useForm();
9888

99-
console.log(utils.getFormValues(inputs));
89+
const { values, invalidInputs } = utils.getFormValues(inputs);
90+
91+
alert(JSON.stringify(values));
92+
93+
if (invalidInputs.length) return invalidInputs;
10094

10195
return true;
10296
}
@@ -113,4 +107,44 @@ export const Sample: Story = {
113107
args: { stages, submitFn },
114108
};
115109

110+
export const WithInvalidStage: Story = {
111+
args: {
112+
stages: [
113+
[
114+
{
115+
title: "Offer field values",
116+
inputs: [
117+
new FormInput({
118+
placeholder: "E.g. Blue",
119+
title: "Possible Value",
120+
icon: ["industry", {}],
121+
name: "offerFieldValues",
122+
multiple: true,
123+
}),
124+
],
125+
},
126+
],
127+
[
128+
{
129+
title: "Children",
130+
/**
131+
* No valid inputs
132+
*/
133+
inputs: [
134+
new FormInput({
135+
type: eFormType.SELECT_FILTER,
136+
placeholder: "Search offer fields",
137+
title: "Choose offer fields",
138+
icon: ["align-left", {}],
139+
name: "offerFieldChildrenIds",
140+
multiple: true,
141+
}),
142+
],
143+
},
144+
],
145+
],
146+
submitFn,
147+
},
148+
};
149+
116150
export default meta;

0 commit comments

Comments
 (0)