Skip to content
This repository was archived by the owner on Jun 27, 2023. It is now read-only.

Commit 1c31da3

Browse files
authored
Merge pull request #157 from alvarosaburido/feature/refactor-fields-logic-evan2
fix(types): fix new types usage
2 parents 2104599 + 8bba457 commit 1c31da3

File tree

7 files changed

+2434
-3116
lines changed

7 files changed

+2434
-3116
lines changed

package-lock.json

Lines changed: 2375 additions & 3053 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/dynamic-form/DynamicForm.vue

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ import {
4949
import { DynamicForm } from './form';
5050
import DynamicInput from '../dynamic-input/DynamicInput.vue';
5151
52-
import { InputBase, FormControl } from '../../core/models';
52+
import { FormControl, InputType } from '../../core/models';
5353
import { dynamicFormsSymbol } from '../../useApi';
5454
import { removeEmpty } from '../../core/utils/helpers';
5555
@@ -64,6 +64,12 @@ const components = {
6464
DynamicInput,
6565
};
6666
67+
const EMPTY_CONTROL = {
68+
dirty: false,
69+
touched: false,
70+
valid: true,
71+
};
72+
6773
/* const AVAILABLE_THEMES = ['default', 'material'];
6874
*/
6975
export default defineComponent({
@@ -73,7 +79,7 @@ export default defineComponent({
7379
setup(props, ctx) {
7480
const { options } = inject(dynamicFormsSymbol);
7581
76-
const controls: Ref<FormControl[]> = ref([]);
82+
const controls: Ref<FormControl<InputType>[]> = ref([]);
7783
const formValues = reactive({});
7884
const submited = ref(false);
7985
@@ -108,8 +114,8 @@ export default defineComponent({
108114
});
109115
110116
const isValid = computed(() => {
111-
const control = controls?.value?.find(control => !control.valid);
112-
return control ? control.valid : true;
117+
const hasInvalidControls = controls.value.some(control => !control.valid);
118+
return !hasInvalidControls;
113119
});
114120
115121
const errors = computed(() => {
@@ -146,33 +152,31 @@ export default defineComponent({
146152
}
147153
});
148154
149-
function valueChange(changedValue) {
155+
function valueChange(changedValue: Record<string, unknown>) {
150156
Object.assign(formValues, changedValue);
151157
ctx.emit('changed', removeEmpty(formValues));
152158
}
153159
154-
function mapControls(empty?) {
160+
function mapControls(empty?: boolean) {
155161
const controlArray =
156162
Object.entries(props.form?.fields).map(
157-
([key, field]: [string, InputBase]) =>
163+
([key, field]: [string, InputType]) =>
158164
empty
159165
? ({
160166
...field,
161167
name: key,
162168
value: null,
163-
dirty: false,
164-
touched: false,
165-
} as FormControl)
169+
...EMPTY_CONTROL,
170+
} as FormControl<InputType>)
166171
: ({
167172
...field,
168173
name: key,
169-
dirty: false,
170-
touched: false,
171-
} as FormControl),
174+
...EMPTY_CONTROL,
175+
} as FormControl<InputType>),
172176
) || [];
173177
if (props.form.fieldOrder) {
174178
controls.value = controlArray.sort(
175-
(a: FormControl, b: FormControl) =>
179+
(a: FormControl<InputType>, b: FormControl<InputType>) =>
176180
props.form.fieldOrder.indexOf(a.name) -
177181
props.form.fieldOrder.indexOf(b.name),
178182
);
@@ -201,7 +205,9 @@ export default defineComponent({
201205
? controls.value.reduce((prev, curr) => {
202206
const obj = {};
203207
obj[curr.name] =
204-
curr.type === 'number' ? parseFloat(curr.value) : curr.value;
208+
curr.type === 'number'
209+
? parseFloat(`${curr.value}`)
210+
: curr.value;
205211
return {
206212
...prev,
207213
...obj,
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { InputBase } from '@/core/models';
1+
import { InputType } from '@/core/models';
22

33
export interface DynamicForm {
44
id: string;
5-
fields: InputBase[];
5+
fields: InputType[];
66
fieldOrder?: string[];
77
}

src/components/dynamic-input/DynamicInput.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
RadioInput,
2222
CheckboxInput,
2323
TextAreaInput,
24+
InputType,
2425
} from '../../core/models';
2526
2627
import { isEmpty, entries, values, keys } from '../../core/utils/helpers';
@@ -38,7 +39,7 @@ const components = {
3839
3940
const props = {
4041
control: {
41-
type: Object as PropType<FormControl>,
42+
type: Object as PropType<FormControl<InputType>>,
4243
required: true,
4344
},
4445
submited: {
@@ -47,7 +48,7 @@ const props = {
4748
},
4849
};
4950
50-
export type ControlAttribute<T> = {
51+
export type ControlAttribute<T extends InputType> = {
5152
control: FormControl<T>;
5253
onChanged: (value: unknown) => void;
5354
};

src/composables/input-events.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@ import { watch } from 'vue';
22

33
export function useInputEvents(props: any, emit: any) {
44
function onChange($event: any): void {
5+
const value =
6+
props.control.type === 'number'
7+
? parseFloat(`${$event.target.value}`)
8+
: $event.target.value;
59
if (props.control) {
6-
props.control.value = $event.target.value;
10+
props.control.value = value;
711
props.control.dirty = true;
812
}
9-
emit('changed', $event.target.value);
13+
emit('changed', value);
1014
}
1115
function onCheck($event: any): void {
1216
if (props.control) {

src/core/models.ts

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,15 @@ type ValidationErrors = {
3636
};
3737

3838
interface ValidatorFn {
39-
(control: FormControl | undefined): ValidationErrors | null;
39+
(control: FormControl<InputType> | undefined): ValidationErrors | null;
4040
}
4141

4242
export interface FormValidation {
4343
validator: ValidatorFn;
4444
text: string;
4545
}
4646

47-
export interface InputBase {
48-
value: boolean | string;
47+
interface InputBase {
4948
name: string;
5049
label: string;
5150
disabled?: boolean;
@@ -55,16 +54,16 @@ export interface InputBase {
5554
}
5655

5756
export type TextInput = InputBase & {
58-
value: string;
5957
type: 'text';
58+
value: string;
6059
};
6160

6261
export type NumberInput = InputBase & {
62+
type: 'number';
63+
value: number;
6364
min?: number;
6465
max?: number;
6566
step?: number;
66-
value: number;
67-
type: 'number';
6867
};
6968

7069
export type SelectInput<T = boolean | string> = InputBase & {
@@ -74,10 +73,10 @@ export type SelectInput<T = boolean | string> = InputBase & {
7473
};
7574

7675
export type TextAreaInput = InputBase & {
77-
cols?: number;
78-
rows?: number;
7976
type: 'textarea';
8077
value: string;
78+
cols?: number;
79+
rows?: number;
8180
};
8281

8382
export type CheckboxInput = InputBase & {
@@ -87,6 +86,7 @@ export type CheckboxInput = InputBase & {
8786

8887
export type CustomInput = InputBase & {
8988
type: 'custom-field';
89+
value: boolean | string;
9090
};
9191

9292
export type EmailInput = InputBase & {
@@ -111,30 +111,11 @@ export type UrlInput = InputBase & {
111111

112112
export type RadioInput = InputBase & {
113113
type: 'radio';
114-
options?: { key: string; value: string; disabled?: boolean }[];
115114
value: string;
116-
};
117-
118-
/* export type UrlInput = InputBase<'url', string>;
119-
120-
export type PasswordInput = InputBase<'password', string>;
121-
122-
export type SelectInput = InputBase<'select'> & {
123115
options?: { key: string; value: string; disabled?: boolean }[];
124116
};
125117

126-
export type TextAreaInput = InputBase<'textarea', string> & {
127-
cols?: number;
128-
rows?: number;
129-
};
130-
131-
export type CheckboxInput = InputBase<'checkbox', string>;
132-
133-
export type RadioInput = InputBase<'radio', string>;
134-
135-
export type ColorInput = InputBase<'color', string>;
136-
*/
137-
export type FormControl<T = InputType> = T & {
118+
export type FormControl<T extends InputType> = T & {
138119
valid: boolean;
139120
invalid: boolean;
140121
dirty: boolean;

src/core/utils/validators.ts

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,67 @@
1-
import { FormControl } from '../models';
1+
import { FormControl, InputType } from '../models';
22

33
export const isEmptyInputValue = (value: any) =>
44
value == null || value === '' || value.length === 0;
55

66
const EMAIL_REGEXP = /^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/;
77
const URL_REGEXP = /^((?:(https?):\/\/)?((?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]|[0-9])\.(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]|[0-9])\.)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]|[0-9])\.)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]|[0-9]))|(?:(?:(?:\w+\.){1,2}[\w]{2,3})))(?::(\d+))?((?:\/[\w]+)*)(?:\/|(\/[\w]+\.[\w]{3,4})|(\?(?:([\w]+=[\w]+)&)*([\w]+=[\w]+))?|\?(?:(wsdl|wadl))))$/;
88

9-
export const required = (control: FormControl<any>) =>
9+
export const required = (control: FormControl<InputType>) =>
1010
isEmptyInputValue(control.value) ? { required: true } : null;
1111

12-
export const min = (min: number) => (control: FormControl<any>) => {
12+
export const min = (min: number) => (control: FormControl<InputType>) => {
1313
if (isEmptyInputValue(control.value) || isEmptyInputValue(min)) {
1414
return null; // don't validate empty values to allow optional controls
1515
}
16-
const value = parseFloat(control.value);
16+
const value = parseFloat(`${control.value}`);
1717

1818
return !isNaN(value) && value < min
1919
? { min: { min, actual: +control.value } }
2020
: null;
2121
};
2222

23-
export const max = (max: number) => (control: FormControl<any>) => {
23+
export const max = (max: number) => (control: FormControl<InputType>) => {
2424
if (isEmptyInputValue(control.value) || isEmptyInputValue(max)) {
2525
return null; // don't validate empty values to allow optional controls
2626
}
27-
const value = parseFloat(control.value);
27+
const value = parseFloat(`${control.value}`);
2828
// Controls with NaN values after parsing should be treated as not having a
2929
// maximum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-max
3030
return !isNaN(value) && value > max
3131
? { max: { max, actual: control.value } }
3232
: null;
3333
};
3434

35-
export const email = (control: FormControl<any>) => {
35+
export const email = (control: FormControl<InputType>) => {
3636
if (isEmptyInputValue(control.value)) {
3737
return null; // don't validate empty values to allow optional controls
3838
}
39-
return EMAIL_REGEXP.test(control.value) ? null : { email: true };
39+
return EMAIL_REGEXP.test(`${control.value}`) ? null : { email: true };
4040
};
4141

42-
export const url = (control: FormControl<any>) => {
42+
export const url = (control: FormControl<InputType>) => {
4343
if (isEmptyInputValue(control.value)) {
4444
return null; // don't validate empty values to allow optional controls
4545
}
46-
return URL_REGEXP.test(control.value) ? null : { email: true };
46+
return URL_REGEXP.test(`${control.value}`) ? null : { email: true };
4747
};
4848

49-
export const minLength = (minLength: number) => (control: FormControl<any>) => {
49+
export const minLength = (minLength: number) => (
50+
control: FormControl<InputType>,
51+
) => {
5052
if (isEmptyInputValue(control.value)) {
5153
return null; // don't validate empty values to allow optional controls
5254
}
53-
const length = control.value ? control.value.length : 0;
55+
const length = control.value ? `${control.value}`.length : 0;
5456
return length < minLength
5557
? { minlength: { requiredLength: minLength, actualLength: length } }
5658
: null;
5759
};
5860

59-
export const maxLength = (maxLength: number) => (control: FormControl<any>) => {
60-
const length = control.value ? control.value.length : 0;
61+
export const maxLength = (maxLength: number) => (
62+
control: FormControl<InputType>,
63+
) => {
64+
const length = control.value ? `${control.value}`.length : 0;
6165
return length > maxLength
6266
? { maxlength: { requiredLength: maxLength, actualLength: length } }
6367
: null;

0 commit comments

Comments
 (0)