Home > Blockchain >  how to wrap a component content with html tag dynamically in vue
how to wrap a component content with html tag dynamically in vue

Time:10-21

Hi i want to wrap the content of a component with some specific html tag let say button for this example.

i have a function which dynamically returns a value which i use as a prop, based on that i want to wrap the content of a component.

i know i could have achieved this way too <button><compA/></button> it does not solve my problem beacuse i need to change it in 100 places.

My expected result:

  1. <button><div>press me i'm button</div></button>
  2. <div>don't wrap me with button leave me as it is</div>

Note: :wrappwithbutton="" having true for 1st usage and false for 2nd usage

const localComponent = {
     name:'first-comp',
     template:`<div> {{text}}</div>`,
     props:['wrappwithbutton','text'],
}



const app = new Vue({
   el:'#app',
   name:'app',
  components:{'first-comp':localComponent},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>


  <div id="app">

    <first-comp :wrappwithbutton="true" text="press me i'm button"></first-comp>
    
    <br/>
    <hr/>
    <br/>
    
       <first-comp :wrappwithbutton="false" text="don't wrap me with button leave me as it is"></first-comp>

 </div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

This is a perfect example for render functions. Instead of using a template you can use a render function to render the template for you. Read more about render functions

const localComponent = {
 name:'first-comp',
 props:['wrappwithbutton', 'text'],
 methods: {
   btnClick() {
     if (this.wrappwithbutton) console.log('button')
   }
 },
 render(h) {
   return h(this.wrappwithbutton ? 'button' : 'div', [
     h('div', this.text)
   ])
 }
}

const app = new Vue({
  el:'#app',
  name:'app',
  components:{'first-comp':localComponent},
});

Vue.config.productionTip = false
Vue.config.devtools = false

You can even go a step further and make your localComponent to be more dynamic with the parent passing a prop with the tag that should be rendered:

const localComponent = {
 name:'first-comp',
 props:['tag', 'text'],
 methods: {
   btnClick() {
     if (this.wrappwithbutton) console.log('button')
   }
 },
 render(h) {
   return h(this.tag, [
     h('div', this.text)
   ])
 }
}

If you would like to have a single div and not two divs you can do:

render(h) {
   if (this.tag === 'div') {
     return ('div', this.text);
   }

   return h(this.tag ? 'button' : 'div', [
     h('div', this.text)
   ])
}

CodePudding user response:

This is my idea, but I think the template should have a more concise way of writing

const localComponent = {
  name: "first-comp",
  template: `
    <template v-if="wrappwithbutton">
      <button>
        <div> {{text}}</div>
      </button>
    </template>
    <template v-else>
      <div> {{text}}</div>
    </template>
  `,
  props: ["wrappwithbutton", "text"]
};

const app = new Vue({
  el: "#app",
  name: "app",
  components: { "first-comp": localComponent }
});

CodePudding user response:

You can try to focus on functionality rather then tags:

const localComponent = {
 name:'first-comp',
 template:`<div 
             :
             @click="btnClick"
           > 
             {{text}}
           </div>`,
 props:['wrappwithbutton','text'],
 methods: {
   btnClick() {
     if (this.wrappwithbutton) console.log('button')
   }
 }
}

const app = new Vue({
  el:'#app',
  name:'app',
  components:{'first-comp':localComponent},
});

Vue.config.productionTip = false
Vue.config.devtools = false
.btn {
  border: 1px solid violet;
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
  <div id="app">
    <first-comp :wrappwithbutton="true" text="press me i'm button"></first-comp>
    <br/>
    <hr/>
    <br/>
    <first-comp :wrappwithbutton="false" text="don't wrap me with button leave me as it is"></first-comp>

 </div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related