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

Commit 196c7d3

Browse files
authored
Merge pull request #231 from asigloo/feature/230-form-reset-after-submission-should-b
Feature/230 form reset after submission should b
2 parents 9742982 + 5e8211d commit 196c7d3

File tree

10 files changed

+174
-14
lines changed

10 files changed

+174
-14
lines changed

demos/vue-3/src/router/index.ts

+11
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,17 @@ const routes: Array<RouteRecordRaw> = [
103103
/* webpackChunkName: "toggle-visibility" */ '../views/ToggleVisibility.vue'
104104
),
105105
},
106+
{
107+
path: '/reset-after-submit',
108+
name: 'Reset after submit',
109+
meta: {
110+
title: 'Reset after submit',
111+
},
112+
component: () =>
113+
import(
114+
/* webpackChunkName: "reset-after-submit" */ '../views/ResetAfterSubmit.vue'
115+
),
116+
},
106117
];
107118

108119
const router = createRouter({

demos/vue-3/src/views/Home.vue

+10
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ export default defineComponent({
5959
route: '/general',
6060
tags: ['all'],
6161
},
62+
{
63+
name: 'Basic',
64+
route: '/basic',
65+
tags: ['text-field', 'select-field', 'checkbox-field'],
66+
},
6267
{
6368
name: 'Text Fields',
6469
route: '/text-fields',
@@ -104,6 +109,11 @@ export default defineComponent({
104109
route: '/toggle-visibility',
105110
tags: ['visibility', 'custom-class', 'custom-styles'],
106111
},
112+
{
113+
name: 'Reset after Submit',
114+
route: '/reset-after-submit',
115+
tags: ['submit', 'reset-forms'],
116+
},
107117
],
108118
];
109119
}, 1000);
+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<template>
2+
<div class="page container">
3+
<div class="mx-auto w-full sm:w-1/2 relative mb-24">
4+
<div
5+
class="absolute inset-0 bg-gradient-to-r from-blue-400 to-green-200 shadow-xl transform -skew-y-3 sm:skew-y-0 sm:-rotate-3 sm:rounded-3xl"
6+
></div>
7+
<div class="relative card p-6 bg-white">
8+
<dynamic-form
9+
:form="form"
10+
@submitted="handleSubmit"
11+
@change="valueChanged"
12+
@error="handleError"
13+
/>
14+
<button
15+
data-cy="submit"
16+
class="btn bg-green-500 text-white hover:bg-green-700 mt-4"
17+
submit="true"
18+
:form="form?.id"
19+
>
20+
Try me
21+
</button>
22+
</div>
23+
</div>
24+
<div class="mx-auto w-full sm:w-1/2"><Console :content="formValues" /></div>
25+
</div>
26+
</template>
27+
28+
<script lang="ts">
29+
import { CheckboxField, TextField } from '@/';
30+
import { computed, defineComponent, reactive } from 'vue';
31+
import Console from '../components/Console.vue';
32+
33+
const components = {
34+
Console,
35+
};
36+
/* } from '../../dist/as-dynamic-forms.esm'; */
37+
export default defineComponent({
38+
name: 'ResetAfterSubmit',
39+
components,
40+
setup() {
41+
const formValues = reactive({
42+
resetAfterSubmit: false,
43+
});
44+
45+
const form = computed(() => ({
46+
id: 'basic-demo',
47+
fields: {
48+
resetAfterSubmit: CheckboxField({
49+
label: 'Toggle option resetAfterSubmit',
50+
}),
51+
name: TextField({
52+
label: 'Just a prefilled name',
53+
value: 'Awiwiwi',
54+
}),
55+
},
56+
options: {
57+
resetAfterSubmit: formValues.resetAfterSubmit,
58+
},
59+
}));
60+
61+
function handleSubmit(values) {
62+
console.log('Values Submitted', values);
63+
}
64+
65+
function valueChanged(values) {
66+
Object.assign(formValues, values);
67+
console.log('Values', values);
68+
}
69+
70+
function handleError(errors) {
71+
console.error('Errors', errors);
72+
}
73+
74+
return {
75+
form,
76+
formValues,
77+
handleSubmit,
78+
valueChanged,
79+
handleError,
80+
};
81+
},
82+
});
83+
</script>
84+
<style lang="scss"></style>

package-lock.json

+7-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"@vue/compiler-sfc": "3.0.2",
4747
"@vue/eslint-config-prettier": "^6.0.0",
4848
"@vue/eslint-config-typescript": "^7.0.0",
49-
"@vue/test-utils": "^2.0.0-beta.14",
49+
"@vue/test-utils": "^2.0.0-rc.0",
5050
"babel-core": "7.0.0-bridge.0",
5151
"babel-eslint": "10.1.0",
5252
"babel-jest": "26.6.3",
@@ -77,7 +77,7 @@
7777
"typescript": "~4.1.2",
7878
"vue": "^3.0.0",
7979
"vue-cli-plugin-cypress-experimental": "~1.2.0",
80-
"vue-jest": "^5.0.0-alpha.7",
80+
"vue-jest": "^5.0.0-alpha.8",
8181
"vue-router": "^4.0.1",
8282
"vue-select": "3.10.8"
8383
},

src/components/dynamic-form/DynamicForm.vue

