1

Currently, I'm working with Vue v2.x.x. I have an array:

sectionTitles = ['Technology', 'Data', 'Poverty and Research', ...]

and I have jobsData that looks like this:

[{'title': 'Software Engineer', mainTag: 'Data', ...}...]

I want to display <li> in an <ul> when the sectionTitle matches the job.mainTag.

I was reading in the Vue docs that you shouldn't combine v-if with v-for, so I created a computed method to be able to filter the jobs. Here is what I did so far:

window.onload = function () {
    var app = new Vue({
    delimiters: ['${', '}'],
    el: '#app',
    data: {
      jobs: jobsData,
      sectionTitles: ['Data','Poverty Research Unit', 'Technology']
    },
    computed: {
      matchingTitles: function (sectionTitle) {
        return this.jobs.filter(function (job, sectionTitle) {
          job.mainTag === sectionTitle;
        })
      }
    }
  })
}
<div id="app">
  <template v-for="title in sectionTitles">
    <h4 class="h3">{{ title }}</h4>
    <ul class="list-none p-0 color-mid-background" id="jobs-list">
      <li class="py-1 px-2" v-for="job in matchingTitles(title)">
        <a :href="`${job.url}`">
          ${job.title}
        </a>
      </li>
    </ul>
  </template>
</div>

So basically I want to only display <li> when the sectionTitle (for example Data) matches the job.mainTag. How can I go about achieving this in Vue?

1
  • computed methods don't take parameters Commented Feb 19, 2020 at 16:32

2 Answers 2

2

Change your computed method to just a method. Then change your filter to return a value. Also for displaying in Vue you want to use {{....}} not ${...}

new Vue({
  el: '#app',
    data: {
      jobs: [{'title': 'Software Engineer', mainTag: 'Data'}],
      sectionTitles: ['Data','Poverty Research Unit', 'Technology']
    },
    methods: {
      matchingTitles: function (sectionTitle) {
        return this.jobs.filter ((job)=>{
          return job.mainTag === sectionTitle;
        })
      }
    }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <template v-for="title in sectionTitles">
    <h4 class="h3">{{ title }}</h4>
    <ul class="list-none p-0 color-mid-background" id="jobs-list">
      <li class="py-1 px-2" v-for="job in matchingTitles(title)">
        <a :href="job.url">
          {{job.title}}
        </a>
      </li>
    </ul>
  </template>
</div>

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

2 Comments

I changed the delimeters becaused the Vue app is within an .hbs file ` delimiters: ['${', '}']`
delimiters weren't used in the original question so I omitted them from the answer for simplicity. jobs was different too...but this is just to show how it works
0

@depperm's answer works well (+1), but I'll offer a more render-efficient alternative. Computed properties are cached, so you could avoid the work of matchingTitles() on re-render. In addition, it might be easier to comprehend the template alone without having to jump to the implementation of matchingTitles().

I recommend computing the entire list to be iterated, mapping sectionTitles to the appropriate iterator object:

computed: {
  items() {
    return this.sectionTitles.map(title => ({
      title,
      jobs: this.jobs.filter(job => job.mainTag === title)
    }))
  }
}

Then, you'd update the references in your template to use this new computed prop:

<template v-for="item in 👉items👈">
  <h4>{{ item.title }}</h4>
  <ul>
    <li v-for="job in 👉item.jobs👈">
      <a :href="job.url">
        {{ job.title }}
      </a>
    </li>
  </ul>
</template>

new Vue({
  el: '#app',
    data: {
      jobs: [{'title': 'Software Engineer', mainTag: 'Data'}],
      sectionTitles: ['Data','Poverty Research Unit', 'Technology']
    },
    computed: {
      items() {
        return this.sectionTitles.map(title => ({
          title,
          jobs: this.jobs.filter(job => job.mainTag === title)
        }))
      }
    }
})
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<div id="app">
  <template v-for="item in items">
    <h4 class="h3">{{ item.title }}</h4>
    <ul class="list-none p-0 color-mid-background" id="jobs-list">
      <li class="py-1 px-2" v-for="job in item.jobs">
        <a :href="job.url">
          {{ job.title }}
        </a>
      </li>
    </ul>
  </template>
</div>

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.