295

How can I manage to get HTML interpreted inside a mustache binding? At the moment the break (<br />) is just displayed/escaped.

Small Vue app:

var logapp = new Vue({
  el: '#logapp',
  data: {
    title: 'Logs',
    logs: [
      { status: true, type: 'Import', desc: 'Learn<br />JavaScript', date: '11.11.2015', id: 1  },
      { status: true, type: 'Import', desc: 'Learn<br />JavaScript', date: '11.11.2015', id: 1  }
    ]
  }
})

And here is the template:

<div id="logapp">    
    <table>
        <tbody>
            <tr v-repeat="logs">
                <td>{{fail}}</td>
                <td>{{type}}</td>
                <td>{{description}}</td>
                <td>{{stamp}}</td>
                <td>{{id}}</td>
            </tr>
        </tbody>
    </table>
</div>
5
  • 2
    doing unescaped HTML for line-breaks is overkill, just wanted to mention that! it's a big security risk Commented Mar 11, 2019 at 19:28
  • 1
    @RyanTaylor why is it a big security risk? Commented Jan 18, 2021 at 12:12
  • 1
    @iiirxs if you don't escape the HTML it can load arbitrary javascript etc. you just wanna make sure users can't input stuff there even indirectly. it's called code injection Commented Feb 14, 2021 at 22:13
  • 5
    how can this be unsafe since it's provided by the application itself and users have no way to inject malicious code? Commented Feb 18, 2021 at 10:42
  • I honestly hear that sort of justification all the time. Yes, everyone seems to have a legitimate use case for dynamic code execution, and yes, if you have absolute control of the output and you're thoroughly sanitizing it as a safeguard, sure, knock yourself out - but unless it's strictly needed, why would you? Why play with fire? The above scenario can easily be worked around with whitespace: pre-wrap + \n. Why take steps to enable and downplay such a classic vulnerability in computer science? It's tiresome to make the case against this every time. Commented Jan 27, 2024 at 6:29

6 Answers 6

390

You can use the v-html directive to show it. like this:

<td v-html="desc"></td>
Sign up to request clarification or add additional context in comments.

5 Comments

That one actually works in vue2. First one trows on compile.
i have a problem with v-html to limit the text, ? is that possible to limit text in v-html ? i tried, it was failed
Try slicing the variable
Jut one comment for v-html. Even if this does the job, we need to have in mind that we should render v-html elements which are sanitized otherwise we expose our front end app to xss vulnerabilities. Official doc here: vuejs.org/v2/guide/security.html
if I have escaped html and unescaped html, how do I make it so it doesn't automatically unescape html?
238

Starting with Vue2, the triple braces were deprecated, you are to use v-html:

<div v-html="task.html_content"> </div>

It is unclear from the documentation link as to what we are supposed to place inside v-html, your variables go inside v-html.

Also, v-html works only with <div> or <span> but not with <template>.

If you want to see this live in an app, click here.

1 Comment

"but not with <template>" is the important part here if you come from Angular.js and look for something like <ng-include>
98

You can read that here

If you use

{{<br />}}

it'll be escaped. If you want raw html, you gotta use

{{{<br />}}}

EDIT (Feb 5 2017): As @hitautodestruct points out, in vue 2 you should use v-html instead of triple curly braces.

3 Comments

Please note that in vue 2.0 the triple moustache has been deprecated you should use v-html instead.
I do not like in the new method that I often have to create an unnecessary element, purely so that it serves to insert html. This sometimes breaks styles and creates unnecessary nesting.
@ИльяЗеленько really must agree with you on this. Particularly true if you are trying to feed text content as a <slot>... you must create a new element
11

You have to use v-html directive for displaying html content inside a vue component

<div v-html="html content data property"></div>

Comments

9

Vue by default ships with the v-html directive to show it, you bind it onto the element itself rather than using the normal moustache binding for string variables.

So for your specific example you would need:

<div id="logapp">    
    <table>
        <tbody>
            <tr v-repeat="logs">
                <td v-html="fail"></td>
                <td v-html="type"></td>
                <td v-html="description"></td>
                <td v-html="stamp"></td>
                <td v-html="id"></td>
            </tr>
        </tbody>
    </table>
</div>

1 Comment

works with Vue.js v2.6.8
1

Before using v-html, you have to make sure that the element which you escape is sanitized in case you allow user input, otherwise you expose your app to xss vulnerabilities.

More info here: https://v2.vuejs.org/v2/guide/security.html

I highly encourage you that instead of using v-html to use this npm package

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.