Elements not staying in declared relationship in Vue template

Viewed 23

I am witnessing really weird behavior in Vue that I want to understand. I have this template:

IhConfirm.vue

<template>
  <v-dialog
    data-cy="ihconfirm-datacy" // <--
    v-model="dialog"
    :max-width="options.width"
    :style="{ zIndex: options.zIndex }"
    persistent
    @keydown.esc="cancel"
  >
    <ih-modal-card id="ih-confirm-modal"> // <--
      <ih-modal-title class="headline">{{ options.title }}</ih-modal-title>
      <ih-modal-body class="body-1 confirm-body">
...
      </ih-modal-body>
      <ih-modal-actions>
...
      </ih-modal-actions>
    </ih-modal-card>
  </v-dialog>
</template>

Importantly, I added the data-cy="ihconfirm-datacy" attribute strictly debugging purposes. The attribute: id="ih-confirm-modal" was already there. For debugging I am using each as a reference to each other.

has only one child, which is My expectation is that if I give an attribute, I should see it in the rendered element that wraps the rendered in the actual browser DOM or at least in a hierarchical arrangement. Instead I see it far flung to a different section and unrelated branch of the tree.

picture of DOM

This does not make sense to me. I know Vue renders the html like template syntax into highly optimized JS code that can do whatever it wants, but why and how would it be made or configured to do something like this?

FWIW The original problem I had is that we declare an id in the IhConfirm modal, but it's a generic component and if two such modals open up, we have two elements with the same ID and that happened and it's breaking testing. Actually even if they click the modal button, it just hides it with display:none which is probably bad practice. The code above is not my intended solution, just an illustration. When I do a similar thing in the parent component and pass an attribute into its instance, the same behavior happens- it flings what should be two related elements far and wide apart. There's also exactly 1 of each in my dev tools so there's no mistaken identity going on.

I'd like to understand how this kind of rendering is possible. It's like the parent component is giving the child component up for adoption.

Thank you for any help and insights!

1 Answers

This is a special design of Vuetify's modal component. Because modals must appear above everything, and because the modal component may be deeply nested an unknown amount of layers, Vuetify's v-dialog is internally designed to attach to the DOM tree as a direct child of the application's root (v-app) component. There is an attach prop you can add to the v-dialog component that will actually let you change this behavior.

Related