|
9 | 9 | summaryError = $state(),
|
10 | 10 | descriptionError = $state(false);
|
11 | 11 |
|
| 12 | + const id = $props.id(); |
| 13 | + const form = `form#${id}`; |
| 14 | +
|
12 | 15 | //takes long string output of document.cookie and splits it into a usable javascript object
|
13 | 16 | let cookies = document.cookie
|
14 | 17 | .split(';')
|
|
26 | 29 |
|
27 | 30 | /**
|
28 | 31 | * @typedef {Object} Props
|
29 |
| - * @property {any} [id] |
30 |
| - * @property {any} [form] |
31 | 32 | * @property {any} postResponseStatusCode
|
32 | 33 | * @property {boolean} [loading] - when true, spinner on submit button animates
|
33 | 34 | * @property {boolean} [hidden] - when true, hides the element (in this case, the form)
|
|
38 | 39 |
|
39 | 40 | /** @type {Props} */
|
40 | 41 | let {
|
41 |
| - id = `id${new Date().getTime()}`, |
42 |
| - form = `form#${id}`, |
43 | 42 | postResponseStatusCode = $bindable(),
|
44 | 43 | loading = $bindable(false),
|
45 | 44 | hidden = $bindable(false),
|
|
86 | 85 | event.stopPropagation();
|
87 | 86 | loading = false;
|
88 | 87 | formValid.classList.add('was-validated');
|
89 |
| - if (formValid.querySelector('#name.form-control:invalid')) { |
| 88 | + if (formValid.querySelector(`#${id}-name.form-control:invalid`)) { |
90 | 89 | nameError = true;
|
91 | 90 | }
|
92 |
| - if (formValid.querySelector('#email.form-control:invalid')) { |
| 91 | + if (formValid.querySelector(`#${id}-email.form-control:invalid`)) { |
93 | 92 | emailError = true;
|
94 | 93 | }
|
95 |
| - if (formValid.querySelector('#summary.form-control:invalid')) { |
| 94 | + if (formValid.querySelector(`#${id}-summary.form-control:invalid`)) { |
96 | 95 | summaryError = true;
|
97 | 96 | }
|
98 |
| - if (formValid.querySelector('#description.form-control:invalid')) { |
| 97 | + if (formValid.querySelector(`#${id}-description.form-control:invalid`)) { |
99 | 98 | descriptionError = true;
|
100 | 99 | }
|
101 | 100 | errorMessage = true;
|
|
143 | 142 | <main>
|
144 | 143 | <form {onsubmit} class:hidden class="needs-validation mb-3" name="feedback" novalidate {id}>
|
145 | 144 | <div class="mb-3">
|
146 |
| - <label for="name" class="form-label">Name <span class="required" aria-hidden="true">(required)</span> </label> |
| 145 | + <label for="{id}-name" class="form-label" |
| 146 | + >Name <span class="required" aria-hidden="true">(required)</span> |
| 147 | + </label> |
147 | 148 | <input
|
148 | 149 | aria-describedby="name-error"
|
149 | 150 | type="name"
|
150 | 151 | class="form-control"
|
151 |
| - id="name" |
| 152 | + id="{id}-name" |
152 | 153 | name="name"
|
153 | 154 | autocomplete="name"
|
154 | 155 | required
|
155 | 156 | />
|
156 |
| - <div class="invalid-feedback" id="name-error"> |
| 157 | + <div class="invalid-feedback" id="{id}-name-error"> |
157 | 158 | {#if nameError}
|
158 | 159 | <span>Error: Please provide your name.</span>
|
159 | 160 | {/if}
|
160 | 161 | </div>
|
161 | 162 | </div>
|
162 | 163 | <div class="mb-3">
|
163 |
| - <label for="email" class="form-label" |
| 164 | + <label for="{id}-email" class="form-label" |
164 | 165 | >Email address <span class="required" aria-hidden="true">(required)</span></label
|
165 | 166 | >
|
166 | 167 | <input
|
167 | 168 | type="email"
|
168 | 169 | class="form-control"
|
169 |
| - id="email" |
| 170 | + id="{id}-email" |
170 | 171 | name="email"
|
171 | 172 | aria-describedby="email-error"
|
172 | 173 | autocomplete="email"
|
173 | 174 | required
|
174 | 175 | />
|
175 |
| - <div class="invalid-feedback" id="email-error"> |
| 176 | + <div class="invalid-feedback" id="{id}-email-error"> |
176 | 177 | {#if emailError}<span>Error: Please provide an email address.</span>{/if}
|
177 | 178 | </div>
|
178 | 179 | </div>
|
179 | 180 | <div class="mb-3">
|
180 |
| - <label for="summary" class="form-label" |
| 181 | + <label for="{id}-summary" class="form-label" |
181 | 182 | >Short summary <span class="required" aria-hidden="true">(required)</span></label
|
182 | 183 | >
|
183 |
| - <input type="text" class="form-control" id="summary" name="summary" aria-describedby="summary-error" required /> |
184 |
| - <div class="invalid-feedback" id="summary-error"> |
| 184 | + <input |
| 185 | + type="text" |
| 186 | + class="form-control" |
| 187 | + id="{id}-summary" |
| 188 | + name="summary" |
| 189 | + aria-describedby="summary-error" |
| 190 | + required |
| 191 | + /> |
| 192 | + <div class="invalid-feedback" id="{id}-summary-error"> |
185 | 193 | {#if summaryError}<span>Error: Please provide a title or subject line to summarize your feedback.</span>{/if}
|
186 | 194 | </div>
|
187 | 195 | </div>
|
188 | 196 | <div class="mb-3">
|
189 |
| - <label for="bookDescription" class="form-label" |
| 197 | + <label for="{id}-bookDescription" class="form-label" |
190 | 198 | >If your question is related to a specific book, what is the title or URL? <span
|
191 | 199 | class="required"
|
192 | 200 | aria-hidden="true">(optional)</span
|
193 | 201 | ></label
|
194 | 202 | >
|
195 |
| - <input type="text" class="form-control" id="bookDescription" name="bookDescription" /> |
| 203 | + <input type="text" class="form-control" id="{id}-bookDescription" name="bookDescription" /> |
196 | 204 | </div>
|
197 | 205 | <div class="mb-3">
|
198 |
| - <label for="description" class="form-label" |
| 206 | + <label for="{id}-description" class="form-label" |
199 | 207 | >Full description of problem or question <span class="required" aria-hidden="true">(required)</span></label
|
200 | 208 | >
|
201 | 209 | <textarea
|
202 | 210 | class="form-control"
|
203 | 211 | aria-describedby="description-error"
|
204 |
| - id="description" |
| 212 | + id="{id}-description" |
205 | 213 | name="description"
|
206 | 214 | rows="3"
|
207 | 215 | required
|
208 | 216 | ></textarea>
|
209 |
| - <div class="invalid-feedback" id="description-error"> |
| 217 | + <div class="invalid-feedback" id="{id}-description-error"> |
210 | 218 | {#if descriptionError}<span
|
211 | 219 | >Error: Please provide some background or details for your feedback or question.</span
|
212 | 220 | >{/if}
|
|
0 commit comments