Vue.js - Use filter inside v-for
Asked Answered
J

3

9

I have a simple Vue filter that limits the length of an array to n elements. It works fine used like this:

{{ array | limitArray(2) }}

Now I'd like to use it inside a v-for loop, like this:

<li v-for="item in items | limitArray(3)">...</li>

But that throws errors. How can I use a filter inside a v-for?

Edit: Probably unimportant, but the filter in question:

Vue.filter('limitArray', function (arr, length = 3) {
    if (arr && arr.length) {
        if (length == -1) {
            return arr;
        }
        if (length > arr.length) {
            return arr;
        }

        return arr.slice(0, length);
    }

    return null;
});
Jasen answered 5/12, 2018 at 19:40 Comment(3)
Does this work? "item in (items | limitArray(3))" Ultimately, it has to be 'item in array'.Nimiety
I honestly think you should use a computed property in this case.Louiselouisette
@Nimiety - it does not :/ Husam Ibrahim - I'd rather not rewrite the same computed property every time I need this.Jasen
O
11

You have to call the filter as a method:

<li v-for="item in $options.filters.limitArray(items, 3)">

But filters are removed in Vue 3. Use a method instead.

Own answered 5/12, 2018 at 23:25 Comment(0)
I
12

You could use method instead of filter (especially in Vue 3) :

  <li v-for="item in limitArray(items,3)">...</li>

and in your methods :

   methods:{
     limitArray (arr, length = 3) {
     if (arr && arr.length) {
    if (length == -1) {
        return arr;
    }
    if (length > arr.length) {
        return arr;
    }

    return arr.slice(0, length);
      }

       return null;
  }
 ...
}

Full Example

new Vue({
  el: '#app',
  data: {
    days: [{
        "number": 1,
        "isSunday": false
      },
      {
        "number": 2,
        "isSunday": false
      },
      {
        "number": 3,
        "isSunday": false
      },
      {
        "number": 4,
        "isSunday": false
      },
      {
        "number": 5,
        "isSunday": false
      },
      {
        "number": 6,
        "isSunday": false
      },
      {
        "number": 7,
        "isSunday": true
      },
      {
        "number": 8,
        "isSunday": false
      },
      {
        "number": 9,
        "isSunday": false
      },
      {
        "number": 10,
        "isSunday": false
      },
      {
        "number": 11,
        "isSunday": false
      },
      {
        "number": 12,
        "isSunday": false
      },
      {
        "number": 13,
        "isSunday": false
      },
      {
        "number": 14,
        "isSunday": true
      },
      {
        "number": 15,
        "isSunday": false
      },
      {
        "number": 16,
        "isSunday": false
      },
      {
        "number": 17,
        "isSunday": false
      },
      {
        "number": 18,
        "isSunday": false
      },
      {
        "number": 19,
        "isSunday": false
      },
      {
        "number": 20,
        "isSunday": false
      },
      {
        "number": 21,
        "isSunday": true
      },
      {
        "number": 22,
        "isSunday": false
      },
      {
        "number": 23,
        "isSunday": false
      },
      {
        "number": 24,
        "isSunday": false
      },
      {
        "number": 25,
        "isSunday": false
      },
      {
        "number": 26,
        "isSunday": false
      },
      {
        "number": 27,
        "isSunday": false
      },
      {
        "number": 28,
        "isSunday": true
      },

      {
        "number": 29,
        "isSunday": false
      },
      {
        "number": 30,
        "isSunday": false
      },
      {
        "number": 31,
        "isSunday": false
      }
    ]
  },
  methods: {

    limitArray(arr, length = 3) {
      if (arr && arr.length) {
        if (length == -1) {
          return arr;
        }
        if (length > arr.length) {
          return arr;
        }

        return arr.slice(0, length);
      }

      return null;
    }
  }
})
<!DOCTYPE html>
<html>

<head>
  <meta name="description" content="Vue.delete">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.min.js"></script>
</head>

<body>
  <div id="app">
    <table class="table table-striped">
      <thead>
        <tr>
          <th>Mon</th>
          <th>Tue</th>
          <th>Wed</th>
          <th>Thi</th>
          <th>Fri</th>
          <th>Sat</th>
          <th>Sun</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td v-for="day in limitArray(days,7)">
            {{day.number}}
          </td>
        </tr>
      </tbody>
    </table>
  </div>
Insouciance answered 5/12, 2018 at 20:1 Comment(4)
Yes this is a better way than using a filter.Louiselouisette
Thanks, I ended up using the filter as a method like Decade Moon suggested. Gave him the answer but gave you an upvote.Jasen
@AndorNémeth knowing also that filters are removed in Vue 3Insouciance
@BoussadjraBrahim Not everybody instantly merged to Vue 3. We have an app that still uses Vue 2.Anthropomorphosis
O
11

You have to call the filter as a method:

<li v-for="item in $options.filters.limitArray(items, 3)">

But filters are removed in Vue 3. Use a method instead.

Own answered 5/12, 2018 at 23:25 Comment(0)
T
-1

I think you should do like this:

<li v-for="item in $options.filter(v => dosomething)">
Tartarean answered 17/10, 2019 at 8:30 Comment(1)
This will not update if the collection updates as filter returns a new collectionPeres

© 2022 - 2024 — McMap. All rights reserved.