|
1 | 1 | <template>
|
2 | 2 | <slot v-if="$slots.toggle" name="toggle" v-bind="{ toggleModal, model }"></slot>
|
3 | 3 | <Teleport v-if="!disabled" :id="modalId" :key="modalId" :to="target || 'body'">
|
4 |
| - <dialog ref="modalRef" @close="closeAndResetModal" @mousedown="clickOutside"> |
| 4 | + <dialog ref="modalRef" @close="closeModal" @mousedown="clickOutside"> |
5 | 5 | <div
|
6 | 6 | v-show="!loading && !hide"
|
7 | 7 | class="modal"
|
|
21 | 21 | <ActionLink
|
22 | 22 | :theme="theme"
|
23 | 23 | :aria-label="cancelButtonOptions.title"
|
24 |
| - @click.stop="closeAndResetModal" |
| 24 | + @click.stop="closeModal()" |
25 | 25 | >
|
26 | 26 | <IconFa name="xmark" size="20" />
|
27 | 27 | </ActionLink>
|
|
35 | 35 | :theme="theme"
|
36 | 36 | :aria-label="saveButtonOptions.title"
|
37 | 37 | :class="saveButtonOptions.btnClass"
|
38 |
| - @click="emit('save', closeAndResetModal, $event)" |
| 38 | + @click="emit('save', closeModal, $event)" |
39 | 39 | >
|
40 | 40 | {{ saveButtonOptions.title }}
|
41 | 41 | </ActionButton>
|
|
46 | 46 | :class="cancelButtonOptions.btnClass"
|
47 | 47 | data-dismiss="modal"
|
48 | 48 | round=":sm-inv"
|
49 |
| - @click.stop="closeAndResetModal" |
| 49 | + @click.stop="closeModal()" |
50 | 50 | >
|
51 | 51 | <IconFa name="xmark" hidden="-full:sm" />
|
52 | 52 | <IconFa name="xmark" regular hidden="-full:sm" />
|
|
66 | 66 | <p class="--txtColor-light --txtShadow --txtSize-sm">
|
67 | 67 | {{ props.hideMessage ? props.hideMessage : t("modal_taking_too_long") }}
|
68 | 68 | </p>
|
69 |
| - <ActionButton |
70 |
| - :theme="theme" |
71 |
| - :aria-label="t('close')" |
72 |
| - @click="closeAndResetModal" |
73 |
| - > |
| 69 | + <ActionButton :theme="theme" :aria-label="t('close')" @click="closeModal()"> |
74 | 70 | {{ t("close") }}
|
75 | 71 | </ActionButton>
|
76 | 72 | </div>
|
|
192 | 188 | ...(!!props.cancelButton && props.cancelButton),
|
193 | 189 | }));
|
194 | 190 |
|
195 |
| - function closeAndResetModal() { |
| 191 | + function closeModal(success?: boolean) { |
196 | 192 | modalRef.value?.close();
|
197 | 193 | loadingTooLong.value = false;
|
| 194 | + localModel.value = false; |
| 195 | + resolver.value?.(success); // resolve promise early |
198 | 196 | emit("update:model-value", false);
|
199 | 197 | emit("close");
|
200 | 198 | }
|
201 | 199 | function clickOutside(e: Event) {
|
202 | 200 | if (modalRef.value !== e.target) return;
|
203 | 201 |
|
204 |
| - closeAndResetModal(); |
| 202 | + closeModal(); |
| 203 | + } |
| 204 | + /** |
| 205 | + * Opens modal if requirements are met |
| 206 | + */ |
| 207 | + function openModal() { |
| 208 | + localModel.value = true; |
| 209 | + modalRef.value?.showModal(); |
| 210 | +
|
| 211 | + // close modal if requirements are not meet |
| 212 | + if (!props.loading && props.hide) { |
| 213 | + Swal.fire({ |
| 214 | + title: t("swal.modal_unauthorized"), |
| 215 | + text: props.hideMessage || t("swal.modal_unauthorized_text"), |
| 216 | + icon: "warning", |
| 217 | + }); |
| 218 | +
|
| 219 | + return closeModal(); |
| 220 | + } |
| 221 | +
|
| 222 | + // display message if loading longer than usual |
| 223 | + setTimeout(() => (loadingTooLong.value = props.loading), 3000); |
205 | 224 | }
|
206 | 225 | /**
|
207 | 226 | * Toggles modal
|
|
210 | 229 | function toggleModal(success?: boolean) {
|
211 | 230 | return new Promise<boolean | undefined>((resolve) => {
|
212 | 231 | if (model.value) {
|
213 |
| - // old promise |
214 |
| - resolver.value?.(success); |
215 |
| - // current promise |
216 |
| - resolve(success); |
217 |
| - } else resolver.value = resolve; |
218 |
| -
|
219 |
| - model.value = !model.value; |
| 232 | + closeModal(success); // close & resolve old promise |
| 233 | + resolve(undefined); // bypass promise |
| 234 | + } else { |
| 235 | + resolver.value = resolve; |
| 236 | + openModal(); |
| 237 | + } |
220 | 238 | });
|
221 | 239 | }
|
222 | 240 |
|
223 |
| - /** |
224 |
| - * Modal model |
225 |
| - */ |
226 |
| - const model = computed({ |
227 |
| - get() { |
228 |
| - return !props.disabled && localModel.value; |
229 |
| - }, |
230 |
| - set(value) { |
231 |
| - if (!value) closeAndResetModal(); |
232 |
| - else { |
233 |
| - modalRef.value?.showModal(); |
234 |
| -
|
235 |
| - // close modal if requirements are not meet |
236 |
| - if (!props.loading && props.hide) { |
237 |
| - value = false; |
238 |
| - closeAndResetModal(); |
239 |
| - Swal.fire({ |
240 |
| - title: t("swal.modal_unauthorized"), |
241 |
| - text: props.hideMessage || t("swal.modal_unauthorized_text"), |
242 |
| - icon: "warning", |
243 |
| - }); |
244 |
| - } |
245 |
| -
|
246 |
| - // display message if loading longer than usual |
247 |
| - setTimeout(() => (loadingTooLong.value = props.loading), 3000); |
248 |
| - } |
249 |
| -
|
250 |
| - localModel.value = value; |
251 |
| - }, |
252 |
| - }); |
| 241 | + /** Modal model */ |
| 242 | + const model = computed(() => !props.disabled && (props.modelValue || localModel.value)); |
253 | 243 |
|
254 | 244 | // lifecycle
|
255 | 245 | onMounted(() => {
|
256 |
| - if (props.modelValue) model.value = props.modelValue; |
| 246 | + watch( |
| 247 | + () => props.modelValue, |
| 248 | + (show) => { |
| 249 | + if (show) openModal(); |
| 250 | + }, |
| 251 | + { immediate: true } |
| 252 | + ); |
257 | 253 | });
|
258 |
| - onUnmounted(closeAndResetModal); |
259 |
| - watch( |
260 |
| - () => props.modelValue, |
261 |
| - (show) => (model.value = show), |
262 |
| - { immediate: false } |
263 |
| - ); |
| 254 | + onUnmounted(closeModal); |
264 | 255 | </script>
|
0 commit comments