Vue.js empty filter results

2019-04-19 03:48发布

In Vue, I have to filter through some data:

<input v-model="search">
<ul>
    <li v-repeat="photo in photos | filterBy search in 'name'">
        <img src="{{ photo.src }}" alt="{{ photo.name }}">
    </li>
    <li v-if="!photos.length">
        No results, sorry!
    </li>
</ul>

How can I detect empty filter results and display an appropriate message to the user?

EDIT

I am currently doing the following which I feel is a hacky workaround:

HTML:

<input v-model="search">
<ul>
    <li v-repeat="photo in photos">
        <img src="{{ photo.src }}" alt="{{ photo.name }}">
    </li>
    <li v-if="!photos.length">
        No results, sorry!
    </li>
</ul>

Javascript:

var v = new Vue({
    data: {
        allPhotos: [...],
        photos: [],
        search: '',
    },
    ready: function () {
        var filter = Vue.filter('filterBy');
        var self = this;
        this.$watch('search', function () {
            self.photos = filter(self.allPhotos, self.search, 'name');
        }, {
            immediate: true
        });
    }
})

标签: vue.js
4条回答
冷血范
2楼-- · 2019-04-19 04:22

This will only work with Vue 1.0, even then you should just be using a computed property. I'll leave this answer here just in case.


You could use vm.$eval and a computed property to do this as well.

computed: {
  filteredItems: function () {
    return this.$eval('items | filterBy searchQuery');
  }
}

and use something like

<div v-if="filteredItems.length">
  <div v-for="item in filteredItems">
    {{ item.name }}
  </div>
</div>
<div v-else>
  No results found!
</div>
查看更多
Ridiculous、
3楼-- · 2019-04-19 04:30

Vue 2.x (Update)

In Vue 2.x filters can now only be used, as docs say, inside text interpolations:

Vue 2.x filters can only be used inside mustache bindings. To achieve the same behavior inside directive bindings, you should use Computed properties instead.

You can achieve same behavior with JavaScript built-in filter method and computed property.

<input v-model="searchQuery">

<span v-if="!filteredItems.length">No results.</span>

<ul>
    <li v-for="item in filteredItems"></li>
</ul>
computed: {
  filteredItems: function () {
    var self = this;
    return self.items.filter(function (item) {
      return item.indexOf(self.searchQuery) !== -1;
    })
  }
}

Vue 1.x (Original Answer)

There are two ways at the moment. In all cases, template can look the same.

<input v-model="searchQuery">

<span v-if="!filteredItems.length">No results.</span>

<ul>
    <li v-for="item in filteredItems"></li>
</ul>

filterBy

Original filterBy method accessed via $options.

computed: {
    filteredItems: function () {
        return this.$options.filters.filterBy(this.items, this.searchQuery);
    }
}

$eval

A little bit cleaner approach. Eval expression like you would do inside your template.

computed: {
  filteredItems: function () {
    return this.$eval('items | filterBy searchQuery');
  }
}
查看更多
混吃等死
4楼-- · 2019-04-19 04:44

In HTML:

<input v-model="search">
<h4 v-if="!filteredPhotos.length">No results</h4>
<ul>
    <li v-for="photo in filteredPhotos">
        <img :src="photo.src" :alt="photo.name">
    </li>
</ul>

In JS, you need to use computed properties like this:

computed: {
  filteredPhotos: function () {
      return this.photos.filter(function(photo){
          return photo.name.indexOf(this.search) > -1;
      }.bind(this));
  }
}

Demo: http://jsfiddle.net/crswll/Lr9r2kfv/37/

查看更多
SAY GOODBYE
5楼-- · 2019-04-19 04:44

HTML/CSS solution (just in case, if you still trying to fix it after 2 years)

/* all list items are visible */
ul.that-list li { display: block; }

/* ...exept last one*/
ul.that-list li:last-child { display: none; }

/* but if last one is also first one ... means the only one */
ul.that-list li:first-child { display: block; }
<h2>List with items</h2>
<ul class="that-list">
  <!-- here is your v-for with any filters you want -->
  <li>1 - Item is here</li>
  <li>2 - Another One Here</li>
  <li>3 - And anothe one</li>
  <!-- this is your message -->
  <li>(!message) There is no items... sorry</li>
</ul>

<h2>Empty</h2>
<ul class="that-list">
  <!-- v-for with no rendered items :c -->
  <li>(!message) There is no items... sorry</li>
</ul>

Also codepen link here

查看更多
登录 后发表回答