Накопительные фильтры на wordpress rest api с nuxt

avatar
cfab
8 апреля 2018 в 10:23
361
1
0

Я новичок в vue.js и пытаюсь сделать что-то вроде этого: https://appendto.com/2017/05/building-tutorial-search-app-vue/ но с nuxt.js и получением данных из WordPress Rest API.

На данный момент мне удалось создать динамическое меню на основе меню WordPress, динамических URL-адресов для страниц и пользовательского типа сообщений.

У меня есть страница со списком пользовательских типов сообщений (experte) и на этой странице

Я хотел бы иметь возможность фильтровать эти сообщения с помощью текстового поиска и по категориям.

Проблема 1

Текстовый поиск отлично работает с приведенным ниже кодом. Если я набираю букву или слово, список соответственно сокращается (мне удалось перечислить тип сообщений через API). Но если я очищаю текстовый ввод, список остается отфильтрованным, и я не знаю, почему... Я решил это, сохранив возврат вызова axios для типов сообщений в другой переменной (orig), которую я использую в методе filterExpertes, но Я не уверен, что это хорошая практика...

Проблема 2

Мне удалось динамически создать список флажков на основе оставшегося API WordPress и с помощью инструментов vue dev, я вижу, что моя выбранная переменная обновляется, когда я делаю выбор. Тем не менее, список становится пустым, как только флажок установлен.

