Overview: I am trying to use MathJax in my livewire component to format math problems. It works fine until a livewire request is made.
What I have done:
I have added the following to my layout file:
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
My Livewire component:
class ShowMathProblemPage extends Component
{
public string $problem = '$$4^2 + 4/6$$';
public function generateNewProblem()
{
$this->problem = '$$5/534^56$$';
}
}
Livewire blade:
<div>
{{ $problem }}
<button wire:click="generateNewProblem">
New Problem
</button>
</div>
The issue:
It works on initial load - but as soon as the livewire call is made to generateNewProblem
(or anything else) the formatter is not reapplied.
I have tried using the following (and variation) to trigger the formatter to run again with no dice:
<script>
document.addEventListener("DOMContentLoaded", () => {
Livewire.on('run-formatter', () => {
MathJax.typesetPromise().then(() => {
MathJax.typesetPromise();
}).catch((err) => console.log(err.message));
});
});
</script>
This is a possible solution:
public function generateNewProblem()
{
$this->problem = '$$5/534^56$$';
$this->dispatch('run-formatter');
}
<div @run-formatter.window="$nextTick(() => MathJax.typeset())">
{{ $problem }}
<button wire:click="generateNewProblem">
New Problem
</button>
</div>
The event is captured by the container of the element to be formatted, using $nextTick() the formatting is invoked after the dom has been updated
If you want to maintain global level management, you can modify your code like this:
<script>
document.addEventListener("alpine:init", () => { // "livewire:init" works too
Livewire.on('run-formatter', () => {
Alpine.nextTick (() => MathJax.typeset());
});
});
</script>