Skip to content

Commit cbe7d83

Browse files
authored
Merge pull request #163 from silinternational/feature/save-form-data
Save form data to local storage
2 parents 7366012 + 6020382 commit cbe7d83

9 files changed

+99
-8
lines changed

components/custom/Form/Form.svelte

+57-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,65 @@
1+
<script>
2+
import { onMount } from 'svelte'
3+
import generateRandomID from '../../../random'
4+
5+
export let id = generateRandomID('form-')
6+
export let saveToLocalStorage = false
7+
8+
let form = {}
9+
10+
onMount(() => {
11+
saveToLocalStorage && listenForBlurOnForm(form)
12+
})
13+
14+
$: saveToLocalStorage && restoreFormValues(form)
15+
16+
const getValuesFromForm = (form) => Object.fromEntries(new FormData(form))
17+
18+
const storeFormValues = (formId, valuesFromForm) => {
19+
sessionStorage.setItem(formId, JSON.stringify(valuesFromForm))
20+
}
21+
22+
const setValuesOnForm = (form, valuesForForm) => {
23+
Object.entries(valuesForForm).forEach((keyValuePair) => {
24+
const [key, value] = keyValuePair
25+
form[key].value = value
26+
})
27+
}
28+
29+
const restoreFormValues = (form) => {
30+
const sessionStorageKey = form.id
31+
const formValuesJson = sessionStorage.getItem(sessionStorageKey)
32+
if (formValuesJson) {
33+
const valuesForForm = JSON.parse(formValuesJson)
34+
if (valuesForForm) {
35+
setValuesOnForm(form, valuesForForm)
36+
sessionStorage.removeItem(sessionStorageKey)
37+
}
38+
}
39+
}
40+
41+
const onBlur = (value) => {
42+
if (value) {
43+
storeFormValues(form.id, getValuesFromForm(form))
44+
}
45+
}
46+
47+
const listenForBlurOnForm = (form) => {
48+
const inputs = form.querySelectorAll('input, textarea')
49+
inputs.forEach((input) => {
50+
input.addEventListener('blur', function () {
51+
onBlur(this.value)
52+
})
53+
})
54+
}
55+
</script>
56+
157
<style>
258
:global(form > *) {
359
margin-top: 2rem;
460
}
561
</style>
662

7-
<form class="w-100 {$$props.class}" on:submit|preventDefault autocomplete="off">
63+
<form bind:this={form} {id} class="w-100 {$$props.class}" on:submit|preventDefault autocomplete="off">
864
<slot />
965
</form>

