Подтвердить что ты не робот

Результаты пустого фильтра Vue.js

В Vue я должен фильтровать некоторые данные:

<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>

Как я могу обнаружить пустой результат фильтра и отобразить соответствующее сообщение пользователю?

ИЗМЕНИТЬ

В настоящее время я делаю следующее, которое, как я считаю, является взломанным обходным путем:

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
        });
    }
})
4b9b3361

Ответ 1

Vue 2.x(Обновление)

В Vue теперь могут использоваться только фильтры 2.x, как говорят docs, внутри интерполяции текста:

Фильтры Vue 2.x могут использоваться только внутри привязок усов. Чтобы добиться такого же поведения внутри привязок директив, вы должны использовать Computed properties.

Вы можете добиться такого же поведения с помощью встроенного метода filter JavaScript и вычислимого свойства.

<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(исходный ответ)

На данный момент существует два способа. Во всех случаях шаблон может выглядеть одинаково.

<input v-model="searchQuery">

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

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

filterBy

Исходный метод filterBy доступен через $options.

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

$Eval

Немного более чистый подход. Eval выражение, как вы бы сделать внутри вашего шаблона.

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

Ответ 2

В 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>

В JS вам нужно использовать вычисленные свойства следующим образом:

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

Демо: http://jsfiddle.net/crswll/Lr9r2kfv/37/

Ответ 3

Это будет работать только с Vue 1.0, даже тогда вы должны просто использовать вычисленное свойство. Я оставлю этот ответ здесь на всякий случай.


Вы можете использовать vm.$eval и вычисленное свойство для этого.

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

и используйте что-то вроде

<div v-if="filteredItems.length">
  <div v-for="item in filteredItems">
    {{ item.name }}
  </div>
</div>
<div v-else>
  No results found!
</div>

Ответ 4

Решение HTML/CSS (на всякий случай, если вы все еще пытаетесь исправить его через 2 года)

/* 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>