6

I have strings that contains ### and I am replacing with array values. Now I want to use them with a component, I created the component and it works but I don't know how to use it in the strings. I don't want to wrap them manually because I don't know how the strings will be, it can have several ###. If it has 2 ###, options will have 2 subArrays.

What is the better way to do it?

Code: https://jsfiddle.net/tsobh4nu/

Vue.component('opt', {
  template: `<label>
                <span class="bold" v-for="(str,idx) in options">
                     {{str + " / "}}
                </span>
             </label>`,
  props:{options: Array}
})

new Vue({
  el: '#app',
  data: {
    str: "I have ### and you have a ###.",
      options: [
        ['AAA', 'BBB', 'CCC'],
        ['XXX', 'YYY', 'ZZZ']
      ]
  },
  computed:{
  	replacedStr(){
    	let newStr = this.str;
      this.options.forEach(option=>{
      	newStr = newStr.replace('###',this.concatenateOptions(option));
      })
      return newStr;
    }
  },
  methods: {
    concatenateOptions(strArr) {
      let separator = "";
      let strOptions = "";
      strArr.forEach(word => {
        strOptions += separator  + word;
        separator = " / ";
      });
      return strOptions;
    }
  }
})
.bold {
  font-weight: bold
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
  <p>I want something like this, but using components: </p>
  {{replacedStr}}
  <br>
  <hr>
  My Components:<br>
  <opt :options="options[0]"></opt>
  <br>
  <opt :options="options[1]"></opt>
</div>

Many thanks.

2
  • Is ### the name of the component? If so, you can use dynamic components. Commented Nov 12, 2018 at 7:05
  • no, it's where I'm going to replace the component. I saw that example and I think it's different. They know where to put <component v-bind:is="currentTabComponent"></component>. In my case I don't know, It's more dynamic. Commented Nov 12, 2018 at 13:51

2 Answers 2

8

This is more general, but I hope it will help someone. Add a dynamic component in your template: <component v-bind:is="processedHtml"></component>.

Then add a computed method:

computed: {
    processedHtml () {
        let html = this.html.replace('[Placeholder]', '<my-component></my-component>');
        return {
            template: '<div>' + html + '</div>'
        }
     }
}

Where <my-component> is your custom component and the this.html is your HTML content that contains the placeholder [Placeholder].

It is important to return an element that has one root node. That's why the return is wrapped with <div>.

Read more advanced tutorial about this issue here in my blog. For example, to pass props to <my-component>

Sign up to request clarification or add additional context in comments.

1 Comment

I've been unsuccessful in using arbitrary html in v-bind:is. The documentation says that you can only use the name of a component or a components option object. vuejs.org/v2/guide/components.html#Dynamic-Components What version of vue are you using?
-1

I just experienced the same issue. I had an element that needed to display the current count of an item. The current count came from the store and was constantly changing. I used v-text. I know this is pretty situation specific, but hopefully it helps someone down the line.

<P id="results_count" v-text="current_count"></P> 

and in the data portion of the component I had a property named current_count that was updated via methods.

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.