Vue: Can I pass propsData to dynamic component in template

Created on 6 Jul 2016  Â·  6Comments  Â·  Source: vuejs/vue

when I render form.jade from columns.json , I try to pass propsData(multi props) to component , but It seems unsupported. Is there a better way to do this?

json

[
  {"title": "A", "name":"a",  "component": "ui-dropdown" , "propsData": {"options": [], "on":"hover" }},
  {"title": "B", "name":"b",  "component": "ui-dropdown" , "propsData": {"options": [] , "on":"click"}},
]

template :

.ui.segment.form.bottom.attached
    .field(v-for="column in columns")
        label {{column.title}}
        component(:is="column.component",
                           :propsData="column.propsData", 
                           :value.sync="editor[column.name]")

Of course , there is a way to pass props one by one , but it seems not so good.

.ui.segment.form.bottom.attached
    .field(v-for="column in columns")
        label {{column.title}}
        component(:is="column.component", 
                           :options="column.propsData.options", 
                           :on="column.propsData.on", 
                            :value.sync="editor[column.name]")

Most helpful comment

[UPDATE] The directive is not that ok in some situation , I have wrote a better solution component-proxy

import _ from 'lodash'
import Vue from 'vue'


export default {
  props: ['name', 'props', 'value'],
  template:  '',
  created(){
    let props = []
    if(this.props ){
      // apply properties to component data
      _.forOwn(this.props, (value, key)=>{
        // console.debug( key,  this[key])
        props.push(`:${_.kebabCase(key)}="props['${key}']"`)
      })
    }

    // console.debug('component proxy', props.join(' '))
    this.$options.template = `<component :is="name" ${props.join(' ')} :value.sync="value"></component>`
  },
}




@fnlctrl , tks for your reply. I have wrote a directive to do this and really appreciate vue would add this feature in the future:

directives: {
    props(props){
      let comp = this.vm.$children[this.vm.$children.length - 1];
      if(props && comp){
        // apply properties to component data
        _.forOwn(props, (value, key)=>{
          comp[key] = value
        })
      }
    }
  }

template:

.ui.segment.form.bottom.attached
    .field(v-for="column in columns")
        label {{column.title}}
        component(:is="column.component",
                           v-props="column.propsData", 
                           :value.sync="editor[column.name]")

All 6 comments

You misunderstood what are propsData for: http://vuejs.org/api/#propsData
You can actually pass and object to the v-bind directive. It looks like what you're trying to do:http://vuejs.org/api/#v-bind

I was excited when I read http://vuejs.org/api/#v-bind.
But I failed when I tried and I found this: https://github.com/vuejs/vue/issues/2114 and this issue provides code: http://jsbin.com/yudivokovi/edit?html,js,output

v-bind only binds attributes, it doesn't pass props. So I guess you have to pass each prop explicitly.

[UPDATE] The directive is not that ok in some situation , I have wrote a better solution component-proxy

import _ from 'lodash'
import Vue from 'vue'


export default {
  props: ['name', 'props', 'value'],
  template:  '',
  created(){
    let props = []
    if(this.props ){
      // apply properties to component data
      _.forOwn(this.props, (value, key)=>{
        // console.debug( key,  this[key])
        props.push(`:${_.kebabCase(key)}="props['${key}']"`)
      })
    }

    // console.debug('component proxy', props.join(' '))
    this.$options.template = `<component :is="name" ${props.join(' ')} :value.sync="value"></component>`
  },
}




@fnlctrl , tks for your reply. I have wrote a directive to do this and really appreciate vue would add this feature in the future:

directives: {
    props(props){
      let comp = this.vm.$children[this.vm.$children.length - 1];
      if(props && comp){
        // apply properties to component data
        _.forOwn(props, (value, key)=>{
          comp[key] = value
        })
      }
    }
  }

template:

.ui.segment.form.bottom.attached
    .field(v-for="column in columns")
        label {{column.title}}
        component(:is="column.component",
                           v-props="column.propsData", 
                           :value.sync="editor[column.name]")

I have the same problem! @terrydai - this is good solution. I try it now.
For now I manually create new instances and mount them in particular element like this
new MyComponent({el: '#id', propsData: {...}})

@fnlctrl You're right.
Sorry for misleading you @terrydai
Marking this as duplicate of #2114

Was this page helpful?
0 / 5 - 0 ratings

Related issues

robertleeplummerjr picture robertleeplummerjr  Â·  3Comments

paceband picture paceband  Â·  3Comments

lmnsg picture lmnsg  Â·  3Comments

finico picture finico  Â·  3Comments

loki0609 picture loki0609  Â·  3Comments