1

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!

3 Answers 3

3

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']
Sign up to request clarification or add additional context in comments.

2 Comments

+1. Another approach would also be slots, if you want to manage data at the parent instead of passing it down.
Works perfectly. Thanks for the response!
2

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.

1 Comment

button elements can contain a tags as phrasing content: developer.mozilla.org/en-US/docs/Web/Guide/HTML/…
0

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>

Comments

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.