Search code examples
javascriptvue.jsvuex

Execute script from plain HTML in vue


I'm fetching a plain HTML widget which contains a script tags from remote API to vuex store. To properly render this widget scripts needs to be executed. Inside vue component I'm doing it this way:

<div v-html="widget" id="widget-container"></div>


computed: mapGetters(["widget"]), // getter returns string of plain HTML
    methods: {
        renderWidget () {
            let container = document.getElementById("widget-container")
            let scriptsTags = container.getElementsByTagName("script")
                for (let i = 0; i < scriptsTags.length; i++) {
                    let parentNode = scriptsTags[i].parentNode
                    let newScriptTag = document.createElement("script")
                    newScriptTag.type = "text/javascript"
                    newScriptTag.text = scriptsTags[i].text
                    parentNode.removeChild(scriptsTags[i])
                    parentNode.appendChild(newScriptTag)
                }
            },
        }

It works perfectly if I assign this method to button click event or else, but not on

mounted () { 
    this.renderWidget()
}

hook. Nothing happens.

So how should I execute scripts after fetching?


Solution

  • widget value isn't available on mount. Script execution can be triggered when a widget is already available in DOM, either with a watcher or updated hook:

      watch: {
        widget(widgetHtml) {
          if (!widgetHtml)
            return;
    
          this.$nextTick(this.renderWidget);
        }
      }
    

    Notice that this way scripts can be evaluated multiple times.