Lim Socheat
Lim Socheat

Reputation: 715

VueJS render property inside html string using v-html

Editor Content

I have a string of html where I get from Editor and stored in the database.

<h3><a href="#" rel="noopener noreferrer nofollow"><em><strong>Profile Of User:</strong></em></a></h3><p></p><p>{{user}}</p>

I want to retrieve it from the database and render it as HTML. when I use v-html, it will be rendered as:

<v-card-text v-html="content"></v-card-text>

Profile Of User:

{{user}}

How to render {{hello}} from data property if I have data property like this:

data() {
        return {
            user: "Lim Socheat",
            content:"<h3><a href="#" rel="noopener noreferrer nofollow"><em><strong>Profile Of User:</strong></em></a></h3><p></p><p>{{user}}</p>"
        };
    },

Expected Result:

Profile Of User:

Lim Socheat

because {{ user }} will be rendered as Lim Socheat

Upvotes: 3

Views: 4590

Answers (3)

Raj Omer Mustafa
Raj Omer Mustafa

Reputation: 149

you can achieve the same functionality using Vue Dynamic Components instead of v-html because for v-html you have to parse variable with in string using regex as explained by @Lim Socheat and @Vijay Joshi. but with Vue Dynamic Components you can pass variables from parent to child component. Hope this will help
I am defining a component in computed with data and Passing data from Parent Component to Child component.

<template>
    <v-container>
        <v-card>
            <v-card-title>Print</v-card-title>
            <v-divider></v-divider>
            <v-card-text>
                <component :is="dynamicComponent"></component>
            </v-card-text>
        </v-card>
    </v-container>
</template>

<script>
import { reactive, shallowRef, ref } from 'vue'
export default {
    data() {
        return {
            hello: "HELLO DATA",
            user: "Lim Socheat",
            content: shallowRef(null)
        };
    },

    methods: {
        getLayout() {
            this.$axios
                .$get("/api/layout/reciept", {
                    params: {
                        type: "reciept"
                    }
                })
                .then(response => {
                    this.content = response.content;
                })
                .catch(error => {
                    this.$toast.error(error);
                });
        },
    },

    computed: {
        id() {
            return this.$route.params.id;
        },
        dynamicComponent() {
            let $this = this;
            return {
                data: function () {
                    return {
                        hello: ref($this.hello),
                        user: ref($this.user),
                    }
                },
                template: $this.content ? $this.content : "loading..."
            };
        }
    },

    watch: {
        id: {
            handler() {
                this.getLayout();
            },
            immediate: true
        }
    }
};
</script>

Upvotes: 0

Lim Socheat
Lim Socheat

Reputation: 715

I found the answer. hope it helps someone in the future.

Orginal post: https://forum.vuejs.org/t/evaluate-string-as-vuejs-on-vuejs2-x/20392/2

VueJS - Interpolate a string within a string

 <template>
        <v-container>
            <v-card>
                <v-card-title>Print</v-card-title>
                <v-divider></v-divider>
                <v-card-text v-html="parse(content)"></v-card-text>
            </v-card>
        </v-container>
    </template>

    <script>
    export default {
        data() {
            return {
                hello: "HELLO DATA",
                user: "Lim Socheat",
                content: ""
            };
        },

        methods: {
            getLayout() {
                this.$axios
                    .$get("/api/layout/reciept", {
                        params: {
                            type: "reciept"
                        }
                    })
                    .then(response => {
                        this.content = response.content;
                    })
                    .catch(error => {
                        this.$toast.error(error);
                    });
            },

            evalInContext(string) {
                try {
                    return eval("this." + string);
                } catch (error) {
                    try {
                        return eval(string);
                    } catch (errorWithoutThis) {
                        console.warn(
                            "Error en script: " + string,
                            errorWithoutThis
                        );
                        return null;
                    }
                }
            },
            parse(string) {
                return string.replace(/{{.*?}}/g, match => {
                    var expression = match.slice(2, -2);

                    return this.evalInContext(expression);
                });
            }
        },

        computed: {
            id() {
                return this.$route.params.id;
            }
        },

        watch: {
            id: {
                handler() {
                    this.getLayout();
                },
                immediate: true
            }
        }
    };
    </script>

Upvotes: 1

Vijay Joshi
Vijay Joshi

Reputation: 959

Make content a computed property. And then use it like this:

  computed: {
    content() {
       return '<h3><a href="#" rel="noopener noreferrer nofollow"><em><strong>Profile Of User:</strong></em></a></h3><p></p><p>' + this.user + '</p>';
    }
  }

You can use all variables defined in data in this way.

Update: Since OP is getting the HTML string from backend, they need to replace the variables in this case. We have kept a map of all variables that might come and then we are creating a Regex dynamically to replace the said key from code.

  computed: {
    content() {
      // keep a map of all your variables
      let valueMap = {
        user: this.user,
        otherKey: 250
      };
      let value = '<h3><a href="#" rel="noopener noreferrer nofollow"><em><strong>Profile Of User:</strong></em></a></h3><p></p><p>{{user}}</p>';
      let allKeys = Object.keys(valueMap);
      allKeys.forEach((key) => {
        var myRegExp = new RegExp('{{' + key + '}}','i');
        value = value.replace(myRegExp, valueMap[key]);
      });
      return value;
    }
  }

Upvotes: 6

Related Questions