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

Commit

Permalink
feat(fields): refactor types and new entity approach for fields
Browse files Browse the repository at this point in the history
  • Loading branch information
alvarosabu committed Oct 2, 2020
1 parent 2169c7c commit f610580
Show file tree
Hide file tree
Showing 11 changed files with 252 additions and 182 deletions.
22 changes: 19 additions & 3 deletions dev/typescript/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,22 @@ export default defineComponent({
setup() {
const title = ref('Vue Dynamic Forms');
const formValues = reactive({});
const form = reactive<any>({
const form = reactive({
id: 'example-form',
fields: [
new TextInput({
fieldOrder: ['name'],
fields: {
name: {
label: 'Name',
type: 'text',
value: 'Alvaro',
} as TextInput,
email: {
label: 'Email',
type: 'email',
} as EmailInput,
},
/* fields: [
new TextInput({
label: 'Name',
value: 'Alvaro',
}),
Expand Down Expand Up @@ -157,12 +169,16 @@ export default defineComponent({
value: '#4DBA87',
}),
],
*/
});
function handleSubmit(values) {
console.log('Values Submitted', values);
}
function valueChanged(values) {
Object.assign(formValues, values);
setTimeout(() => {
form.fields.email.value = 'alvaro.saburido@gmail.com';
}, 2000);
}
function handleError(errors) {
console.error(errors);
Expand Down
4 changes: 2 additions & 2 deletions src/components/checkbox-input/CheckboxInput.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script lang="ts">
import { defineComponent, h, PropType } from 'vue';
import { FormControl } from '../../core/models';
import { FormControl, CheckboxInput } from '../../core/models';
import { useInputEvents } from '../../composables/input-events';
const props = {
control: Object as PropType<FormControl<string>>,
control: Object as PropType<FormControl<CheckboxInput>>,
};
export default defineComponent({
Expand Down
12 changes: 7 additions & 5 deletions src/components/dynamic-form/DynamicForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export default defineComponent({
setup(props, ctx) {
const { options } = inject(dynamicFormsSymbol);
const controls: Ref<FormControl<any>[]> = ref([]);
const controls: Ref<FormControl[]> = ref([]);
const formValues = reactive({});
const submited = ref(false);
Expand Down Expand Up @@ -153,10 +153,12 @@ export default defineComponent({
function mapControls(empty?) {
controls.value =
props.form?.fields?.map((field: InputBase<any>) =>
Object.entries(
props.form?.fields,
).map(([key, field]: [string, InputBase]) =>
empty
? new FormControl({ ...field, value: null })
: new FormControl({ ...field }),
? ({ ...field, name: key, value: null } as FormControl)
: ({ ...field, name: key } as FormControl),
) || [];
}
Expand Down Expand Up @@ -192,7 +194,7 @@ export default defineComponent({
ctx.emit('changed', formValues);
}
watch(props, () => {
watch(props.form.fields, () => {
mapControls();
});
Expand Down
101 changes: 79 additions & 22 deletions src/components/dynamic-input/DynamicInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,56 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
import { defineComponent, PropType, computed, h, inject } from 'vue';
import TextInput from '../text-input/TextInput.vue';
import SelectInput from '../select-input/SelectInput.vue';
import TextAreaInput from '../text-area-input/TextAreaInput.vue';
import CheckboxInput from '../checkbox-input/CheckboxInput.vue';
import RadioInput from '../radio-input/RadioInput.vue';
import NumberInput from '../number-input/NumberInput.vue';
import { FormControl } from '../../core/models';
import TextInputComponent from '../text-input/TextInput.vue';
import SelectInputComponent from '../select-input/SelectInput.vue';
import TextAreaInputComponent from '../text-area-input/TextAreaInput.vue';
import CheckboxInputComponent from '../checkbox-input/CheckboxInput.vue';
import RadioInputComponent from '../radio-input/RadioInput.vue';
import NumberInputComponent from '../number-input/NumberInput.vue';
import {
FormControl,
TextInput,
NumberInput,
EmailInput,
PasswordInput,
UrlInput,
ColorInput,
SelectInput,
RadioInput,
CheckboxInput,
TextAreaInput,
} from '../../core/models';
import { isEmpty, entries, values, keys } from '../../core/utils/helpers';
import { useInputEvents } from '../../composables/input-events';
import { dynamicFormsSymbol } from '../../useApi';
const components = {
TextInput,
SelectInput,
TextAreaInput,
CheckboxInput,
RadioInput,
NumberInput,
TextInputComponent,
SelectInputComponent,
TextAreaInputComponent,
CheckboxInputComponent,
RadioInputComponent,
NumberInputComponent,
};
const props = {
control: {
type: Object as PropType<FormControl<any>>,
type: Object as PropType<FormControl>,
required: true,
},
submited: {
type: Boolean,
required: true,
},
};
export type ControlAttribute<T> = {
control: FormControl<T>;
onChanged: (value: unknown) => void;
};
export default defineComponent({
name: 'asDynamicInput',
components,
Expand All @@ -45,7 +64,7 @@ export default defineComponent({
const attributes = computed(() => {
return {
control: props.control,
control: props?.control,
onChanged: valueChange,
};
});
Expand Down Expand Up @@ -134,26 +153,64 @@ export default defineComponent({
return () => {
switch (props?.control?.type) {
case 'text':
component = h(
TextInputComponent,
attributes.value as ControlAttribute<TextInput>,
);
break;
case 'email':
component = h(
TextInputComponent,
attributes.value as ControlAttribute<EmailInput>,
);
break;
case 'password':
component = h(
TextInputComponent,
attributes.value as ControlAttribute<PasswordInput>,
);
break;
case 'url':
component = h(
TextInputComponent,
attributes.value as ControlAttribute<UrlInput>,
);
break;
case 'color':
component = h(TextInput, attributes.value);
component = h(
TextInputComponent,
attributes.value as ControlAttribute<ColorInput>,
);
break;
case 'number':
component = h(NumberInput, attributes.value);
component = h(
NumberInputComponent,
attributes.value as ControlAttribute<NumberInput>,
);
break;
case 'select':
component = h(SelectInput, attributes.value);
component = h(
SelectInputComponent,
attributes.value as ControlAttribute<SelectInput>,
);
break;
case 'textarea':
component = h(TextAreaInput, attributes.value);
component = h(
TextAreaInputComponent,
attributes.value as ControlAttribute<TextAreaInput>,
);
break;
case 'checkbox':
component = h(CheckboxInput, attributes.value);
component = h(
CheckboxInputComponent,
attributes.value as ControlAttribute<CheckboxInput>,
);
break;
case 'radio':
component = h(RadioInput, attributes.value);
component = h(
RadioInputComponent,
attributes.value as ControlAttribute<RadioInput>,
);
break;
case 'custom-field':
component = h(
Expand Down
4 changes: 2 additions & 2 deletions src/components/number-input/NumberInput.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script lang="ts">
import { defineComponent, h, PropType } from 'vue';
import { FormControl } from '../../core/models';
import { FormControl, NumberInput } from '../../core/models';
import { useInputEvents } from '../../composables/input-events';
const props = {
control: Object as PropType<FormControl<string>>,
control: Object as PropType<FormControl<NumberInput>>,
};
export default defineComponent({
Expand Down
4 changes: 2 additions & 2 deletions src/components/radio-input/RadioInput.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script lang="ts">
import { defineComponent, h, PropType } from 'vue';
import { FormControl } from '../../core/models';
import { FormControl, RadioInput } from '../../core/models';
import { useInputEvents } from '../../composables/input-events';
const props = {
control: Object as PropType<FormControl<string>>,
control: Object as PropType<FormControl<RadioInput>>,
};
export default defineComponent({
Expand Down
4 changes: 2 additions & 2 deletions src/components/select-input/SelectInput.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script lang="ts">
import { defineComponent, h, PropType } from 'vue';
import { FormControl } from '../../core/models';
import { FormControl, SelectInput } from '../../core/models';
import { useInputEvents } from '../../composables/input-events';
const props = {
control: Object as PropType<FormControl<any>>,
control: Object as PropType<FormControl<SelectInput>>,
};
export default defineComponent({
Expand Down
4 changes: 2 additions & 2 deletions src/components/text-area-input/TextAreaInput.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script lang="ts">
import { defineComponent, h, PropType } from 'vue';
import { FormControl } from '../../core/models';
import { FormControl, TextAreaInput } from '../../core/models';
import { useInputEvents } from '../../composables/input-events';
const props = {
control: Object as PropType<FormControl<any>>,
control: Object as PropType<FormControl<TextAreaInput>>,
};
export default defineComponent({
Expand Down
23 changes: 16 additions & 7 deletions src/components/text-input/TextInput.vue
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
<script lang="ts">
import { defineComponent, h, PropType } from 'vue';
import { FormControl } from '../../core/models';
import {
ColorInput,
EmailInput,
FormControl,
PasswordInput,
TextInput,
UrlInput,
} from '../../core/models';
import { useInputEvents } from '../../composables/input-events';
const props = {
control: Object as PropType<FormControl<string>>,
control: Object as PropType<
FormControl<TextInput | EmailInput | PasswordInput | UrlInput | ColorInput>
>,
};
export default defineComponent({
name: 'asTextInput',
props,
setup(props, { emit }) {
const { onChange, onFocus, onBlur } = useInputEvents(props?.control, emit);
const { onChange, onFocus, onBlur } = useInputEvents(props, emit);
return () =>
h('input', {
name: props?.control?.name || '',
type: props?.control?.type,
disabled: props?.control?.disabled,
placeholder: props?.control?.placeholder,
name: props.control.name || '',
type: props.control.type,
disabled: props.control.disabled,
placeholder: props.control.placeholder,
class: ['form-control'],
value: props?.control?.value,
onFocus,
Expand Down
28 changes: 15 additions & 13 deletions src/composables/input-events.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import { FormControl } from '@/core/models';
import { watch } from 'vue';

export function useInputEvents(
control: FormControl<any> | undefined,
emit: any,
) {
export function useInputEvents(props: any, emit: any) {
function onChange($event: any): void {
if (control) {
control.value = $event.target.value;
control.dirty = true;
if (props.control) {
props.control.value = $event.target.value;
props.control.dirty = true;
}
emit('changed', $event.target.value);
}
function onCheck($event: any): void {
if (control) {
control.value = $event.target.checked;
control.dirty = true;
if (props.control) {
props.control.value = $event.target.checked;
props.control.dirty = true;
}
emit('changed', $event.target.checked);
}
Expand All @@ -23,10 +20,15 @@ export function useInputEvents(
}
function onBlur(): void {
emit('blur');
if (control) {
control.touched = true;
if (props.control) {
props.control.touched = true;
}
}

watch(props, (value: any) => {
emit('changed', value.control.value);
});

return {
onFocus,
onChange,
Expand Down
Loading

0 comments on commit f610580

Please sign in to comment.