What's the best way to sort objects using VueJS?

Lately, I've been delving into Vue.js and experimenting with it. Currently, I am working on a basic todo list project. However, I have run into some issues with the buttons that are supposed to filter tasks. The "All" button should display every single task, the "Ongoing" button is meant for unchecking input checkboxes, and the "Done" button is for displaying checked tasks.

I'm struggling to figure out how to fix this problem. Any suggestions or solutions would be greatly appreciated!

new Vue({
  el: '#app',
  data: {
    inputTask:'',
    todos: [
      {task:'task01', done: false},
      {task:'task02', done: false},
      {task:'task03', done: true},
      {task:'task04', done: true},
      {task:'task05', done: false},
    ]
  },
  computed: {


  },
  methods: {
    allTask : function () {
      this.todos
    },
    ongoingTask: function () {
      this.todos = this.todos.filter(function (el) {
        el.value = false
      })
    },
    doneTask: function () {
      this.todos = this.todos.filter(function (el) {
        el.checked
      })
    },
    addTask: function() {
      const todo = { task: this.inputTask, done:false, };
      this.todos.push(todo);
      this.inputTask ='';
    },
    deleteTask: function (index) {
      this.todos.splice(index, 1);
    }


  }

})
.done {text-decoration: line-through;}
<div id="app">
<input type="text" v-model="inputTask">
<button @click="addTask">Add</button>

<div>
<button @click="allTask">All</button>
<button @click="ongoingTask">Ongoing</button>
<button @click="doneTask">Done</button>
</div>

<ul>
  <li v-for="(todo, index) in todos" :key="todo">
    <input type="checkbox" v-model="todo.done">
    <span :class="{done:todo.done}">{{todo.task}}</span>
    <button @click="deleteTask(index)">Remove</button>
  </li>
</ul>
<p v-show="todos.length===0">Nothing to do</p>


</div>



<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

Answer №1

To enhance your task filtering capabilities, consider utilizing computed properties while also improving the user interface for a more user-friendly experience. Your updated code snippet will appear as follows:

new Vue({
    el: '#app',
    data: {
        type: '',
        inputTask:'',
        todos: [
            {task:'task01', done: false},
            {task:'task02', done: false},
            {task:'task03', done: true},
            {task:'task04', done: true},
            {task:'task05', done: false},
        ]
    },
    methods: {
        setFilterType(type) {
            this.type = type;
        },
        addTask() {
            const todo = { task: this.inputTask, done: false};
            this.todos.push(todo);
            this.inputTask = '';
        },
        deleteTask(index) {
            this.todos.splice(index, 1);
        }
    },
    computed: {
        filteredTodos() {
            return this.todos.filter(todo => {
                switch(this.type) {
                    case 'ongoing':
                        return !todo.done;
                    case 'done':
                        return todo.done;
                    default:
                        return true;
                }
            });
        }
    }
})

Here is the corresponding template:

<div id="app">
<input type="text" v-model="inputTask">
<button @click="addTask">Add</button>

<div>
<button :class="{active: type ===''}" @click="setFilterType('')">All</button>
<button :class="{active: type ==='ongoing'}" @click="setFilterType('ongoing')">Ongoing</button>
<button :class="{active: type ==='done'}" @click="setFilterType('done')">Done</button>
</div>

<ul>
  <li v-for="(todo, index) in filteredTodos" :key="todo">
    <input type="checkbox" v-model="todo.done">
    <span :class="{done:todo.done}">{{todo.task}}</span>
    <button @click="deleteTask(index)">Remove</button>
  </li>
</ul>
<p v-show="todos.length===0">Nothing to do</p>


</div>

In addition, I have included the active class for buttons, allowing you to apply CSS styling to highlight the current sorting. For further information on computed properties, refer to this resource.

Answer №2

It appears that the filter functions for ongoingTask and doneTask are incorrect as they should be returning a value. To understand how the filter function works, you can reference the documentation here.

If I understand correctly, the following adjustments to the code should resolve the issue. Please provide feedback on whether this solves the problem so I can make any necessary updates.

// ...
    ongoingTask: function () {
      this.todos = this.todos.filter(function (el) {
        return el.value === false
      })
    },
    doneTask: function () {
      this.todos = this.todos.filter(function (el) {
        return el.checked
      })
    },
// ...

UPDATE:

An additional aspect of the problem relates to the logic; currently, when clicking on any filtering button, data in the state is removed causing unwanted data loss. It is advisable to retain the data and utilize computed properties to address this issue. Below is a demonstration using a Vue component for consolidated data handling:

<template>
  <div id="app">
    <input type="text" v-model="inputTask">
    <button @click="addTask">Add</button>

    <div>
      <button @click="changeFilter('all')">All</button>
      <button @click="changeFilter('ongoing')">Ongoing</button>
      <button @click="changeFilter('done')">Done</button>
    </div>

    <ul>
      <li v-for="(todo, index) in getTasksList()" :key="{index}">
        <input type="checkbox" v-model="todo.done">
        <span :class="{done:todo.done}">{{todo.task}}</span>
        <button @click="deleteTask(index)">Remove</button>
      </li>
    </ul>
    <p v-show="todos.length===0">Nothing to do</p>
  </div>
</template>