На стороне wordpress я распорядился так, чтобы оставшийся ответ включал такие категории типов сообщений, как этот (код, возвращаемый, если я перехожу к своей конечной точке пользовательского типа сообщения http://lesexpertes.test/wp-json/wp/v2 /experte (результат запроса axios)

[
  {
    "id": 120,
    "date": "2018-03-29T10:02:01",
    "date_gmt": "2018-03-29T08:02:01",
    "guid": {
      "rendered": "http://lesexpertes.test/experte/aperiam-itaque-enim-omnis/"
    },
    "modified": "2018-03-29T18:03:23",
    "modified_gmt": "2018-03-29T16:03:23",
    "slug": "julia",
    "status": "publish",
    "type": "experte",
    "link": "http://lesexpertes.test/experte/julia/",
    "title": {
      "rendered": "Julia"
    },
    "content": {
      "rendered": "<h2>Nemo aut fuga ad voluptatem placeat aliquam quia. Voluptatibus nihil dolorem assumenda repellat ipsum excepturi possimus. Dolorem optio blanditiis eius rem distinctio id eveniet</h2>\n<p>Veritatis odit <a title=\"Excepturi consequatur pariatur quisquam voluptas.\" href=\"http://www.quigley.info/natus-et-cupiditate-repudiandae-illum-et\">et quos quaerat. Deserunt qui in</a> pariatur libero atque. Aperiam sint consectetur deserunt necessitatibus. Laboriosam sunt facilis qui beatae. Qui dignissimos quia dolores. Dolores molestiae ullam id. Temporibus ut autem fugiat <a title=\"Possimus.\" href=\"http://williamson.info/\">modi aut sed soluta.</a> eligendi modi corrupti necessitatibus unde libero alias Repudiandae delectus fugiat ea quos dolorum quasi dolorem Porro delectus dolore iure explicabo. Rerum blanditiis <a title=\"Quaerat eos dicta facilis.\" href=\"http://www.heaney.com/soluta-exercitationem-qui-quaerat-et-quo-nostrum.html\">quam consequatur maxime</a> Et rerum aliquam natus sequi sed. Deserunt consequuntur quo quos earum est. Neque officiis explicabo nihil eum. Eaque porro perspiciatis voluptas animi eveniet. sint quibusdam ut Voluptatem dolores quidem consequatur unde. Omnis <a title=\"Distinctio non numquam.\" href=\"http://www.cruickshank.com/vitae-quia-laborum-harum-ipsam-tempore-enim\">dolore quas ipsum ut quasi. Autem</a> <a title=\"Odio quas similique.\" href=\"http://www.johnson.org/ut-aspernatur-eum-recusandae-voluptatem-tempora-rerum\">incidunt vero fuga</a> magnam magnam. Laudantium ratione impedit consequatur. Nemo veniam ipsam reiciendis in. Rerum labore magni dicta saepe doloremque laudantium. Voluptatem eos qui sit aut voluptas eveniet. Numquam et accusamus nisi dolorem. Vel porro vitae sint hic. Ut nam quam aut <a title=\"Consequatur ullam magni aliquam quo error voluptas.\" href=\"http://www.boyle.biz/qui-aut-aperiam-inventore-omnis-accusantium.html\">autem esse eum.</a></p>\n",
      "protected": false
    },
    "author": 1,
    "featured_media": 121,
    "template": "",
    "categories": [
      11,
      10
    ],
    "langue": [

    ],
    "better_featured_image": {
      "id": 121,
      "alt_text": "",
      "caption": "",
      "description": "",
      "media_type": "image",
      "media_details": {
        "width": 300,
        "height": 300,
        "file": "2018/03/e9c4f864-3555-3e8c-b0f7-73f9d4d74348.jpg",
        "sizes": {
          "thumbnail": {
            "file": "e9c4f864-3555-3e8c-b0f7-73f9d4d74348-150x150.jpg",
            "width": 150,
            "height": 150,
            "mime-type": "image/jpeg",
            "source_url": "http://lesexpertes.test/wp-content/uploads/2018/03/e9c4f864-3555-3e8c-b0f7-73f9d4d74348-150x150.jpg"
          }
        },
        "image_meta": {
          "aperture": "0",
          "credit": "",
          "camera": "",
          "caption": "",
          "created_timestamp": "0",
          "copyright": "",
          "focal_length": "0",
          "iso": "0",
          "shutter_speed": "0",
          "title": "",
          "orientation": "0",
          "keywords": [

          ]
        }
      },
      "post": 120,
      "source_url": "http://lesexpertes.test/wp-content/uploads/2018/03/e9c4f864-3555-3e8c-b0f7-73f9d4d74348.jpg"
    },
    "acf": {
      "nom": "Watson",
      "prenom": "Julia",
      "telephone": "022 733 40 31",
      "courriel": "julia@banquise.ch",
      "formation": "<p>Université de Genève &#8211; Master en Ecologie</p>\n"
    },
    "cats": [
      {
        "term_id": 11,
        "name": "Ecologie",
        "slug": "ecologie",
        "term_group": 0,
        "term_taxonomy_id": 11,
        "taxonomy": "category",
        "description": "",
        "parent": 0,
        "count": 23,
        "filter": "raw",
        "cat_ID": 11,
        "category_count": 23,
        "category_description": "",
        "cat_name": "Ecologie",
        "category_nicename": "ecologie",
        "category_parent": 0
      },
      {
        "term_id": 10,
        "name": "Technologies",
        "slug": "technologies",
        "term_group": 0,
        "term_taxonomy_id": 10,
        "taxonomy": "category",
        "description": "",
        "parent": 0,
        "count": 26,
        "filter": "raw",
        "cat_ID": 10,
        "category_count": 26,
        "category_description": "",
        "cat_name": "Technologies",
        "category_nicename": "technologies",
        "category_parent": 0
      }
    ],
    "_links": {
      "self": [
        {
          "href": "http://lesexpertes.test/wp-json/wp/v2/experte/120"
        }
      ],
      "collection": [
        {
          "href": "http://lesexpertes.test/wp-json/wp/v2/experte"
        }
      ],
      "about": [
        {
          "href": "http://lesexpertes.test/wp-json/wp/v2/types/experte"
        }
      ],
      "author": [
        {
          "embeddable": true,
          "href": "http://lesexpertes.test/wp-json/wp/v2/users/1"
        }
      ],
      "wp:featuredmedia": [
        {
          "embeddable": true,
          "href": "http://lesexpertes.test/wp-json/wp/v2/media/121"
        }
      ],
      "wp:attachment": [
        {
          "href": "http://lesexpertes.test/wp-json/wp/v2/media?parent=120"
        }
      ],
      "wp:term": [
        {
          "taxonomy": "category",
          "embeddable": true,
          "href": "http://lesexpertes.test/wp-json/wp/v2/categories?post=120"
        },
        {
          "taxonomy": "langue",
          "embeddable": true,
          "href": "http://lesexpertes.test/wp-json/wp/v2/langue?post=120"
        }
      ],
      "curies": [
        {
          "name": "wp",
          "href": "https://api.w.org/{rel}",
          "templated": true
        }
      ]
    }
  },
  {
    "id": 84,
    "date": "2018-03-29T09:33:04",
    "date_gmt": "2018-03-29T07:33:04",
    "guid": {
      "rendered": "http://lesexpertes.test/experte/qui-et-similique-deleniti-sint-exercitationem/"
    },
    "modified": "2018-03-29T09:33:04",
    "modified_gmt": "2018-03-29T07:33:04",
    "slug": "qui-et-similique-deleniti-sint-exercitationem",
    "status": "publish",
    "type": "experte",
    "link": "http://lesexpertes.test/experte/qui-et-similique-deleniti-sint-exercitationem/",
    "title": {
      "rendered": "Qui et similique deleniti sint exercitationem"
    },

...

А вот мой код:

index.vue

    <template>
  <div>
    <main role="main">
      <section class="jumbotron text-center">
        <SearchBox v-model="searchTerm" />
        <RadioGroup v-model="selected" />
        <ExpertesList :expertes="expertes" />
      </section>
    </main>
  </div>
</template>

<script>
  import axios from 'axios'
  import ExpertesList from '@/components/ExpertesList'
  import SearchBox from '@/components/SearchBox'
  // import Pagination from '@components/Pagination'
  import RadioGroup from '@/components/RadioGroup'

  export default {
    components: {
      ExpertesList,
      SearchBox,
      RadioGroup
    },

    asyncData(context) {
      return axios.get('http://lesexpertes.test/wp-json/wp/v2/experte')
        .then(res => {
          return {
            expertes: res.data,
            orig: res.data
          }
        })
        .catch(e => context.error(e))
    },
    data() {
      return {
        searchTerm: '',
        selected: ''
        // expertes: ''
      }
    },
    computed: {
      result() {
        return this.orig
      }
    },
    watch: {
      searchTerm: function () {
        this.filterExpertes()
      },
      selected: function () {
        this.filterExpertes()
      }
    },
    methods: {
      filterExpertes: function () {
        const searchTerm = this.searchTerm.toLowerCase()
        const selected = this.selected
        let result = this.result
        if (searchTerm) {
          result = result.filter(experte => {
            return (
              experte.title.rendered.toLowerCase().search(searchTerm) >= 0
              // ||
              //experte.description.toLowerCase().search(searchTerm) >= 0
            )
          })
        }

        if (selected) {
          // result = result.filter(experte => {
          //   return (
          //     experte.categories.indexOf(selected) >= 0
          //   )
          // })
          result = result.filter(experte => experte.categories.indexOf(selected) >= 0)
        }
        this.expertes = result
        //this.page = 1
      }
    },
    created: function () {
      this.filterExpertes()
    }
  }
</script>

RadioGroup.vue

    <template>
  <div>
    <!-- <b-form-group label="Catégories:">
      <b-form-checkbox-group id="checkboxes2" name="flavour2" v-model="selected">
        <b-form-checkbox v-for="cat in cats" :value="cat.id">{{cat.name}}</b-form-checkbox>
      </b-form-checkbox-group>
    </b-form-group> -->
    <div v-for="cat in cats">
      <input type="checkbox" :value="cat.id" v-model="selected">
      <label >{{cat.name}}</label>
    </div>

    <hr>
    <div>Selected:
      <strong>{{ selected }}</strong>
    </div>
  </div>
</template>

<script>
  import axios from 'axios';
  export default {
    name: 'RadioGroup',
    mounted: function () {
      //console.log( wp.api.collections );
      this.getCats();
    },
    data() {
      return {
        cats: '',
        selected: []
        //
      }
    },
    methods: {
      getCats: function () {
        const vm = this;
        axios.get('http://lesexpertes.test/wp-json/wp/v2/categories')
          .then((res2) => {
            vm.cats = res2.data;
          })
          .catch((res2) => {
            //console.log( `Something went wrong : ${ res }` );
          });
      }
    },
    watch: {
      selected: function (val) {
        this.$emit('input', val)
      }
    }
  }
</script>

ExpertesList.vue

    <template>
  <div>

    <ul>
       <li v-for="experte in expertes">
         {{experte.title.rendered}} - {{experte.categories}}
         </li>
    </ul>
    </div>


</template>

<script>
//import Experte from '@/components/Experte'
export default {
  name: 'ExpertesList',
  //components: { Experte },
  props: ['expertes']
}
</script>

SearchBox.vue

  <template>
  <div class="form-group has-feedback">
    <input type="search" class="form-control input-lg" v-model="searchTerm"
      placeholder="Search the title/description" :name="name">
    <span class="glyphicon glyphicon-search form-control-feedback" aria-hidden="true"></span>
  </div>
</template>

<script>
export default {
  props: {
    value: {
      default: ''
    },
    name: {
      default: ''
    }
  },
  data: function() {
    return { searchTerm: this.value }
  },
  watch: {
    value: function(val) {
      this.searchTerm = val
    },
    searchTerm: function(val) {
      this.$emit('input', val)
    }
  }
}
</script>

Любая помощь/подсказка приветствуется...

Источник
oniondomes
8 апреля 2018 в 10:29
0

coderhelper.com/help/mcve

cfab
8 апреля 2018 в 15:27
0

Ok ! Короткая версия здесь, но тот же вопрос: как фильтровать по почтовому ящику поиска и флажку jsfiddle.net/cfab/de7ncvvf

Ответы (1)

avatar
oniondomes
8 апреля 2018 в 15:54
0

Я не вижу проблемы №1 в вашей скрипке, но вот решение второй:

new Vue({
  el: '#app',
  data: {
    searchQuery: '',
    items: [],
    cats: [{
        id: 2672,
        name: "Autre",
        slug: "autre",
        taxonomy: "category",
        checked: false,
      },
      {
        id: 25,
        name: "Culture",
        slug: "culture",
        taxonomy: "category",
        checked: false,
      },
    ],
  },
  computed: {
    checkedIds() {
      return Object.assign({}, ...this.cats
        .filter(el => el.checked)
        .map(el => ({
          [el.id]: true
        })));
    },
    filteredItems() {
      return this.items.filter((item) => {
        return (
          item.title.rendered.indexOf(this.searchQuery) !== -1 &&
          item.categories.filter(el => this.checkedIds[el]).length > 0
        );
      });
    },
  },
  created: function() {
    const that = this
    axios.get('https://lecourrier.ch/wp-json/wp/v2/posts')
      .then(function(response) {
        that.items = response.data
      });
  },
});
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<div id="app">
  <input type="search" placeholder="Search" v-model="searchQuery">
  <div v-for="cat in cats">
    <input type="checkbox" :value="cat.id" v-model="cat.checked">
    <label>{{cat.name}} - cat_id: {{cat.id}}</label>
  </div>
  <ul>
    <li v-for="item in filteredItems" :key="item.id">{{ item.title.rendered }} - cat_id: {{item.categories}}</li>
  </ul>
</div>

Помимо фильтрации по строке запроса, вам также необходимо отслеживать выбранные категории. Вы можете сделать это, используя директиву v-model на входах. Затем вы можете создать карту выбранного идентификатора (взгляните на checkedIds) и отфильтровать свои элементы, используя ее.

jsFiddle

P.S. используйте функцию стрелки, чтобы не писать var that = this. У стрелочных функций нет собственного this, поэтому он будет ссылаться на компонент.