2

Assume I have a method in a Vue.js component that returns a string to be rendered onto the page:

display: (arg) => {
    return arg.name
}

And in the relevant HTML:

<div html="component.display(arg)">
</div>

This has worked fine for me until now, but now I want to return HTML with some Vue-bound data on it:

display: (arg) => {
    return '<button @click="myMethod(arg)">Click</button>'
}

Obviously, the above doesn't work. My research has led me to believe that the correct approach here would be to create a component and return it, but I just can't seem to get it working. How would I approach this problem?

1
  • Your question is very confusing without knowing 1) What arg is and where it is defined. 2) What component is. 3) Where myMethod is defined Commented Nov 21, 2018 at 5:23

3 Answers 3

5

I think what you're after is a dynamic component.

I would use a computed property to return the component definition to take advantage of Vue's reactivity (methods run all the time, computed properties only when required)

<component :is="display" :arg="arg" @click="myMethod"></component>

and...

computed: {
  display () {
    // you weren't clear on the conditions
    // that should cause this to return something different
    // but here is where you would put them
    return {
      props: ['arg'],
      template: `<button @click="$emit('click', arg)">Click</button>`
    }
  }
}

I'm assuming here that myMethod is defined in the parent, hence adding the @click handler on <component> and $emit in the child.


I suppose you could use a method to return the component definition but that feels like it would be quite inefficient and there's probably a better way to do it.

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

1 Comment

This is way better than mine.
2

Seems like you could make that button its own component.

// New component
Vue.component('arg-button', {
  props: ['arg'],
  data: function () {
    return {
      arg: null
    }
  },
  myMethod: function(arg) {
    console.log(arg)
  },
  template: `
    <button 
      @click="myMethod(arg)">
        Click
    </button>`
})

// Old component
Vue.component('parent', {
  data: function () {
    return {
      arg: null,
      displayIfArg: true
    }
  },
  template: `
    <arg-button 
      v-show="displayIfArg"
      :arg="arg">
    </arg-button>`

})

Your overall approach is what Vue solves without returning functions-as-strings like that. There's a couple of ways to do it The Vue Way, but it roughly involves conditional instantiation/display of components—which should be readily reusable anyway, so thinking you need to base your return on arg itself is likely more hassle than it's worth.

Components should above all be reusable and atomic. Read their docs, esp. on components, it'll shed a lot of light.

1 Comment

That's a fantastic explanation after your code. Hope it helps OP see things the "Vue way"
1

If you want to write a function that will return a component and be able to use vue-bound data but do not want to make that into a separate file, then you can look into render functions in vue

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.