<script>
export default {
  name: "App",
  data: () => ({
    inputTask: "",
    currentFilter: "ongoing",
    todos: [
      { task: "task01", done: false },
      { task: "task02", done: false },
      { task: "task03", done: true },
      { task: "task04", done: true },
      { task: "task05", done: false }
    ]
  }),
  computed: {
    ongoingTasks: function() {
      return this.todos.filter(function(todo) {
        return todo.done === false;
      });
    },
    doneTasks: function() {
      return this.todos.filter(function(el) {
        return el.done;
      });
    }
  },
  methods: {
    changeFilter(newFilter) {
      this.currentFilter = newFilter;
    },
    addTask: function() {
      const todo = { task: this.inputTask, done: false };
      this.todos.push(todo);
      this.inputTask = "";
    },
    deleteTask: function(index) {
      this.todos.splice(index, 1);
    },
    getTasksList() {
      switch (this.currentFilter) {
        case "ongoing":
          return this.ongoingTasks;
        case "done":
          return this.doneTasks;
        case "all":
        default:
          return this.todos;
      }
    }
  }
};
</script>

I trust this will be beneficial to your situation!

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

The JSON information is not appearing as expected

Utilizing a jQuery function, I am attempting to access a JSON file: $.ajax({ type: 'GET', url: '/data/coffee.json', dataType:'json', success: function(data) { let widget = displayData(data); $(" ...

Unable to use jQuery to delete class from an element

Here is the markup I am working with: <div class="row"> <img src="image.png" class="download-image regular-image" /> <div class="options"> <p>download</p> </div> <img src="image.png" class="download-image r ...

Tips for securely closing express servers to ensure that ports are properly released

One problem I have noticed, particularly on Mac computers, is that when I shut down a Node server using "CTRL + Z," the server stops running but the ports remain occupied. What is the correct method to close a server in order to release the ports and be a ...

Efficiently Extract and Append Unknown Nested JSON Values into an Array using JavaScript

It's puzzling why I'm finding this challenging. It seems like there should be a solution using Lodash or a similar tool. My object is structured like this: { "fdjkafdajkfasfjkdaslj": { "-LMUD-2APhiSLkEtVbM": { "profileName": "bo ...

What role does JavaScriptExecutor play within the Selenium framework?

Can you explain the concept of JavaScript Executor in Selenium WebDriver? How is it utilized and what are some practical applications within Selenium WebDriver? Please provide an illustrative example for better understanding. ...

Is it possible to incorporate the arrow function within the debounce function?

export const debounce = (callback: Function, ms = 300) => { let timeoutId: ReturnType<typeof setTimeout> return function (...args: any[]) { clearTimeout(timeoutId) timeoutId = setTimeout(() => callback.apply(this, args), ms) ...

When the file is active on a local machine, the bot commands run smoothly. However, these commands do not execute on a remote

Lately, while working on coding a discord bot using discord.js, I came across an issue. Whenever I run my bot on my local machine, all the commands work perfectly fine. However, after committing and pushing the code to GitHub, and then allowing buddy.works ...

How come my Angular JS isn't functioning properly?

I am trying to use AngularJS to replace specific text with defined text. Here is my HTML: <!DOCTYPE html> <html> <head> <title>Directive</title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/ ...

Display a message to a user on the same HTML page using jQuery or JavaScript

How can I show a message to the user on the HTML page confirming their selected date without using an alert box? I attempted this code snippet, but I'm uncertain: document.writeln("The date you picked is: " + dateText); ...

The function call within the onKeyPress event in ReactJS isn't triggering

After entering a search string and hitting enter in the code below, I noticed that this becomes undefined causing the function not to be called. Can anyone shed some light on why this is happening? I've exhausted all my options without any success, an ...

How can I apply a class to a list item when clicked using Vue.js and a template component generated by v-for loop?

I'm struggling to add an active class to a list item in a template component when it's clicked, making sure that only one item can have the class at a time. I've attempted different solutions such as passing a new data object on click and r ...

Using Ngrx to filter data following an action dispatch

I have a method for dispatching an action to query and select the account. I am unsure if this is the most efficient approach for selecting the data post-dispatch. this._store.dispatch(AccountsPageActions.loadAccountWithDetails({ accountId: this._accountId ...

Which RxJS operators necessitate unsubscription?

It can be confusing to know which operators in RxJS must be unsubscribed from to prevent subscription leaks. Some, like forkJoin, complete automatically, while others, such as combineLatest, never complete. Is there a comprehensive list or guideline availa ...

Creating a tool for arranging furniture, seeking guidance on best practices

Creating a web application that operates mostly on the client side with data processing and storage on the server side using PHP/MySQL. The app allows users to add various pieces of furniture to a room, represented by simple shapes like rectangles and squa ...

Using PHP, assign a reference to a class member

Trying to create a JSON server response in PHP has been quite the task. Using an array in my output to monitor errors and successes within the script has been helpful. Take a look at the code snippet below for a better understanding. <?php $output = ar ...

Express.js failing to send back a response

After attempting this process numerous times, I am puzzled by the behavior of my code in this particular scenario. The situation involves sending login credentials from a webpage to an express server: async function request(url, data) { data = JSON.strin ...

The footer is now accompanied by the <v-navigation-drawer> on the side

I am looking for a way to dynamically adjust the height value of a style applied to an element based on certain conditions. Specifically, when scrolling to the bottom, I want the height to be 77.5%, when the footer is not visible at all, it should be 100%, ...

No content found in the responseText when sending an XMLHttpRequest

I am facing an issue where the alert is blank when I send a request. The files are being uploaded successfully, but there is no response text being displayed. Is there something wrong with my code below? var request = new XMLHttpRequest(); request.open( ...

I am unable to click on the navigation buttons in my bootstrap template

I've been working on turning a single page Bootstrap template into a multi-page layout. I duplicated the index page and modified them into services, among other things. Although I updated the href to point to these new pages, the navbar buttons are no ...

What is the best way to fill in a property for a mongoose schema?

let newPost = new Post({ content: fields.content, creator: req.user, }); newPost.save(function(error) { if(error) { res.status(501).json({ error: error }); } else { res.json({ post: newPost }); } }); The post model has a field called cr ...