12

I am trying to filter an array using a computed property in vue.js. I would like to search on on multiple fields, name, state, tags etc.

My data:

events: [
  {
    id: 1,
    name: 'Name of event',
    url: '#',
    datetime: '2017-05-10T00:00:00Z',
    description: 'The full text of the event',
    state: 'VIC',
    tags: [
      'ordinary',
      'advanced'
    ]
  },
  {
    id: 2,
    name: 'Another event',
    url: '#',
    datetime: '2017-05-12T00:00:00Z',
    description: 'The full text of the event',
    state: 'VIC',
    tags: [
      'beginner'
    ]
  },
  {
    id: 3,
    name: 'Great event',
    url: '#',
    datetime: '2017-05-18T00:00:00Z',
    description: 'The full text of the event',
    state: 'NSW',
    tags: [
      'beginner'
    ]
  }
]

},

The following function works as expected, however I cant work out how to have it search the items in 'tags' (commented out).

searchevents: function(){
  let result = this.events
  if (this.filterValue){
    result = result.filter(event =>
      event.name.toLowerCase().includes(this.filterValue.toLowerCase()) ||
      event.state.toLowerCase().includes(this.filterValue.toLowerCase())
      // event.tags.toLowerCase().values().includes(this.filterValue.toLowerCase())
    )
  }
  return result
}

The following returns a blank array, this method works ok when i have done it in angular but not in vue.

searchevents2: function(){
  var searchRegex = new RegExp(this.filterValue,'i')
  this.events.filter(function(event){
    return !self.filterValue || searchRegex.test(event.name) || searchRegex.test(event.state)
  })
}

Ideally I would either like to be able to list array items to filter by or just filter by the entire array.

Appreciate any help, first post here so be gentle. I have a lot more experience with Python than Javascript so i may also use incorrect terminology at times.

2
  • 1
    I recommend you to shorten your question and code. Commented May 4, 2017 at 2:12
  • I think your question is fine. The only thing I would add that really helps is a working example that can be modified to fix your issue. Commented May 4, 2017 at 2:34

2 Answers 2

6

You weren't too far off.

For your searchEvents filter, you just needed to add the tag filter. Here's how you might do that.

searchevents: function(){
    let result = this.events
    if (!this.filterValue)
      return result

    const filterValue = this.filterValue.toLowerCase()

    const filter = event => 
        event.name.toLowerCase().includes(filterValue) ||
        event.state.toLowerCase().includes(filterValue) ||
        event.tags.some(tag => tag.toLowerCase().includes(filterValue))

    return result.filter(filter)
}

Array.some() is a standard array method that returns true if any element of the array passes your test.

searchevents2: function(){
    const searchRegex = new RegExp(this.filterValue,'i')
    return this.events.filter(event => 
      !this.filterValue || searchRegex.test(event.name) || searchRegex.test(event.state))
}

With searchEvents2 you really only left an errant self in there. Either you needed to set self before you executed the filter, or, as I have done here, turned it into an arrow function.

Example.

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

2 Comments

Thankyou so much. Perfect explanation and it works great. I revised the second function and added a test for event.tags and it works great and somewhat neater code I think.
@KyleHadland Glad to help :)
6

const app = new Vue ({
  el: '#app',
  data: {
    search: '',
    userList: [
      {
        id: 1,
        name: "Prem"
      },
      {
        id: 1,
        name: "Chandu"
      },
      {
        id: 1,
        name: "Shravya"
      }
    ]
  },
  computed: {
    filteredAndSorted(){
     // function to compare names
     function compare(a, b) {
       if (a.name < b.name) return -1;
       if (a.name > b.name) return 1;
       return 0;
     }
      
     return this.userList.filter(user => {
        return user.name.toLowerCase().includes(this.search.toLowerCase())
     }).sort(compare)
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<div id="app">
  <div class="search-wrapper">
    <input type="text" v-model="search" placeholder="Search title.."/>
        <label>Search Users:</label>
  </div>
  <ul>
    <li v-for="user in filteredAndSorted">{{user.name}}</li>
  </ul>
</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.