273

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>
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Mike
  • 5,416
  • 4
  • 40
  • 73
  • 1
    doing unescaped HTML for line-breaks is overkill, just wanted to mention that! it's a big security risk – Ryan Taylor Mar 11 '19 at 19:28
  • 1
    @RyanTaylor why is it a big security risk? – iiirxs Jan 18 '21 at 12:12
  • @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 – Ryan Taylor Feb 14 '21 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? – iiirxs Feb 18 '21 at 10:42

6 Answers6

362

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

<td v-html="desc"></td>
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
王开朗
  • 3,791
  • 2
  • 10
  • 6
  • 3
    That one actually works in vue2. First one trows on compile. – Yauheni Prakopchyk Sep 14 '16 at 21:28
  • 1
    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 – Zum Dummi Apr 14 '19 at 11:21
  • Try slicing the variable – PiggyPlex Aug 14 '20 at 11:34
  • 2
    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: https://vuejs.org/v2/guide/security.html – LastM4N Jan 13 '21 at 10:41
233

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 goes 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.

tony19
  • 125,647
  • 18
  • 229
  • 307
thewhitetulip
  • 3,235
  • 3
  • 21
  • 26
97

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.

tony19
  • 125,647
  • 18
  • 229
  • 307
zeratulmdq
  • 1,484
  • 16
  • 15
  • 70
    Please note that in vue 2.0 the triple moustache [has been deprecated](https://github.com/vuejs/vue/issues/2873) you should [use v-html](http://vuejs.org/api/#v-html) instead. – hitautodestruct Aug 23 '16 at 12:52
  • 3
    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. – Илья Зеленько Aug 03 '20 at 13:30
  • 1
    @ИльяЗеленько really must agree with you on this. Particularly true if you are trying to feed text content as a ... you must create a new element – Jonathan Sep 23 '20 at 11:25
11

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

<div v-html="html content data property"></div>
Shair Haider
  • 123
  • 1
  • 6
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

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

tony19
  • 125,647
  • 18
  • 229
  • 307
LastM4N
  • 1,890
  • 1
  • 16
  • 22