Created
May 2, 2024 17:34
-
-
Save Valian/6418d0d4af528d8a15963e27100431f5 to your computer and use it in GitHub Desktop.
Phoenix LiveView teleport hook
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<.flash_group flash={@flash} /> | |
<main> | |
<%= @inner_content %> | |
</main> | |
<%!-- We're doing teleport because navigation is rendered in root layout which is not updated --%> | |
<%!-- Notice "hidden" class, it's important because we're not really teleporting content, but duplicating it --%> | |
<div :if={@current_user} id="onboarding-render" phx-hook="teleport" data-teleport-target="onboarding" class="hidden"> | |
<MyApp.Onboarding.onboarding current_user={@current_user} /> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { teleportHook } from "./hooks/teleport"; | |
// ... | |
const liveSocket = new LiveSocket("/live", Socket, { | |
params: { _csrf_token: csrfToken }, | |
hooks: { teleport: teleportHook }, | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8" /> | |
</head> | |
<body> | |
<nav> | |
<div id="onboarding"> | |
<%!-- Teleported content will land here --%> | |
</div> | |
</nav> | |
<%= @inner_content %> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Teleport hook for phoenix live view | |
// It's not a real teleport, but rather a synchronized duplication of DOM Element | |
// On mount and on each update we copy the DOM element to the destination. | |
// I tried to really move it to the destination, but it screws up phoenix DOM morph updates | |
// Example use case - updating onboarding being part of navigation rendered in root.html.heex | |
// Example use case 2 - updating footer | |
const getTarget = (el: HTMLElement) => { | |
const target = el.dataset.teleportTarget | |
if (!target) { | |
console.error("No teleport target provided") | |
return | |
} | |
const targetElement = document.getElementById(target) | |
if (!targetElement) { | |
console.error("No teleport target element found") | |
return | |
} | |
return targetElement | |
} | |
export const teleportHook = { | |
mounted() { | |
this.teleport() | |
}, | |
updated() { | |
this.teleport() | |
}, | |
teleport() { | |
const target = getTarget(this.el) | |
if(target) { | |
target.replaceChildren(...this.el.cloneNode(true).childNodes) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment