0

I am new to Vue and after checking the docs I can not figure out how to achieve the following:

  • pass an arbitrarily named variable as a prop to a component instance.

From my understanding, props are meant to be a way to allow data to be passed to a component and as it states on the website:

Passing Data to Child Components with Props: Props are custom attributes you can register on a component. When a value is passed to a prop attribute, it becomes a property on that component instance.

Since props can be required, it would seem that we can design components under the assumption that some data would be there, and possible within certain parameters (if the validator option is specified).

So I would like to define a function or object outside of vue, e.g. in an application, and pass this function or object to my vue instance.

This works if my named object of function has the exact same name as the prop to which I attempt to bind it. However, as I might have multiple instances of the Vue component and I might want to bind different data, I find using the same name for the variable less than ideal.

Now if I do as the Vue warning suggests, and name object / function the same as the prop, then the warning switches to that my data is not defined inside vue and to make sure it is reactive by reading: https://v2.vuejs.org/v2/guide/components-props.html

which, to be honest, doesnt really explain how to solve the issue,

or move the prop to the data level.

Which I can do (still gives the same warning), but kind of defeats the purpose of having props with my understanding of Vue.

This become more frustrating with anonymous vue instances.

e.g.

<script>
export default {
  props: {
    // records: {
    //   default: function(){return{}},
    //   type: Object
    // }
  },
  data: function() {
    return {
      records: {} // define even an empty value in data for it to be 'reactive'
    }
  },
  computed: {
    fields: function() {

    },
    keys: function() {
      return Object.keys(this.records)
    }
  },
  methods: {

  }
}
</script>

trying to use this as a component and set records to var myRecords = {"a": {}} fails:

<my-comp :records="myRecords"/>

So how exactly should I circumvent this? Where should I define my data then? and how should I handle the naming in the case of multiple instances?

A more fledged on example is found on a similar question:

Vue2: passing function as prop triggers warning that prop is already set

4
  • where do you define your data now? Commented Jun 14, 2018 at 12:11
  • @ippi currently I am just defining it in a script tag in the body of the html prior to the vue instance. However, it is conceivable that it would come as the response of an XMLHttpRequest or something similar Commented Jun 14, 2018 at 12:13
  • Well then, since for example <component :data="{x:1}"></component> actually does work and since this looks like a component, I'll assume you need to pass the data in to the parent (which also can have props) and then pass it along to the component in props, once more. Commented Jun 14, 2018 at 12:21
  • @ippi, I am not sure that I follow. I started using Vue a few days ago. This component, is the root Commented Jun 14, 2018 at 12:26

1 Answer 1

1

So I would like to define a function or object outside of vue, e.g. in an application, and pass this function or object to my vue instance.

It's hard to give a definitive answer because I don't know the specifics of how you have organized your code. Are you using Webpack? Single file components (.vue)? If yes to any of these, then you needn't use global variables in the way you have described in your question.

Your entire Vue app should consist of a single root Vue instance (which you instantiate with new Vue(...), and from there each component is rendered within the root component's template, and templates of those components, and so on.

Looking at the following template:

<my-comp :records="myRecords"/>

myRecords must be a property on the Vue component instance whose template contains the above. It could be declared within the data block, or as a computed property, or a prop, it doesn't matter.

Here's a small example:

<div id="app">
  <my-comp :records="myRecords"></my-comp>
</div>
// Obtain records in some way and store it in a global variable
var records = ...

// This is the root Vue instance
new Vue({
  el: '#app',
  data: {
    // You must store the records array in the Vue component like this
    // for it to be referenced within the template.
    // You can optionally transform the data first if you want.
    myRecords: records.filter(r => r.name.startsWith('Bob'))
    // ^        ^
    // |        |
    // |        +--- the global variable
    // |
    // +---- the name of the property on the component instance
  }
})

Note that MyComp component does not access the records global variable in any way, it only takes its input through the records prop.

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

6 Comments

foremost thank you very much for the detailed answer. I am using single file components via rollup. I guess my confusion is in not understanding then how to best use components defined in a single file component. Is it possible to, however, to use global variables? The way that you solve the issue works, but means that if I want the same app with different data, and maybe some other different structure, I have to change more code.
I'm not sure where exactly you would have to change lots of the code. You would not need to change any of MyComp's code at least, since it doesn't access any global variables. Using global variables often leads to spaghetti code which is hard to maintain and reason about the source of the data, which is why global variables are often not used like this. For small apps it's OK.
Yea, internally there are no globals. I mean, suppose I want three instances, from using data from 3 different apis. Is it cleaner (I honestly do not know) to have the vue tags defined in the html and a file for the vue component, and then have the apis called elsewhere async for each of these instances? Basically, I do not want to dynamically create new vue instances because there is html rendered even when there is no data provided. Nor, do I want to pass around vue instances as a parameter to whatever functions need to pass data in as a prop.
How are you using this API? Is it a REST API that you can request via XMLHttpRequest/fetch entirely on the client, or are the HTML pages being rendered server-side? If the former, the best way would be to create a single file component for your app which fetches the data from the API (perhaps in the created hook) and stores the result on itself, which is then fed to other components via props as usual.
They are REST APIs, but the data can take a while, hence why I would want it to be async... I guess I will cross that bridge when I get there. Your answer is more than enough to let me prototype the components I need. I'll make as an answer in a bit to let some others chime in if they have other ideas. +1 for all the assistance :)
|

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.