Skip to content

Template refs inside <Html> component are not working #596

@damienmontastier

Description

@damienmontastier

Describe the bug

I am using <Html> to wrap elements containing template refs, but these refs are not correctly initialized. As a result, the references to the slotted elements are inaccessible within the component's lifecycle.

Perhaps related to issues: 464312

Reproduction

https://play.tresjs.org/#eNqdVW1v2zYQ/iucgiEuJkuykxSb5xSZ3XbtsKxBG2Afqn5gpIvFhCIJkvLLAv/3HSnLlpLWdWoLhnkvzz13vDs9BNcazB9KRfMKglEwNplmyhIDtlKEUzE7TwNr0uBVKlippLbkgWi4DYkUl7ISFvKQLKjNCrImt1qW5BiBjn9vWbsAUyrm1GxNLizK7kycSd21/aBvmJ1KYbXkJiTvbMmfOjEQVhrnl4pMCmOJoprONFUf4ZacO3o9UXH+whlsafZ6L8j5K/KQCkKcl+QQcTnrHZe1/jhsw0RzyitAhLVH8Rn2WvqQfAvOm+4BG8d1ibGgeLBQKk4t4ImQcatUCyZyuegb9h+QjAPV/UxyqfE2jn4dvp5Mz/yVEPx4ryvQRkFm2RymtARNyUhJwyyTAl0+/xYS93xJAxI3bp1a78QO7RJM0QXoD0OCT+IQRlpa2iiSkFxSW0RX72vtBqZJRgr4E2QJVq/IiOqZcT6DkAyis5CctPm0Ql9LvDUsimaUY3Efpb2jGjcO+7kjRfe4YBk1tm8KiqXthp3I5Vd4OpLNz7O4nr513x/gijV2pX5ayU+qAL2r5cFM3k4mycmkwx19/GBlOEegW2JUKDc96NfqXmTyDjiX5F+pef7TOFZtpNhB7U3yNdOuMaWg/G82K+yTy8F8T31fMeQjULVCxSAadu9rk0Adox4SFIzj1gTh0dgVd38LZBWm4kbmq3pGS7xUJkYkwbVBcDjznIlZcyzAERuRQZL87AULlttie16n4ogqVQN9x5aQG5rdzzQulbwe2RE5ShIXB2Fw+D3BIAzqndcvqYrujBS4ez18ulHgyh3VAZ2svTCdIg0Ka5UZxXGWC/TPgbO5jgTYWKgybptfnEbDaBjnzNjYidE6DbA0j4Drpfoc7NoD4ZMo6QtY2miwi7LRdoPZBdB7RcUhKWxtfYAGuRFGJXM+bexCw0G4zu4CEV8i7fgXMGW7GvjuqgwcXOaW+cUgic4QEdc2LKOyW+SNHTayhvwZwLXDPmg07OdQsgNAG1OX/Gn0Mubspg3pELFD19ia1uAb7ZbNHjVmJkvFOOgPyg1vt0EpLojFX15mdQVbflkB2f1X5HdmWVO+wmYBPcdy764SRxVsrX7z6R/srJaylHnFN5fzDeVHwLdx5TjWZhMcRaTdsvNs3/s5wy1wbd4s/eLZJNUhalcKvPRzs/S2vVYLvvjCeXt/HdM9VdpldhKdbAu+/h+NgxeG

Steps to reproduce

  1. Use the <Html> component to wrap elements containing template refs.
  2. Observe that these refs are not initialized (console.log inside onMounted shows them as undefined).
  3. Any logic relying on these refs does not work as expected.
<template>
  <Html>
    <div ref="container">Some Content</div>
  </Html>
</template>

<script setup>
import { Html } from '@tresjs/cientos'
import { ref, onMounted, watch } from 'vue';

const container = ref(null);

onMounted(() => {
  console.log(container.value); // Expected: DOM Element | Actual: null
});

watch(container, () => {
  console.log('watch', container.value);  // Expected: DOM Element | Actual: The log never appears
})
</script>

Summary of Solutions

Parent refs don't get assigned when using createVNode() and render() because the content ends up outside the parent's render tree. Here's a quick breakdown:

What Doesn't Work

  • Direct <Teleport>
    The custom TresJS renderer can't find the target in the standard DOM.

  • Manual createVNode() + render()
    This creates a new root outside the parent's render tree, so refs declared in the template aren't assigned.

What Might Work ?

  • Global Store (Pinia/Vuex)
    You could set up a tunnel to share content via a global store, but that adds an external dependency we’d rather avoid.

  • Tunnel via Provide/Inject (In/Out)
    Use provide/inject to share a reactive state (like an array of VNodes) between an "In" component (capturing the content) and an "Out" component (rendering it in the standard DOM). This should preserve reactivity and proper ref assignment without extra dependencies. This message in issue 312 talked about this method.

System Info

System:
    OS: macOS 15.1.1
    CPU: (14) arm64 Apple M4 Pro
    Memory: 116.89 MB / 24.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.11.0 - ~/.nvm/versions/node/v22.11.0/bin/node
    npm: 11.0.0 - ~/.nvm/versions/node/v22.11.0/bin/npm
    pnpm: 9.14.4 - ~/.nvm/versions/node/v22.11.0/bin/pnpm
  Browsers:
    Chrome: 133.0.6943.55
    Safari: 18.1.1

Used Package Manager

pnpm

Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions