Stefan Neubert
Stefan Neubert

Reputation: 1054

How to force Vue to update modified HTML

I use a custom directive to render LaTeX-code with KaTeX' renderMathInElement function. This, obviously, changes the component's innerHTML. I would like to re-run KaTeX once the content changes, but: The content never does!

A simple reproduction of the problem does not need KaTeX or directives and still shows, that reactivity works, but stops to work for the parts of a component with changed innerHTML:

<template>
  <div>
    {{content}}
    <span ref="elem">{{content}}</span>
  </div>
</template>

<script lang="ts">
  import { Component, Ref, Vue } from "vue-property-decorator";

  @Component({})
  export default class Test extends Vue {
    content = "Hello World!";

    @Ref()
    elem!: HTMLSpanElement;

    mounted(): void {
      // Without the following statement, Vue correctly re-renders the whole component after a second with the new content
      // With this line, the update does not happen for the span element.
      this.elem.innerHTML = "<b>Hello World!</b>";

      setTimeout(() => {
        this.content = "Greetings!";
      }, 1000);
    }
  }
</script>

I suppose this is intended behavior - but that doesn't solve my problem. Is there some way to force Vue to replace all the component's DOM as soon as a re-render takes place?

Upvotes: 0

Views: 269

Answers (1)

marsnebulasoup
marsnebulasoup

Reputation: 2660

You can use a key on your span, but if you don't want to tie it in with content, you can instead set it to a number, and increment it every time you want to make a change. Like so (I am not using TS here):

Set a key on your span:

<span :key="content_key">{{ content }}</span>

Then you can watch content and update the key accordingly:

watch: {
    content() {
        this.content_key ++;
    }
}

In this way you can avoid setting the key to content directly.

Does this work for you?

Upvotes: 1

Related Questions