Load and run external/third party in liveview dynamically

I have a url input that triggers a lookup that will look for an oembed link and then grab the returned html and add it to the page. But, it seems like the javscript from that html does not run. It will run if it is added on first mount, but not when it is added dynamically by liveview.

Here is an example of what is grabbed and added to the page:

<blockquote class=\"tiktok-embed\" cite=\"https://www.tiktok.com/@scout2015/video/6718335390845095173\" data-video-id=\"6718335390845095173\" data-embed-from=\"oembed\" style=\"max-width: 605px;min-width: 325px;\" > <section><a target=\"_blank\" title=\"@scout2015\" href=\"https://www.tiktok.com/@scout2015?refer=embed\">@scout2015</a><p>Scramble up ur name & I’ll try to guess it😍❤️ <a title=\"foryoupage\" target=\"_blank\" href=\"https://www.tiktok.com/tag/foryoupage?refer=embed\">#foryoupage</a> <a title=\"petsoftiktok\" target=\"_blank\" href=\"https://www.tiktok.com/tag/petsoftiktok?refer=embed\">#petsoftiktok</a> <a title=\"aesthetic\" target=\"_blank\" href=\"https://www.tiktok.com/tag/aesthetic?refer=embed\">#aesthetic</a></p> <a target=\"_blank\" title=\"♬ original sound - tiff\" href=\"https://www.tiktok.com/music/original-sound-6689804660171082501?refer=embed\">♬ original sound - tiff</a> </section> </blockquote> <script async src=\"https://www.tiktok.com/embed.js\"></script>

But, when added dynamically by liveview events, it looks like this because the javascript is not running:
tiktok_oembed_not_working

If I add that block of html statically on the heex template the javacript does run and it loads:

There must be a reason the javascript is not being run when I add it dynamically, but why is that? And is there a way around it?

Adding scripts dynamically is generally a bad idea. Adding a script tag is not a reasonable way to execute code. Add the script once somewhere and figure out how you can tell it to rerun whatever DOM searching it does when being inserted the first time. Trigger that (likely with a js hook) via code on updates.

1 Like

Like @LostKobrakai adding dynamic script is a bad idea. If you have to, I’d recommend to use a iframe and put the content in the srcdoc

1 Like

Thank you. iframe was what I was missing. Adding the html to the srcdoc on the iframe made it work how I needed.

  def render(assigns) do
    {:safe, html} = raw(assigns.oembed_html)

    ~H"""
    <div id={@id} phx-update="ignore">
      <iframe class="w-full aspect-video aspect-square" srcdoc={"#{html}"}></iframe>
    </div>
    """
  end

You may also want to limit what the script inside the iframe can do. See this:

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox

2 Likes