- commit
- cea4f35
- parent
- e42f365
- author
- CheddarCrisp
- date
- 2020-03-05 02:53:18 +0100 CET
Add validation to forms Fix values being treated as strings
3 files changed,
+64,
-38
+18,
-12
1@@ -11,14 +11,16 @@
2 </div>
3 {#if showAddDialog}
4 <div class="dialog">
5- <div class="dialog-content">
6- <label>Name<input type="text" bind:value={newCounter.title} use:focus/></label>
7- <label>Initial Value<input type="text" inputmode="decimal" bind:value={newCounter.initialValue} /></label>
8- <label>Target<input type="text" inputmode="decimal" bind:value={newCounter.max} /></label>
9+ <form class="dialog-content" novalidate bind:this={ dialogForm }>
10+ <label>Counter Name<input type="text" required bind:value={newCounter.title} use:focus/></label>
11+ <label>Initial Value<input type="text" required pattern="(0|([1-9]\d*))(\.\d+)?" inputmode="decimal" bind:value={newCounter.initialValue} /></label>
12+ <label>Target<input type="text" pattern="(0|([1-9]\d*))(\.\d+)?" inputmode="decimal" bind:value={newCounter.max} /></label>
13 <label>Save history<input type="checkbox" bind:checked={newCounter.saveHistory} /></label>
14- <button on:click={ () => { showAddDialog = false; } }>Cancel</button>
15- <button class="ok" on:click={ add }>OK</button>
16- </div>
17+ <div class="buttons">
18+ <button class="ok" on:click|preventDefault={ add }>OK</button>
19+ <button on:click|preventDefault={ () => { showAddDialog = false; } }>Cancel</button>
20+ </div>
21+ </form>
22 </div>
23 {/if}
24 {#if showAbout}
25@@ -32,6 +34,7 @@ import { counters } from './db.js';
26 let showAddDialog = false;
27 let showAbout = false;
28 let newCounter = null;
29+let dialogForm = null;
30
31 function focus(node){
32 node.focus();
33@@ -41,6 +44,7 @@ function showAdd(){
34 newCounter = {
35 title: '',
36 initialValue: 0,
37+ max: '',
38 saveHistory: false,
39 history: []
40 }
41@@ -49,9 +53,15 @@ function showAdd(){
42 }
43
44 function add(){
45+ if(!dialogForm.checkValidity()) {
46+ dialogForm.removeAttribute('novalidate');
47+ return;
48+ }
49+
50 const counter = {
51 ...newCounter,
52- value: newCounter.initialValue
53+ max: newCounter.max !== '' ? +newCounter.max : null,
54+ value: +newCounter.initialValue
55 }
56
57 counters.add(counter);
58@@ -60,10 +70,6 @@ function add(){
59 }
60 </script>
61 <style lang="scss">
62- .ok {
63- margin-left: auto;
64- }
65-
66 .app {
67 display: flex;
68 flex-direction: column;
+39,
-26
1@@ -1,7 +1,7 @@
2 <div class="counter">
3 <header>{ counter.title }</header>
4 <span class="value">{ counter.value }</span>
5- {#if counter.max}
6+ {#if counter.max !== null}
7 <MyProgress value={ counter.value } max={ counter.max }></MyProgress>
8 {/if}
9 <div class="controls">
10@@ -16,24 +16,28 @@
11 </div>
12 {#if showValueDialog}
13 <div class="dialog">
14- <div class="dialog-content">
15+ <form class="dialog-content" novalidate bind:this={ dialogForm }>
16 <h1>{ showIncrement ? "Add" : "Set" }</h1>
17- <input class="dialog-value" type="text" inputmode="decimal" bind:value={ dialogValue } use:focus />
18- <button on:click={ dialogCancel }>Cancel</button>
19- <button class="ok" on:click={ dialogDone }>OK</button>
20- </div>
21+ <input class="dialog-value" type="text" required pattern="(0|([1-9]\d*))(\.\d+)?" inputmode="decimal" bind:value={ dialogValue } use:focus />
22+ <div class="buttons">
23+ <button class="ok" on:click|preventDefault={ dialogDone }>OK</button>
24+ <button on:click|preventDefault={ dialogCancel }>Cancel</button>
25+ </div>
26+ </form>
27 </div>
28 {/if}
29 {#if showEditDialog}
30 <div class="dialog">
31- <div class="dialog-content">
32- <label>Name<input type="text" bind:value={editingCounter.title} use:focus/></label>
33- <label>Initial Value<input type="text" inputmode="decimal" bind:value={editingCounter.initialValue} /></label>
34- <label>Target<input type="text" inputmode="decimal" bind:value={editingCounter.max} /></label>
35+ <form class="dialog-content" novalidate bind:this={ dialogForm }>
36+ <label>Name<input type="text" required bind:value={editingCounter.title} use:focus/></label>
37+ <label>Initial Value<input type="text" required pattern="(0|([1-9]\d*))(\.\d+)?" inputmode="decimal" bind:value={editingCounter.initialValue} /></label>
38+ <label>Target<input type="text" pattern="(0|([1-9]\d*))(\.\d+)?" inputmode="decimal" bind:value={editingCounter.max} /></label>
39 <label>Save history<input type="checkbox" bind:checked={editingCounter.saveHistory} /></label>
40- <button on:click={ () => { showEditDialog = false; } }>Cancel</button>
41- <button class="ok" on:click={ finishEdit }>OK</button>
42- </div>
43+ <div class="buttons">
44+ <button class="ok" on:click|preventDefault={ finishEdit }>OK</button>
45+ <button on:click|preventDefault={ () => { showEditDialog = false; } }>Cancel</button>
46+ </div>
47+ </form>
48 </div>
49 {/if}
50 {#if showHistory}
51@@ -56,6 +60,7 @@ let showSet;
52 let showEditDialog;
53 let editingCounter;
54 let showHistory;
55+let dialogForm;
56
57 $: showValueDialog = showIncrement || showSet;
58
59@@ -68,14 +73,23 @@ function update(newCounter){
60 }
61
62 function startEdit(e){
63- e.stopPropagation();
64-
65- editingCounter = {...counter};
66+ editingCounter = { ...counter };
67 showEditDialog = true;
68 }
69
70 function finishEdit(){
71- update(editingCounter);
72+ if(!dialogForm.checkValidity()) {
73+ dialogForm.removeAttribute('novalidate');
74+ return;
75+ }
76+
77+ const updatedCounter = {
78+ ...editingCounter,
79+ max: editingCounter.max !== null && editingCounter.max !== '' ? +editingCounter.max : null,
80+ value: +editingCounter.value
81+ }
82+
83+ update(updatedCounter);
84 showEditDialog = false;
85 }
86
87@@ -85,12 +99,17 @@ function dialogCancel(){
88 }
89
90 function dialogDone(){
91+ if(!dialogForm.checkValidity()) {
92+ dialogForm.removeAttribute('novalidate');
93+ return;
94+ }
95+
96 const newCounter = showIncrement ? {
97 ...counter,
98- value: counter.value + dialogValue
99+ value: +counter.value + +dialogValue
100 } : {
101 ...counter,
102- value: dialogValue
103+ value: +dialogValue
104 }
105
106 update(newCounter);
107@@ -101,12 +120,10 @@ function dialogDone(){
108 }
109
110 function reset(e){
111- e.stopPropagation();
112-
113 if(confirm(`Reset ${counter.title}?`)){
114 const newCounter = {
115 ...counter,
116- value: counter.initialValue
117+ value: +counter.initialValue
118 }
119
120 update(newCounter);
121@@ -166,8 +183,4 @@ header {
122 width: 100%;
123 margin: 5px 0;
124 }
125-
126-.ok {
127- margin-left: auto;
128-}
129 </style>
+7,
-0
1@@ -125,6 +125,13 @@ button:focus, button:hover {
2 width: auto;
3 }
4
5+.dialog-content .buttons {
6+ display: flex;
7+ flex-direction: row-reverse;
8+ justify-content: space-between;
9+ width: 100%;
10+}
11+
12 .dialog-content button:focus, .dialog-content button:hover {
13 border: 0;
14 outline: 2px solid var(--button-color);