+11
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ export default defineComponent({
7777
onValidate,
7878
forceValidation,
7979
detectChanges,
80+
onOptionsChanged,
8081
} = useDynamicForm(props.form as DynamicForm, ctx, options);
8182
8283
watch(
@@ -88,6 +89,16 @@ export default defineComponent({
8889
deep: true,
8990
},
9091
);
92+
93+
watch(
94+
() => props.form.options,
95+
options => {
96+
onOptionsChanged(options);
97+
},
98+
{
99+
deep: true,
100+
},
101+
);
91102
return {
92103
controls,
93104
valueChange,

src/composables/useDynamicForm.spec.ts

+11
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,17 @@ describe('UseDynamicForm', () => {
188188
rememberMe: true,
189189
});
190190
});
191+
// TODO: check this after on how to spy on functions inside functions
192+
/*
193+
it('should reset form after valid form submission', async () => {
194+
const { mapControls, handleSubmit, resetForm } = useDynamicForm(form, ctx);
195+
const spy = jest.spyOn({ resetForm }, 'resetForm');
196+
mapControls();
197+
198+
await handleSubmit();
199+
200+
expect(spy).toHaveBeenCalled();
201+
}); */
191202

192203
it('should emit error event with errors if hadleSubmit is called and is form is invalid ', async () => {
193204
const spy = jest.spyOn(ctx, 'emit');

src/composables/useDynamicForm.ts

+18-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
InputEvent,
99
DynamicForm,
1010
FormFields,
11+
FormOptions,
1112
} from '@/core/models';
1213
import {
1314
computed,
@@ -27,6 +28,7 @@ interface DynamicFormComposition {
2728
controls: Ref<FormControl<InputType>[]>;
2829
forceValidation: Ref<boolean>;
2930
formValues: ComputedRef<(string | { [key: string]: boolean })[]>;
31+
formOptions: Ref<FormOptions>;
3032
errors: ComputedRef<Record<string, unknown>>;
3133
isValid: ComputedRef<boolean>;
3234
normalizedControls: ComputedRef<Record<string, unknown>>;
@@ -42,6 +44,7 @@ interface DynamicFormComposition {
4244
findControlByName: (name: string | unknown) => FormControl<InputType>;
4345
resetForm: () => void;
4446
detectChanges: (fields: FormFields) => void;
47+
onOptionsChanged: (options: FormOptions) => void;
4548
}
4649

4750
export function useDynamicForm(
@@ -56,6 +59,11 @@ export function useDynamicForm(
5659
let cache = deepClone(toRaw(form.fields));
5760

5861
const controls: Ref<FormControl<InputType>[]> = ref([]);
62+
const formOptions: Ref<FormOptions> = ref({
63+
resetAfterSubmit: true,
64+
...options?.form,
65+
...form?.options,
66+
});
5967
const forceValidation = ref(false);
6068

6169
const deNormalizedScopedSlots = computed(() => Object.keys(ctx.slots));
@@ -107,10 +115,7 @@ export function useDynamicForm(
107115
});
108116

109117
const formattedOptions = computed(() => {
110-
const opts = {
111-
...options?.form,
112-
...form?.options,
113-
};
118+
const opts = formOptions.value;
114119

115120
if (opts) {
116121
const {
@@ -220,6 +225,10 @@ export function useDynamicForm(
220225
cache = deepClone(toRaw(fields));
221226
}
222227

228+
function onOptionsChanged(changes) {
229+
Object.assign(formOptions.value, changes);
230+
}
231+
223232
function resetForm() {
224233
mapControls(true);
225234
forceValidation.value = false;
@@ -232,7 +241,9 @@ export function useDynamicForm(
232241

233242
if (isValid.value) {
234243
ctx.emit('submitted', formValues.value);
235-
resetForm();
244+
if (formOptions.value.resetAfterSubmit) {
245+
resetForm();
246+
}
236247
} else {
237248
ctx.emit('error', errors.value);
238249
}
@@ -251,6 +262,7 @@ export function useDynamicForm(
251262
mapControls,
252263
valueChange,
253264
formValues,
265+
formOptions,
254266
handleSubmit,
255267
isValid,
256268
errors,
@@ -264,5 +276,6 @@ export function useDynamicForm(
264276
findControlByName,
265277
resetForm,
266278
detectChanges,
279+
onOptionsChanged,
267280
};
268281
}

src/core/models.ts

+1
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ export interface FormOptions {
167167
netlify?: boolean;
168168
netlifyHoneypot?: string;
169169
autocomplete?: boolean | string;
170+
resetAfterSubmit?: boolean;
170171
}
171172

172173
export enum FieldTypes {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
describe('Reset after submission', () => {
2+
beforeEach(() => {
3+
cy.visit('/reset-after-submit'); // "baseUrl" is defined in cypress.json file
4+
});
5+
6+
context('Basic Events', () => {
7+
it('should reset the form if resetAfterSubmit is checked', () => {
8+
cy.get('input[name="resetAfterSubmit"]').check();
9+
cy.get('[data-cy=submit]').click();
10+
cy.get('input[name="name"]').should('not.have.value', null);
11+
});
12+
13+
it('should reset the form if resetAfterSubmit is unchecked', () => {
14+
cy.get('input[name="resetAfterSubmit"]').uncheck();
15+
cy.get('[data-cy=submit]').click();
16+
cy.get('input[name="name"]').should('have.value', 'Awiwiwi');
17+
});
18+
});
19+
});

0 commit comments

Comments
 (0)