Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mooseh's avatar

component in component ref not working?

So I'm pretty sure i have pulled this off in vue2 many times, but for some reason i am having a harder time getting my head around the vue3 and the composition api.

I have a form for creating / editing an entry like so Form.vue

<script setup>
import { reactive } from 'vue'

let entry = reactive({
    name: null,
    description: null,
    link: null,
    datetime: null,
})

const setEntry = (newEntry) => {
    Object.assign(entry, newEntry)
}

defineExpose({
    setEntry
});
</script>

I want to use this form inside of a modal so i am doing this on the page: Home.vue

      <modal ref="eventFormModal" name="Test">
          <EntryFormComponent ref="entryForm"/>
      </modal>

with Home.vue

<script setup>
  import EntryFormComponent from '../Entry/Form.vue'
  import Modal from '../Modals/Static.vue'
  const entryForm = ref(null)
  const eventFormModal = ref(null)

  const selectEntry = (entry) => {
    eventFormModal.value.toggleOpen()
    //console.log(entryForm.value)
    entryForm.value.setEntry(entry)
  }

Static.vue

<template>
  <TransitionRoot as="template" :show="data.open">
    <Dialog as="div" class="relative z-10">
      <TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0" enter-to="opacity-100" leave="ease-in duration-200" leave-from="opacity-100" leave-to="opacity-0">
        <div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity"/>
      </TransitionChild>

      <div class="fixed inset-0 z-10 overflow-y-auto">
        <div class="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0" @click="toggleOpen()">
          <TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" enter-to="opacity-100 translate-y-0 sm:scale-100" leave="ease-in duration-200" leave-from="opacity-100 translate-y-0 sm:scale-100" leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
            <DialogPanel class="relative transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-xl sm:p-6">
              <slot></slot>
            </DialogPanel>
          </TransitionChild>
        </div>
      </div>
    </Dialog>
  </TransitionRoot>
</template>

<script setup>
import { reactive, defineProps, ref } from 'vue'
import { Dialog, DialogPanel, DialogTitle, TransitionChild, TransitionRoot } from '@headlessui/vue'
import { CheckIcon } from '@heroicons/vue/24/outline'

const wrapper = ref(null)

const data = reactive({
  open: false
})

const toggleOpen = () => {
    data.open = !data.open
}

const props = defineProps({
  name: {
    type: String,
    required: true,
  }
})

defineExpose({
  wrapper,
  toggleOpen
})

</script>

for some reason entryForm.value is null if i pull the entry form outside of the modal slot it works just fine, what am i missing here?

0 likes
1 reply

Please or to participate in this conversation.