Rizki Prastyo
Rizki Prastyo

Reputation: 21

Search list in local JSON received with axios (Vue 3)

I had a problem when I want to filter data with search box. I had to use code from this reference Vue2 Search in List received via Axios and still not working.

I want to get data from my local json file (that I put in public folders). Here's my db.json file:

{
  "products": [
    {
      "id": 1,
      "nama": "Skin10004",
      "deskripsi": "Madagascar Centella Toning"
    },
    {
      "id": 2,
      "nama": "Some By Mi",
      "deskripsi": "AHA-BHA-PHA 30 Days"
    },
    {
      "id": 3,
      "nama": "Avoskin",
      "deskripsi": "Your Skin Bae Series Toner"
    }
  ]
}

With axios, i'm successfully get all the data. But my problem is, my search box can't filter the data when user type on it. Here's my code in Products.vue:

// Here's my view code
<template>
  <div>
    <Navbar />
    <div class="container">

    <!-- Here's my search box but fail to filter the data-->
      <div class="row mt-3">
        <div class="col">
          <div class="input-group mb-3">
            <input
              v-model="search"
              type="search"
              class="form-control"
              placeholder="Cari disini .."
              aria-label="Cari"
              aria-describedby="basic-addon1"
              @keyup="searchProducts"
            />

            <div class="input-group-prepend">
              <span class="input-group-text" id="basic-addon1">
                <b-icon-search></b-icon-search>
              </span>
            </div>
          </div>
        </div>
      </div>

    <!-- Here's where my product display and success to display all data -->
      <div class="row mb-4">
        <div
          class="col-md-4 mt-4"
          v-for="product in products"
          :key="product.id"
        >
          <CardProduct :product="product" />
        </div>
      </div>

    </div>
  </div>
</template>

<script src="https://unpkg.com/[email protected]"></script>
<script>
// Navbar and CardProduct is not the issue
import Navbar from "@/components/Navbar.vue";
import CardProduct from "@/components/CardProduct.vue";
import axios from "axios";

export default {
  name: "Products",
  components: {
    Navbar,
    CardProduct,
  },

  data() {
    return {
      products: [], // Where I store the data to display in view
      search: null, // initialize search null
    };
  },

  // Where I grab all the data in db.json
  mounted() {
    axios
      .get("/db.json")
      .then((response) => this.setProducts(response.data.products))
      .catch((error) => console.log(error));
  },

  // Where I store the data to display in view
  methods: {
    setProducts(data) {
      this.products = data;
    },
  },

  // Here's my problem. Search can't filter the display data
  computed: {
    searchProducts: function () {
      let searchTerm = (this.search || "").toLowerCase();
      return this.products.filter(function (product) {
        let nama = (product.nama || "").toLowerCase();
        let deskripsi = (product.deskripsi || "").toLowerCase();
        return (
          nama.indexOf(searchTerm) > -1 || deskripsi.indexOf(searchTerm) > -1
        );
      });
    },
  },
  
  created() {
    setTimeout(() => (this.products = products), 500);
  },

};
</script>

In console, i've got an error like this:

  1. Uncaught ReferenceError: products is not defined
  2. [Vue warn]: Error in v-on handler: "TypeError: handler.apply is not a function"
  3. TypeError: handler.apply is not a function

Thanks.

Upvotes: 0

Views: 831

Answers (1)

tony19
tony19

Reputation: 138356

Uncaught ReferenceError: products is not defined

The error is likely in created(), where products doesn't seem to be defined anywhere:

export default {
  created() {                            
    setTimeout(() => (this.products = products), 500);
  },                                  ^^^^^^^^
}

It doesn't look like you even need it, since your mounted() hook populates this.products. Just remove the created() hook altogether.

[Vue warn]: Error in v-on handler: "TypeError: handler.apply is not a function"

This error is caused by your keyup binding to the computed prop searchProducts, which doesn't quite make sense. I suspect you actually want the displayed product list to be automatically filtered by the user's search term. The problem is the displayed product list loops through all products, but it should be looping through searchProducts:

<div
  class="col-md-4 mt-4"
  v-for="product in searchProducts"
  :key="product.id"
>
  <CardProduct :product="product" />
</div>

Just remove the @keyup binding, and update the v-for variable as shown above.

Upvotes: 1

Related Questions