Need help: Unusual Interaction of JS library

I’m trying to use MathJax in combination with Earmark to display math symbols in a LiveView. Here is how I’m including it in my root.html.heex:

<script src=""></script>
<script id="MathJax-script" async src=""></script>

And here’s a link to a working example on jsbin

In my heex template if I have this:

<section class="markdown" phx-update="ignore" id="topic-description">
      <%= Earmark.as_html!(@topic.description) |> Phoenix.HTML.raw() %>

Where the value of @topic.description is a Latex snippet:

$$F = G\frac{m_1m_2}{r^2}$$

I get properly rendered math symbols when my LiveView if first mounted.


However, if @topic.description changes due to a handle_event callback, the new content is not rendered. This makes sense since I am specifying phx-update=“ignore”*

If I remove the phx-update=“ignore” from my template, the math symbols aren’t rendered at all and I just get:


However, I do see the screen quickly flashing the the properly rendered math symbols and then quickly reverting to the un-rendered Latex snippet.

Does anyone have an insight that can move me along a bit?


Once you remove phx-update="ignore", LiveView will update with the new Latex snippet but MathJax does not automagically re-typeset it. I suggest creating a client side hook on that calls MathJax.typeset() on updated.

MathJax in Dynamic Content

If you are writing a dynamic web page where content containing mathematics may appear after MathJax has already typeset the rest of the page, then you will need to tell MathJax to look for mathematics in the page again when that new content is produced. To do that, you need to use the MathJax.typeset() method. This will cause MathJax to look for unprocessed mathematics on the page and typeset it, leaving unchanged any math that has already been typeset.

1 Like

@codeanpeace Yep, that was the ticket. I actually did see a reference to MathJax.typeset() and it did look like it was relevant, but I had never implemented a hook before. Using your reference to client side hook, I was able to figure out how to do it.

Super, the problem that I struggled with for too long is now fixed and I learned something new and useful.