Modals
How it works
Spire uses Modals differently than most Component-Libraries out there. Instead of specifically creating a component that is using some sort of <Modal> component with its own button, Spire can use any Component as a Modal.
This way we can ensure proper lifecycle-hook management of those Modals. Most other ways create issues around when onMounted or similar hooks are being called, since the Component already gets rendered with the display of its "Open Modal" Button.
Another benefit of this is that you don't have to care to much about what a Modal is. Let's say you have an "Edit Customer" Page. Wouldn't it be cool if you could use it within a Modal, but also within a Page? You can do this by default!
Opening a Modal
Opening a Modal is as straighforward as calling openModal(component: Component, props: ComponentProps).
<script setup lang="ts">
import { useModal } from "@/toolkit"
import MyModalComponent from "@/ui/components/MyModalComponent.vue"
const { openModal } = useModal()
const openMyModal = () => {
openModal(MyModalComponent, {
somePropKey: "schning"
})
}
</script>
<template>
<button @click="openMyModal()">Open Modal</button>
</template><script setup lang="ts">
import { useModal, type Modal } from "@/toolkit"
const props = defineProps<Modal & {
somePropKey: string
}>()
const { closeModal } = useModal(props)
</script>
<template>
<button @click="closeModal()">Close Modal</button>
</template>INFO
useModal will pass some randomly generated ID to the Modals props to track it. You don't have to care about this. Just use the Modal type in your Props and pass your Props object to useModal() and it will take care of it.
The cool thing about this is, that you could (theoretically) use <MyModalComponent/> just normally, without it being rendered in a modal. Spire changes the question to "Is it a Modal?" to "where do we need this to render?".
Emitting Events
Ofcourse, a Modal-System is no good if we don't have a way to emit things from a Modal. Spire provides similar-to-vue experience by providing "emit", "passthrough" and "on" methods on a modal instance.
If you want to emit something in your Modal component:
<script setup lang="ts">
import { useModal, type Modal } from "@/toolkit"
const props = defineProps<Modal & {
somePropKey: string
}>()
const { emit } = useModal(props)
const emitSomeThing = () => {
emit('saved', {
status: true
})
}
</script>
<template>
<button @click="emitSomeThing()">Emit</button>
</template>And how to react to it in the caller component:
<script setup lang="ts">
import { useModal } from "@/toolkit"
import MyModalComponent from "@/ui/components/MyModalComponent.vue"
const { openModal } = useModal()
const openMyModal = () => {
openModal(MyModalComponent, {
somePropKey: "schning"
}).on('saved', (data) => {
// data will be { status: true }
})
}
</script>
<template>
<button @click="openMyModal()">Open Modal</button>
</template>There's also helper methods like onClose() that will be triggered if the modal gets closed either way.
passthrough() will grab an event and re-emit it. This is useful if you have modals that open on top of other modals and you want the event to propagate further.
If you need to set a custom css class to the modal container, like setting a specific width, you can use setClass()