components/mdc/TextInput/MoneyInput.svelte

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export let label = ''
99
export let value = ''
1010
export let step = '0.01'
1111
export let placeholder = ''
12+
export let name = ''
1213
export let maxValue = undefined
1314
export let minValue = undefined
1415
export let autofocus = false
@@ -87,10 +88,11 @@ const focus = (node) => autofocus && node.focus()
8788
on:keydown
8889
on:keypress
8990
on:keyup
90-
{required}
91-
{maxlength}
9291
{disabled}
92+
{maxlength}
93+
{name}
9394
{placeholder}
95+
{required}
9496
/>
9597
{#if showErrorIcon}
9698
<span class="mdc-text-field__affix mdc-text-field__affix--suffix">

components/mdc/TextInput/TextArea.svelte

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export let autofocus = false
1414
export let rtl = false
1515
export let required = false
1616
export let description = ''
17+
export let name = ''
1718
1819
const labelID = generateRandomID('textarea-label-')
1920
@@ -86,6 +87,7 @@ label {
8687
aria-describedby="{labelID}-helper-id"
8788
{rows}
8889
maxlength="524288"
90+
{name}
8991
{required}
9092
{placeholder}
9193
bind:value

components/mdc/TextInput/TextField.svelte

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export let disabled = false
1414
export let required = false
1515
export let icon = ''
1616
export let description = ''
17+
export let name = ''
1718
1819
const labelID = generateRandomID('text-label-')
1920
@@ -77,6 +78,7 @@ const focus = (node) => autofocus && node.focus()
7778
on:keydown
7879
on:keypress
7980
on:keyup
81+
{name}
8082
{required}
8183
{disabled}
8284
maxlength="524288"

index.d.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ declare module '@silintl/ui-components' {
167167
interface MoneyInputProps extends svelte.JSX.HTMLAttributes<HTMLElementTagNameMap['div']> {
168168
label?: string
169169
value?: number
170+
name?: string
170171
placeholder?: string
171172
autofocus?: boolean
172173
disabled?: boolean
@@ -228,6 +229,7 @@ declare module '@silintl/ui-components' {
228229
interface TextAreaProps extends svelte.JSX.HTMLAttributes<HTMLElementTagNameMap['div']> {
229230
label?: string
230231
value?: string
232+
name?: string
231233
placeholder?: string
232234
rows?: number | string
233235
required?: boolean
@@ -241,6 +243,7 @@ declare module '@silintl/ui-components' {
241243
interface TextFieldProps extends svelte.JSX.HTMLAttributes<HTMLElementTagNameMap['div']> {
242244
label?: string
243245
value?: string
246+
name?: string
244247
placeholder?: string
245248
maxlength?: number
246249
autofocus?: boolean
@@ -300,7 +303,8 @@ declare module '@silintl/ui-components' {
300303
export class FileDropArea extends SvelteComponentTyped<FileDropAreaProps> {}
301304

302305
interface FormProps extends svelte.JSX.HTMLAttributes<HTMLElementTagNameMap['div']> {
303-
// no exported members
306+
id?: string
307+
saveToLocalStorage?: boolean
304308
}
305309
export class Form extends SvelteComponentTyped<FormProps> {}
306310

stories/Form.stories.svelte

+21-4
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,37 @@
11
<script>
22
import { Meta, Template, Story } from '@storybook/addon-svelte-csf'
3-
import { TextField } from '../components/mdc'
3+
import { TextField, MoneyInput, TextArea, Button } from '../components/mdc'
44
import { Form } from '../components/custom'
5+
import { copyAndModifyArgs } from './helpers'
56
67
const args = {
78
class: '', //only works for global classes
8-
onSubmit: () => {},
9+
id: '',
10+
saveToLocalStorage: false,
11+
'on:submit': function () {
12+
sessionStorage.removeItem(this.id)
13+
alert('submitted, reloading page')
14+
location.reload()
15+
},
916
}
1017
</script>
1118

1219
<Meta title="Molecule/Form" component={Form} />
1320

1421
<Template let:args>
15-
<Form on:submit={args.onSubmit} {...args}>
16-
<TextField />
22+
<Form on:submit={args['on:submit']} {...args}>
23+
<TextField label='first' name='first'/>
24+
25+
<TextArea label='second' name='second' rows={4}/>
26+
27+
<MoneyInput label='third' name='third' />
28+
29+
<Button raised>Submit</Button>
1730
</Form>
1831
</Template>
1932

2033
<Story name="Default" {args} />
34+
35+
<Story name="Id" args={copyAndModifyArgs(args, { id: '123' })} />
36+
37+
<Story name="Save To Local Storage" args={copyAndModifyArgs(args, { saveToLocalStorage: true })} />

stories/MoneyInput.stories.svelte

+3
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,6 @@ function setValues(max, step) {
8383
<Story name="Description" args={copyAndModifyArgs(args, { description: 'a description' })} />
8484

8585
<Story name="Test step" args={{ ...args, label: '' }} />
86+
87+
<Story name="Name" args={copyAndModifyArgs(args, { name: 'money' })} />
88+

stories/TextArea.stories.svelte

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ let title = 'TextArea'
77
88
const args = {
99
label: title,
10+
name: '',
1011
row: 8,
1112
class: '', //only works for global classes
1213
}
@@ -35,3 +36,5 @@ const args = {
3536
<Story name="Required" args={copyAndModifyArgs(args, { required: true })} />
3637

3738
<Story name="Description" args={copyAndModifyArgs(args, { description: 'a description' })} />
39+
40+
<Story name="Name" args={copyAndModifyArgs(args, { name: 'area' })} />

stories/TextField.stories.svelte

+2
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,5 @@ let lastKey = ''
3939
<Story name="Required" args={copyAndModifyArgs(args, { required: true })} />
4040

4141
<Story name="Description" args={copyAndModifyArgs(args, { description: 'a description' })} />
42+
43+
<Story name="Name" args={copyAndModifyArgs(args, { name: 'field' })} />

0 commit comments

Comments
 (0)