0

I am writing a page using Vue.js and am attempting some custom components. I've started with a very simple one:

Vue.component('single-field', {
    template: '<b>{{ key }}:</b> {{ value }}',
    props: ['key', 'value']
});

This works fine on its own: it is intended to take two values and return them in a key: value format. Initially, when I was passing the value as an element from the Vue data object (specifically, pickup.dateTime it wasn't working. It's easier to show than explain:

<div id="app">
    <single-field key="Date & Time" value="pickup.dateTime"></single-field>
</div>

I was able to fix this by binding the value (notice the colon by value):

<single-field key="Date & Time" :value="pickup.dateTime"></single-field>

I then wrote a second component which is designed to take an object and a title and return each element of the object as a set of <single-field> components, with a title above them. Here is what I wrote:

Vue.component('field-block', {
    template: '<h2>{{title}}</h2>\
               <div v-for="(p-key, p-value) in parent">\
                   <single-field key="p-key" value="p-value"></single-field>\
               </div>',
    props: ['parent', 'title']
});

Now, I think there must be something wrong with the way I am binding (or not binding?) which is causing the data to be displayed in a strange way. Here is my HTML:

<div id="app">
    <single-field key="DateTime" :value="pickup.dateTime"></single-field>
    <single-field key="Name" :value="pickup.name"></single-field>
    <field-block title="Address" :parent="pickup.address"></field-block>
</div>

The field pickup.address is an object, so I was hoping that the component would iterate through the elements and return them as single fields, but what it's currently doing is just returning the variable names, like p-key: p-value. I tried doing a bind on both of them in the component definition (on both because they are now both variables being passed whereas previously I was using a static string for the key field):

<div v-for="(p-key, p-value) in parent">
    <single-field :key="p-key" :value="p-value"></single-field>
</div>

But what this returns is NaN: NaN, and I can't figure out why it would do that. I don't fully understand the bind operation, but I expect that it only binds to data in the data option when defining the view, which is not where p-key and p-value are defined. How would I get the variables to 'carry through' from the outer component to the inner ones? Thanks.

2
  • 2
    Beware, as 'key' is a reserved property name: vuejs.org/v2/guide/list.html#key Commented Jun 1, 2017 at 8:11
  • Thanks for the heads up - I've adjusted my code to replace all instances of key with s-key. The behaviour is the same, but thank you for saving me potential trouble down the line. Commented Jun 1, 2017 at 8:16

1 Answer 1

2

Okay this one was tricky.

Several problems with your code: Your components should have only one root element. So pack your components into a <div>.

Then, - is not a valid character to put into a javascript variable name. So you can't write (p-key, p-value) in parent, write something else, like (pKey, pValue) in parent.

On the other hand, html properties are not case-sensitive, so you should actually write key-name (for example) instead of keyName, but only for the property names. This limitation does apply only in your html files (not in your string templates).

Finally, here is a working js-fiddle.

https://jsfiddle.net/6juwLd3b/

Additionally, I would advise you that you look at your console while developing. Many error where displayed that could have lead you to a working version.

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

2 Comments

Thanks very much, that's fixed it! Honestly though, using Chrome, not a single error in the console. Where were you looking to find them?
Yeah, chrome as well. That's strange, as Vue should have notified you at least about the single root element problem (except if you are using Vue1, where it's not required).

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.