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

Commit f610580

Browse files
committed
feat(fields): refactor types and new entity approach for fields
1 parent 2169c7c commit f610580

File tree

11 files changed

+252
-182
lines changed

11 files changed

+252
-182
lines changed

dev/typescript/App.vue

+19-3
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,22 @@ export default defineComponent({
6767
setup() {
6868
const title = ref('Vue Dynamic Forms');
6969
const formValues = reactive({});
70-
const form = reactive<any>({
70+
const form = reactive({
7171
id: 'example-form',
72-
fields: [
73-
new TextInput({
72+
fieldOrder: ['name'],
73+
fields: {
74+
name: {
75+
label: 'Name',
76+
type: 'text',
77+
value: 'Alvaro',
78+
} as TextInput,
79+
email: {
80+
label: 'Email',
81+
type: 'email',
82+
} as EmailInput,
83+
},
84+
/* fields: [
85+
new TextInput({
7486
label: 'Name',
7587
value: 'Alvaro',
7688
}),
@@ -157,12 +169,16 @@ export default defineComponent({
157169
value: '#4DBA87',
158170
}),
159171
],
172+
*/
160173
});
161174
function handleSubmit(values) {
162175
console.log('Values Submitted', values);
163176
}
164177
function valueChanged(values) {
165178
Object.assign(formValues, values);
179+
setTimeout(() => {
180+
form.fields.email.value = '[email protected]';
181+
}, 2000);
166182
}
167183
function handleError(errors) {
168184
console.error(errors);

src/components/checkbox-input/CheckboxInput.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<script lang="ts">
22
import { defineComponent, h, PropType } from 'vue';
3-
import { FormControl } from '../../core/models';
3+
import { FormControl, CheckboxInput } from '../../core/models';
44
import { useInputEvents } from '../../composables/input-events';
55
66
const props = {
7-
control: Object as PropType<FormControl<string>>,
7+
control: Object as PropType<FormControl<CheckboxInput>>,
88
};
99
1010
export default defineComponent({

src/components/dynamic-form/DynamicForm.vue

+7-5
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export default defineComponent({
7373
setup(props, ctx) {
7474
const { options } = inject(dynamicFormsSymbol);
7575
76-
const controls: Ref<FormControl<any>[]> = ref([]);
76+
const controls: Ref<FormControl[]> = ref([]);
7777
const formValues = reactive({});
7878
const submited = ref(false);
7979
@@ -153,10 +153,12 @@ export default defineComponent({
153153
154154
function mapControls(empty?) {
155155
controls.value =
156-
props.form?.fields?.map((field: InputBase<any>) =>
156+
Object.entries(
157+
props.form?.fields,
158+
).map(([key, field]: [string, InputBase]) =>
157159
empty
158-
? new FormControl({ ...field, value: null })
159-
: new FormControl({ ...field }),
160+
? ({ ...field, name: key, value: null } as FormControl)
161+
: ({ ...field, name: key } as FormControl),
160162
) || [];
161163
}
162164
@@ -192,7 +194,7 @@ export default defineComponent({
192194
ctx.emit('changed', formValues);
193195
}
194196
195-
watch(props, () => {
197+
watch(props.form.fields, () => {
196198
mapControls();
197199
});
198200

src/components/dynamic-input/DynamicInput.vue

+79-22
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,56 @@
22
/* eslint-disable @typescript-eslint/no-use-before-define */
33
44
import { defineComponent, PropType, computed, h, inject } from 'vue';
5-
import TextInput from '../text-input/TextInput.vue';
6-
import SelectInput from '../select-input/SelectInput.vue';
7-
import TextAreaInput from '../text-area-input/TextAreaInput.vue';
8-
import CheckboxInput from '../checkbox-input/CheckboxInput.vue';
9-
import RadioInput from '../radio-input/RadioInput.vue';
10-
import NumberInput from '../number-input/NumberInput.vue';
11-
12-
import { FormControl } from '../../core/models';
5+
import TextInputComponent from '../text-input/TextInput.vue';
6+
import SelectInputComponent from '../select-input/SelectInput.vue';
7+
import TextAreaInputComponent from '../text-area-input/TextAreaInput.vue';
8+
import CheckboxInputComponent from '../checkbox-input/CheckboxInput.vue';
9+
import RadioInputComponent from '../radio-input/RadioInput.vue';
10+
import NumberInputComponent from '../number-input/NumberInput.vue';
11+
12+
import {
13+
FormControl,
14+
TextInput,
15+
NumberInput,
16+
EmailInput,
17+
PasswordInput,
18+
UrlInput,
19+
ColorInput,
20+
SelectInput,
21+
RadioInput,
22+
CheckboxInput,
23+
TextAreaInput,
24+
} from '../../core/models';
25+
1326
import { isEmpty, entries, values, keys } from '../../core/utils/helpers';
1427
import { useInputEvents } from '../../composables/input-events';
1528
import { dynamicFormsSymbol } from '../../useApi';
1629
1730
const components = {
18-
TextInput,
19-
SelectInput,
20-
TextAreaInput,
21-
CheckboxInput,
22-
RadioInput,
23-
NumberInput,
31+
TextInputComponent,
32+
SelectInputComponent,
33+
TextAreaInputComponent,
34+
CheckboxInputComponent,
35+
RadioInputComponent,
36+
NumberInputComponent,
2437
};
2538
2639
const props = {
2740
control: {
28-
type: Object as PropType<FormControl<any>>,
41+
type: Object as PropType<FormControl>,
2942
required: true,
3043
},
3144
submited: {
3245
type: Boolean,
3346
required: true,
3447
},
3548
};
49+
50+
export type ControlAttribute<T> = {
51+
control: FormControl<T>;
52+
onChanged: (value: unknown) => void;
53+
};
54+
3655
export default defineComponent({
3756
name: 'asDynamicInput',
3857
components,
@@ -45,7 +64,7 @@ export default defineComponent({
4564
4665
const attributes = computed(() => {
4766
return {
48-
control: props.control,
67+
control: props?.control,
4968
onChanged: valueChange,
5069
};
5170
});
@@ -134,26 +153,64 @@ export default defineComponent({
134153
return () => {
135154
switch (props?.control?.type) {
136155
case 'text':
156+
component = h(
157+
TextInputComponent,
158+
attributes.value as ControlAttribute<TextInput>,
159+
);
160+
break;
137161
case 'email':
162+
component = h(
163+
TextInputComponent,
164+
attributes.value as ControlAttribute<EmailInput>,
165+
);
166+
break;
138167
case 'password':
168+
component = h(
169+
TextInputComponent,
170+
attributes.value as ControlAttribute<PasswordInput>,
171+
);
172+
break;
139173
case 'url':
174+
component = h(
175+
TextInputComponent,
176+
attributes.value as ControlAttribute<UrlInput>,
177+
);
178+
break;
140179
case 'color':
141-
component = h(TextInput, attributes.value);
180+
component = h(
181+
TextInputComponent,
182+
attributes.value as ControlAttribute<ColorInput>,
183+
);
142184
break;
143185
case 'number':
144-
component = h(NumberInput, attributes.value);
186+
component = h(
187+
NumberInputComponent,
188+
attributes.value as ControlAttribute<NumberInput>,
189+
);
145190
break;
146191
case 'select':
147-
component = h(SelectInput, attributes.value);
192+
component = h(
193+
SelectInputComponent,
194+
attributes.value as ControlAttribute<SelectInput>,
195+
);
148196
break;
149197
case 'textarea':
150-
component = h(TextAreaInput, attributes.value);
198+
component = h(
199+
TextAreaInputComponent,
200+
attributes.value as ControlAttribute<TextAreaInput>,
201+
);
151202
break;
152203
case 'checkbox':
153-
component = h(CheckboxInput, attributes.value);
204+
component = h(
205+
CheckboxInputComponent,
206+
attributes.value as ControlAttribute<CheckboxInput>,
207+
);
154208
break;
155209
case 'radio':
156-
component = h(RadioInput, attributes.value);
210+
component = h(
211+
RadioInputComponent,
212+
attributes.value as ControlAttribute<RadioInput>,
213+
);
157214
break;
158215
case 'custom-field':
159216
component = h(

src/components/number-input/NumberInput.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<script lang="ts">
22
import { defineComponent, h, PropType } from 'vue';
3-
import { FormControl } from '../../core/models';
3+
import { FormControl, NumberInput } from '../../core/models';
44
import { useInputEvents } from '../../composables/input-events';
55
66
const props = {
7-
control: Object as PropType<FormControl<string>>,
7+
control: Object as PropType<FormControl<NumberInput>>,
88
};
99
1010
export default defineComponent({

src/components/radio-input/RadioInput.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<script lang="ts">
22
import { defineComponent, h, PropType } from 'vue';
3-
import { FormControl } from '../../core/models';
3+
import { FormControl, RadioInput } from '../../core/models';
44
import { useInputEvents } from '../../composables/input-events';
55
66
const props = {
7-
control: Object as PropType<FormControl<string>>,
7+
control: Object as PropType<FormControl<RadioInput>>,
88
};
99
1010
export default defineComponent({

src/components/select-input/SelectInput.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<script lang="ts">
22
import { defineComponent, h, PropType } from 'vue';
3-
import { FormControl } from '../../core/models';
3+
import { FormControl, SelectInput } from '../../core/models';
44
import { useInputEvents } from '../../composables/input-events';
55
66
const props = {
7-
control: Object as PropType<FormControl<any>>,
7+
control: Object as PropType<FormControl<SelectInput>>,
88
};
99
1010
export default defineComponent({

src/components/text-area-input/TextAreaInput.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<script lang="ts">
22
import { defineComponent, h, PropType } from 'vue';
3-
import { FormControl } from '../../core/models';
3+
import { FormControl, TextAreaInput } from '../../core/models';
44
import { useInputEvents } from '../../composables/input-events';
55
const props = {
6-
control: Object as PropType<FormControl<any>>,
6+
control: Object as PropType<FormControl<TextAreaInput>>,
77
};
88
99
export default defineComponent({

src/components/text-input/TextInput.vue

+16-7
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,33 @@
11
<script lang="ts">
22
import { defineComponent, h, PropType } from 'vue';
3-
import { FormControl } from '../../core/models';
3+
import {
4+
ColorInput,
5+
EmailInput,
6+
FormControl,
7+
PasswordInput,
8+
TextInput,
9+
UrlInput,
10+
} from '../../core/models';
411
import { useInputEvents } from '../../composables/input-events';
512
613
const props = {
7-
control: Object as PropType<FormControl<string>>,
14+
control: Object as PropType<
15+
FormControl<TextInput | EmailInput | PasswordInput | UrlInput | ColorInput>
16+
>,
817
};
918
1019
export default defineComponent({
1120
name: 'asTextInput',
1221
props,
1322
setup(props, { emit }) {
14-
const { onChange, onFocus, onBlur } = useInputEvents(props?.control, emit);
23+
const { onChange, onFocus, onBlur } = useInputEvents(props, emit);
1524
1625
return () =>
1726
h('input', {
18-
name: props?.control?.name || '',
19-
type: props?.control?.type,
20-
disabled: props?.control?.disabled,
21-
placeholder: props?.control?.placeholder,
27+
name: props.control.name || '',
28+
type: props.control.type,
29+
disabled: props.control.disabled,
30+
placeholder: props.control.placeholder,
2231
class: ['form-control'],
2332
value: props?.control?.value,
2433
onFocus,

src/composables/input-events.ts

+15-13
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1-
import { FormControl } from '@/core/models';
1+
import { watch } from 'vue';
22

3-
export function useInputEvents(
4-
control: FormControl<any> | undefined,
5-
emit: any,
6-
) {
3+
export function useInputEvents(props: any, emit: any) {
74
function onChange($event: any): void {
8-
if (control) {
9-
control.value = $event.target.value;
10-
control.dirty = true;
5+
if (props.control) {
6+
props.control.value = $event.target.value;
7+
props.control.dirty = true;
118
}
129
emit('changed', $event.target.value);
1310
}
1411
function onCheck($event: any): void {
15-
if (control) {
16-
control.value = $event.target.checked;
17-
control.dirty = true;
12+
if (props.control) {
13+
props.control.value = $event.target.checked;
14+
props.control.dirty = true;
1815
}
1916
emit('changed', $event.target.checked);
2017
}
@@ -23,10 +20,15 @@ export function useInputEvents(
2320
}
2421
function onBlur(): void {
2522
emit('blur');
26-
if (control) {
27-
control.touched = true;
23+
if (props.control) {
24+
props.control.touched = true;
2825
}
2926
}
27+
28+
watch(props, (value: any) => {
29+
emit('changed', value.control.value);
30+
});
31+
3032
return {
3133
onFocus,
3234
onChange,

0 commit comments

Comments
 (0)