What could be causing the sort method to malfunction in the parent component?

Just starting out with VueJS and working on my first project. I have a list of products that I want to sort by price. I created two components - a parent and a child component for the dropdown button. I've been trying to pass a sort method from the child component to the parent by emitting an event, but no matter how many times I try, I can't seem to figure out what's wrong in my code. Any assistance would be greatly appreciated!

Child Component Code:

<template>
  <div class="dropdown">
    <button
      @click="toggleShow(); $emit('sortPrice')"
      class="dropbtn"
    >
      {{ title }}
      <span class="material-icons-outlined"> {{ icon }} </span>
    </button>

    <div v-if="showMenu" class="menu">
      <div class="menu-item" v-for="(item, index) in this.items" :key="index">
        {{ item }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "Dropdown-menu",

  props: {
    title: String,
    icon: String,
    items: {
      type: Object,
      required: true,
    },
  },

  data() {
    return {
      showMenu: false
    };
  },

  methods: {
    toggleShow: function () {
      this.showMenu = !this.showMenu;
    },

    sortPrice: function () {
      this.$emit("sort", this.sortPrice);
    },
  },
};
</script>

Parent Component Code:

<template>
    <dropdown
          :title="sortedBy"
          :items="arrangements"
          :icon="material_icons"
          @sort="sortByPrice"
    ></dropdown>
</template>

<script>
import Dropdown from "@/components/Dropdown.vue";

export default {
  components: {
    Dropdown,
  },

  data() {
    return {
      sortedBy: "Featured",
      arrangements: ["Featured", "Lowest", "Highest"],
      material_icons: "expand_more",
      productData: require("@/data/store-data.json"),
    };
  },
  methods: {
    sortByPrice: function () {
      let realProducts = this.productData.products;
      let sortedProducts = realProducts.sort((a, b) => {
        if (this.sortedBy === "Highest") {
          return b.price - a.price;
        } else if (this.sortedBy === "Lowest") {
          return a.price - b.price;
        }
      });
      return sortedProducts;
    },
  },
};
</script>

Answer №1

