DavidBrown
DavidBrown

Reputation: 192

Vue.js Dynamic Values in Component

I'm building a decoupled application with Vue.js, consuming data from WordPress' Rest API. The application includes a sort by category feature. I can't use vanilla form inputs to accomplish this and still match the design, to I need to use a Vue component to list the categories. The issue I have is that I can't populate the name of the category in the component's template.

The component code:

Vue.component( 'sort-button', {
        props: ['value'],
        template: `
          <button class="button button-accent"
            v-bind:value="value"               
            v-on:input="$emit( 'input', $event.target.value )"
          >
          <a href="#">{{ cat.name }}</a>
        `
    }
);

I'm displaying this as in-DOM template, like so:

<sort-button v-for="cat in portfolioCats"></sort-button>

This loops through each category and gives me a corresponding button if I leave the a tag contents of the template static or blank. However, if I use the {{ cat.name }} mustache, it errors because cat is not defined.

My question: How can I make the template aware of cat in the context of the for loop? Note that I would like for this to be a re-usable component that I can plugin into other Vue instances within the site.

Thanks!

Upvotes: 1

Views: 4164

Answers (3)

Roy J
Roy J

Reputation: 43899

cat is not defined in the component. You need a prop for it, and you also need to supply the value for value.

<sort-button v-for="cat in portfolioCats" :name="cat.name" :value="cat.value"></sort-button>

So your template should be

Vue.component( 'sort-button', {
    props: ['value', 'name'],
    template: `
      <button class="button button-accent"
        v-bind:value="value"               
        v-on:input="$emit( 'input', $event.target.value )"
      >
      <a href="#">{{ name }}</a>
    `
});

Also, buttons don't typically have input events, so it's not clear what you're expecting to happen there. Possibly you want a click event.

Just noticed you aren't closing your <button> tag, too. It's odd to put an anchor inside a button; maybe you want the button to close before the anchor.

Upvotes: 2

Phil
Phil

Reputation: 164960

One option would be to use a slot so you can define the content from the parent context. For example

<button class="button button-accent"
        :value="value"               
        @input="$emit( 'input', $event.target.value )">
  <slot></slot>
</button>

and in the parent...

<sort-button v-for="cat in portfolioCats" v-model="something" :key="cat.id">
  <a href="#">{{ cat.name }}</a>
</sort-button>

Upvotes: 0

You need to pass the variable cat as a prop.

<sort-button v-for="cat in portfolioCats" :cat="cat"></sort-button>

And add it to the props array.

props: ['value', 'cat']

Upvotes: 3

Related Questions