-
-
Save blackfyre/ccd2a207948912594b5ac6cf67a11ef8 to your computer and use it in GitHub Desktop.
<template> | |
<modal @modal-close="handleClose"> | |
<form | |
@submit.prevent="handleConfirm" | |
slot-scope="props" | |
class="bg-white rounded-lg shadow-lg overflow-hidden" | |
style="width: 460px" | |
> | |
<slot :uppercaseMode="uppercaseMode" :mode="mode"> | |
<div class="p-8"> | |
<heading :level="2" class="mb-6">{{ __('General Modal') }}</heading> | |
<p class="text-80 leading-normal">{{__('General modal contents')}}</p> | |
</div> | |
</slot> | |
<div class="bg-30 px-6 py-3 flex"> | |
<div class="ml-auto"> | |
<button type="button" data-testid="cancel-button" dusk="cancel-general-button" @click.prevent="handleClose" class="btn text-80 font-normal h-9 px-3 mr-3 btn-link">{{__('Cancel')}}</button> | |
<button id="confirm-delete-button" ref="confirmButton" data-testid="confirm-button" type="submit" class="btn btn-default btn-danger">{{ __(uppercaseMode) }}</button> | |
</div> | |
</div> | |
</form> | |
</modal> | |
</template> | |
<script> | |
export default { | |
name: "GeneralModal", | |
methods: { | |
handleClose() { | |
this.$emit('close') | |
}, | |
handleConfirm() { | |
this.$emit('confirm') | |
}, | |
}, | |
/** | |
* Mount the component. | |
*/ | |
mounted() { | |
this.$refs.confirmButton.focus() | |
}, | |
} | |
</script> | |
<style scoped> | |
</style> |
<template> | |
<div> | |
<button @click="openModal">{{__('Open Modal')}}</button> | |
<portal to="modals"> | |
<transition name="fade"> | |
<general-modal | |
v-if="modalOpen" | |
@confirm="confirmModal" | |
@close="closeModal" | |
/> | |
</transition> | |
</portal> | |
</div> | |
</template> | |
<script> | |
import GeneralModal from './parts/modals/GeneralModal.vue'; | |
export default { | |
props: ["resourceName", "resourceId", "field"], | |
data() { | |
return { | |
modalOpen: false | |
} | |
}, | |
components: { | |
GeneralModal | |
}, | |
mounted() { | |
}, | |
methods: { | |
openModal() { | |
this.modalOpen = true; | |
}, | |
confirmModal() { | |
this.modalOpen = false; | |
}, | |
closeModal() { | |
this.modalOpen = false; | |
} | |
} | |
}; | |
</script> |
@henryavila
Thanks for the background, this puts things into perspective 😄
Haven't developed a Card before, but the match between the Card & Tool vue files seems reasonable.
As for placing the GeneralModal.vue
file is totally up to you! At some point, you'll have to reference it in your card vue file.
Hello everyone, today i face one problem that I can't use improted component inside this <modal>
tag, maybe I do something wrong, I wanted to use vuedraggable to make some functionality inside my project, but i couldn't because <draggable>
tag is not initialize like draggable component. After I tried to make my own component just with test content like "Hello world" and import that component and use it inside <modal>
tag, the same result. Laravel Nova
If i need two modals in my tool.vue, i need to make two but this does not work I mean if i have two components GeneralModal and TableModal both using difference betwen componentes is only the contenu in the Nova modal's slot, how could I have two modals ?
thanks for this mehn
Thank you for your sharing; I fixed it for Nova 4 like this:
Similar to your implementation but changed to match laravel/nova/resources/js/components/Modals/DeleteResourceModal.vue
GeneralModal.vue
<template>
<Modal @modal-close="handleClose"
:show="show"
role="alertdialog"
size="sm">
<form
@submit.prevent="handleConfirm"
class="mx-auto bg-white dark:bg-gray-800 rounded-lg shadow-lg overflow-hidden"
>
<slot/>
<ModalFooter>
<div class="ml-auto">
<LinkButton
type="button"
data-testid="cancel-button"
dusk="cancel-delete-button"
@click.prevent="handleClose"
class="mr-3"
>
{{ __('Cancel') }}
</LinkButton>
<LoadingButton
ref="confirmButton"
dusk="confirm-delete-button"
:processing="working"
:disabled="working"
component="DangerButton"
type="submit"
>
{{ confirmButtonText }}
</LoadingButton>
</div>
</ModalFooter>
</form>
</Modal>
</template>
<script setup>
import {ref, watchEffect} from 'vue'
const props = defineProps({
confirmButtonText: {
type: String,
default: 'Delete'
}
})
const emit = defineEmits(['close', 'confirm'])
const confirmButton = ref(null)
watchEffect(() => {
// Only focus when mounted (e.g. if hidden through :show)
if (confirmButton.value) {
confirmButton.value.focus()
}
})
const handleClose = () => {
emit('close')
};
const handleConfirm = () => {
emit('confirm')
};
</script>
Tool.vue
...
<GeneralModal
:show="modalOpen"
confirmButtonText="Delete"
@close="closeModal"
@confirm="confirmModal">
<ModalHeader>Delete resource</ModalHeader>
<ModalContent>
<p class="leading-normal">
Are you sure you want to delete the resource?
</p>
</ModalContent>
</GeneralModal>
...
@bmoex thanks for the snippet. any idea how to trigger the auto close on click away functionality? I can see that Nova 4 native modals have it
@bmoex thanks for the snippet. any idea how to trigger the auto close on click away functionality? I can see that Nova 4 native modals have it
You really can't do that without modifying the nova code as it usually involves a click listener on the backdrop.
Thanks for quick response @blackfyre. In fact I'm using Laravel Nova. I'm new in VueJS and automatically the way Laravel Nova use it. I'm a backend (php) developer starting with the frontend with Laravel Nova.
If you could give some direction, I will be so gald.
For example. I create a Card in Laravel Nova. And whant this card to display a Modal. In this case, the
Tool.vue
in your gist represent my Card vue file? Then where do I put theGeneralModal.vue
(from your gist) file?