question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

A way to programmatically pass props and args to a new Vue instance and keep it updated

See original GitHub issue

What problem does this feature solve?

I am trying to integrate Vue with Meteor Blaze and am working on rendering of Vue components from Blaze templates. I would like to programmatically create an Vue instance (new Vue(...)) and pass it props and args which would be equivalent to doing <vue-component :prop="propValue" :arg="argValue">. So an object of key/values which would then be mapped to props, if keys are among props, or be set as element attributes otherwise. But the important part is to also be able to update all of them afterwards. So if any of the props or args change, allowing to call a function to update them would be great.

What does the proposed API look like?

I propose that propData could be a function. So that I could provide a reactive function which would be used to populate both props and args (so any keys returned from the function which are not props would become args).

Alternatively. we could have vm.$propsUpdate function which I could run to update props and args in a more imperative way.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:7
  • Comments:19 (18 by maintainers)

github_iconTop GitHub Comments

8reactions
mitarcommented, Jul 19, 2017

No worries. I know it is sometimes hard to communicate online and also understand what all is the background. I have not asked anything on the forum because I think I have good enough grasp of Vue code (I have read through it) and what is currently possible, so I didn’t feel that there are some questions I would need an answer to. But of course maybe I missed something.

(I have issues using the forum because when I try to login, I get “You can’t log in as mitar from that IP address,” but that is a different issue.)

So, I am working on Blaze integration with Vue. Current code is here. What this issue relates to is how I could create a nice API to render Vue components from Blaze templates. Ideally, I wanted to support something like the following syntax:

{{> VueComponent component="my-vue-component" prop="propValue" arg="argValue"}}

What Blaze does is puts all the arguments into an object and passes it on to the code which would include Vue. If any of the values reactively change, code is rerun with new object with new value, which allows one to push those updated values to Vue component’s instance. Now, there are two questions:

  • how to know which of the values are props and which are args, and should I (as somebody using the code to push new values to the instance) even care, and should the developer using the above syntax care (they do not have to care when using <vue-component :prop="propValue" :arg="argValue">)
  • how should I push these new values, given that I am getting a new object with new values

One approach would be that I ask the developer to specify which are props and which are args, by asking them to pass only to arguments, something like:

{{> VueComponent component="my-vue-component" props=props args=args}}

But I would prefer that developer does not have to do so.

I have tried two approaches. One with wrapping component, and one without. With wrapping component, code is something like (if data is the object above).

const vm = new Vue({
  el,
  render: (createElement) => {
    return createElement(Vue.component(data.component), {props: filterProps(data), attrs: filterAttrs(data)});
  }
});

This works, but has two issues:

  • how do I know what are props and what are attrs, I could inspect component’s options and figure that out manually, but that would require me to duplicate the code which already existing in Vue, so it would be great if I could just pass an object of all of them and Vue figures this out
  • how to update those props or attrs once they change, without recreating the whole component (maybe component keeps important state, or is a form which should not loose existing user input)

I tried something like:

_.each(_.keys(vm.$children[0]._props || {}), (key, i) => {
  vm.$children[0]._props[key] = filterProps(data)[key];
});

But this throws a warning, because one should not be changing non-root props directly. Moreover, I have no idea how to change attributes in a similar way.

A second approach I tried is to do:

const propsData = filterProps(data);
const component = Vue.component(data.component);
const vm = new component({
  el,
  propsData,
});

And then when I want to update props, I do:

_.each(_.keys(vm._props || {}), (key, i) => {
  vm._props[key] = filterProps(data)[key];
});

Now it works. Alternatively, I suspect, I could just be setting values on propsData object directly and it might propagate by Vue. I have not yet tried this, because the issue with this approach is that I do not know how to pass attrs. And again, I have to manually filter props and attrs.

So, while working on this, I wondered why there is no API which would match the template API, where I can do <vue-component :prop="propValue" :arg="argValue"> and Vue figures out which one is prop and which one is attr.

Maybe instead of propsData we could have propsAndAttrsData and that Vue would split them as needed. And then or augment the object to detect changes to it (observe), or provide vm.$updatePropsAndAttrs method.

So I think all this is doable without help by Vue. But my issue is that I think it should be simpler to do. Maybe I am complicating here though and there is easier way to do it.

0reactions
jbmikkcommented, Mar 2, 2020

I was wondering how to set the props of a component on the beforeRouteEnter router guard. So I guess there is no official way of setting props programmatically?

I am using router guards to resolve some data and pass it down to the components if everything goes well.

Right now I’m using setter methods on the component to set inputs that would otherwise have been props. This seems a bit clumsy if you ask me, particularly when trying to reuse components.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Passing props dynamically to dynamic component in VueJS
To pass props dynamically, you can add the v-bind directive to your dynamic component and pass an object containing your prop names and ......
Read more >
Props | Vue.js
All props form a one-way-down binding between the child property and the parent one: when the parent property updates, it will flow down...
Read more >
Creating Vue.js Component Instances Programmatically
This article aims to illustrate how different aspects of using components in a template, such as instantiation, props passing, slots, ...
Read more >
How To Pass Data Between Components In Vue.js
Let's analyze three of the most common ways to pass data in VueJS. ... VueJS props are the simplest way to share data...
Read more >
Routing in Vue3: Navigating the Options - CODE Magazine
Shawn Wildermuth demonstrates how to use Vue Routing in a single page ... here is to have the parameters passed to the component...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found