Here are some suggestions:

  • Instead of emitting when the button is clicked, emit when an individual item is clicked. This way, you capture the user's selection.
  • To achieve this, call the sortPrice function from the menu-item div using
    @click="sortPrice(item)"
  • In the sortPrice function, pass the item parameter like so: function (item) { and then include it as a second parameter in your emit call:
    this.$emit("sort", item);
    . This ensures that the parent component knows what was selected.
  • In the parent component's sortByPrice function, accept the item parameter like this: sortByPrice: function (item) { and use it to set the sortedBy property: this.sortedBy = item;
  • Perform the sorting in a computed property that is then displayed, such as the example named sortedProducts.

For instance, in the parent component:

<template>
  <h2>Main App</h2>
  <dropdown
    :title="sortedBy"
    :items="arrangements"
    @sort="sortByPrice"
  ></dropdown>
  <div>
    <h3>Products</h3>
    <ul>
      <li v-for="product in sortedProducts" :key="product.index">
        {{ product.name }} ${{ product.price }}
      </li>
    </ul>
  </div>
</template>

<script>
import Dropdown from "@/components/Dropdown.vue"; 

export default {
  components: {
    Dropdown,
  },

  data() {
    return {
      sortedBy: "Featured",
      arrangements: ["Featured", "Lowest", "Highest"],
      productData: {
        // Dummy data for demonstration purposes
        products: [
          { index: 1, name: "product A", price: 1, featured: true },
          { index: 2, name: "product B", price: 2, featured: false },
          { index: 3, name: "product C", price: 6, featured: true },
          { index: 4, name: "product G", price: 4, featured: false },
          { index: 5, name: "product V", price: 0, featured: true },
        ],
      },
    };
  },
  methods: {
    sortByPrice: function (item) {
      this.sortedBy = item;
    },
  },
  computed: {
    sortedProducts: function () {
      if (this.sortedBy === "Featured") {
        return this.productData.products.filter((prod) => prod.featured);
      } else if (this.sortedBy === "Highest") {
        return this.productData.products.sort((a, b) => b.price - a.price);
      } else if (this.sortedBy === "Lowest") {
        return this.productData.products.sort((a, b) => a.price - b.price);
      }
      // Default return just in case
      return this.productData.products;
    },
  },
};
</script>

And the child Dropdown.vue component:

<template>
  <div class="dropdown">
    <button @click="toggleShow()" class="dropbtn">
      {{ title }}
    </button>

    <div v-if="showMenu" class="menu">
      <div
        class="menu-item"
        v-for="(item, index) in this.items"
        :key="index"
        @click="sortPrice(item)"
      >
        {{ item }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "Dropdown-menu",

  props: {
    title: String,
    items: {
      type: Object,
      required: true,
    },
  },

  data() {
    return {
      showMenu: false,
    };
  },

  methods: {
    toggleShow: function () {
      this.showMenu = !this.showMenu;
    },

    sortPrice: function (item) {
      this.$emit("sort", item);
      this.toggleShow();
    },
  },
};
</script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Warning: The use of [email protected] is deprecated when using Vue 3

While utilizing Vue 3, I came across the error message: "npm WARN deprecated [email protected]: Vue 2 has reached EOL and is no longer actively maintained." What is causing this error to appear? The screenshot displays additional deprecated ...

Retrieve a basic JSONP object from a remote server PHP file by utilizing AJAX (along with jQuery) integrated into JavaScript directly on my WordPress page

I have implemented PHP code on a static WordPress page (using the include-php-in-pages-and-posts plugin) to retrieve a JSON object from a remote server. However, this process only works once during the page load and does not refresh again without using Aja ...

I'm wondering how I can design a utility function within my Redux module that can extract a specific subset of read-only data from the current state

I am currently utilizing redux to create a "helper function" inside my redux module that is responsible for fetching filtered data from the state based on a specified index. This specific data will be used to generate a form consisting of inputs depending ...

Does Vue trigger v-bind when referring to a component?

My upload component is set up to submit after a message has been sent. Within this component, there is an action that specifies the request URL using v-bind. However, I've noticed that whenever I try to access the reference, the v-bind does not seem t ...

In what situations can the comma operator be beneficial?

After reading a question about the "comma operator" in expressions and exploring the MDN documentation on it, I am struggling to identify a practical scenario where it would be beneficial. Therefore, in what situations does the comma operator prove useful ...

Hide the address bar in a Google Maps iFrame

After numerous attempts, I still can't seem to hide the address bar on this Google Maps iFrame. Can anyone provide a solution or workaround for this issue? https://i.sstatic.net/x0pl9.png I have tried using display:none; in our CSS, which successfull ...

How to use jQuery to hide list items after a certain threshold

$('li[data-number=4]').after().hide(); <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <ul> <li data-number="0"">1</li> <li data-number="1">2</li> ...

Implementing multiple components in a Vue route: A comprehensive guide

As a beginner in Vue, I am experimenting with incorporating two components in a route - a navigation bar and some sales data. The assets are being bundled by Laravel mix using Webpack, but I keep encountering failures with npm. index.php <body> ...

Getting the ID of a button: A step-by-step guide

My query involves a file named Index.aspx connected to another file called seatbooks.js. Within Index.aspx, there is a button with the id Indexbutton. This button has an eventonclick='book_ticket()' attribute. The book_ticket() method is includ ...

Received undefined response from Axios.get() request

While working with the code below, I encountered an issue. The axios get request from await axios.get('/products/api') is functioning properly and I can see the data in the console. However, for await axios.get('/users/api'), 'Unde ...

The search function on my blog is not displaying the blogs that have been filtered

I have encountered an issue with my code as I am unable to get any search results from the search bar. const RecentBlogs = ({recentBlogs}) => { const [query, setQuery] = useState("") const filteredItems = (() => { if(!query) return rec ...

Displaying array data without the need for a loop in Vue.js and Axios

I want to display data in my Vue.js 3 app without using a loop. Here is the response from my Axios API: In My Axios Api I got reponse: [{id: 2, name: "sub_title", value: "The Best Developer Team", created_at: null, updated_at: null},… ...

Please be aware that any fabricated comments will not be displayed in the posts object

-I have made an EDIT at the bottom of my original post -For my plunker, please visit this link Currently, I am learning AngularJS by following a tutorial located here. At this moment, I am stuck on the step called 'Faking comment data'. I have ...

Implementing the React Router into a ReactJS project: Methods to prevent users from clicking on links within React-Router's <Link> component

I'm exploring React-Router's Link and have set up the following: <Link to={...}>{this.props.live? "Live": "Not Live"}</Link> In this configuration, if this.props.live is present, I want to display the text "Live" which will lead to ...

Developing a progress bar with jQuery and Cascading Style Sheets (

Below is the code I'm currently using: <progress id="amount" value="0" max="100"></progress> Here is the JavaScript snippet I have implemented: <script> for (var i = 0; i < 240; i++) { setTimeout(function () { // this repre ...

When an absolute positioned DIV is nested inside a relatively positioned DIV, it disappears when the page is scrolled

A unique feature of my DIV is that it remains fixed at the top of the page as you scroll. This is achieved by setting its position to fixed. However, within this main container, I have another div with a relative position. While the content in the relative ...

The initial UI did not match the server-rendered content, resulting in a Next.JS Hydration failure

I'm facing an issue with hydration in Next.JS 14, where there is a discrepancy between the server-side rendered UI and the client-side rendering. I have a suspicion that this problem may stem from using new Date(), which could be producing different v ...

Passing multiple arguments to a callback function in node-js without using promises

Within my small program, I am working on unshortening a URL and then verifying if the link adheres to a specific pattern. If it meets the criteria, I aim to carry out additional processing steps. However, I find it cumbersome to pass along all 3 paramete ...

`Where can I locate a grid example?`

Right here: Upon reading the documentation, I discovered: onItemInserting has the following arguments: { grid // represents the grid instance item // item being inserted } In my software application there are multi ...

What advantages does using immutablejs offer compared to using object.freeze?

I've scoured the internet trying to find convincing reasons for using immutablejs instead of Object.freeze(), but I still haven't found a satisfactory answer! What are the advantages of working with non-native data structures in this library ove ...