What is the best way to implement date range filtering in vue js?

Currently, I am delving into the realm of vue.js and experimenting with a filtering feature that involves date ranges. The process goes like this: initially filter by type, then proceed to filter by a specified date range, consisting of start and end dates. The search results are expected to show up once the end date has been selected. While I have successfully implemented the first part of the filter for types and it is functioning correctly, I am encountering challenges when trying to implement the date range filter. I have scoured through various resources but haven't yet found the ideal solution. How can I effectively filter date ranges using either 'computed' or 'methods'? If anyone out there possesses the knowledge on this subject matter, could you please provide me with a detailed, step-by-step guide?

 // Vue.js code snippet here... 
 // CSS code snippet here... 

Answer №1

One way to resolve this issue is:

  1. Initialize startDate and endDate as Date objects. Keep in mind that the date picker uses an ISO string format (yyyy-mm-dd), which is in UTC. However, the data provides dates in locale-specific format (mm/dd/yyyy). To ensure consistent time zone offsets, normalize the dates before comparing them:

    methods: {
      localizeDate(date) {
        if (!date || !date.includes('-')) return date
        const [yyyy, mm, dd] = date.split('-')
        return new Date(`${mm}/${dd}/${yyyy}`)
      }
    }
    
    let startDate = this.localizeDate(this.startDate);
    let endDate = this.localizeDate(this.endDate);
    
  2. In your if-else statements, you are checking for null explicitly. Since you're creating Date instances, they won't be null. After implementing step 1, the dates will either be a valid Date object or false. Update your comparisons to check for falsy values instead of null:

    if (startDate && endDate) {/*...*/}
    if (startDate && !endDate) {/*...*/}
    if (!startDate && endDate) {/*...*/}
    
  3. The variable selectedType will never be null, but you can check if it's falsy to determine if the type is unspecified. If it is unspecified, you can return the original array without filtering it unnecessarily:

    const itemsByType = filterType ? this.items.filter(item => item.type === filterType) : this.items
    
  4. To display the date in the format MMM dd, yyyy, you can utilize the "long" date style provided by Intl.DateTimeFormat. Implement this functionality in a component method and call it from the template:

    methods: {
      formatDate(date) {
        return new Intl.DateTimeFormat('en-US', { dateStyle: 'long' }).format(new Date(date))
      }
    }
    
    <p>Date: {{ formatDate(item.date) }}</p>
    

new Vue({
  el: '#app',
  data: {
    selectedType: '',
    startDate:null,
    endDate:null,
    items: [
      {
        name: 'Nolan',
        type: 'mercedes',
        year: '2020',
        country: 'england',
        date: '08/01/2020'
      },
      {
        name: 'Edgar',
        type: 'bmw',
        year: '2020',
        country:'belgium',
        date: '08/11/2020'
      },
      {
        name: 'John',
        type: 'bmw',
        year: '2019',
        country: 'england',
        date: '08/21/2020'
      },
      {
        name: 'Axel',
        type: 'mercedes',
        year: '2020',
        country: 'england',
        date: '08/01/2020'
      }
    ]
  },
  computed: {
    filterItem() {
      let filterType = this.selectedType;
      let startDate = this.localizeDate(this.startDate);
      let endDate = this.localizeDate(this.endDate);
      
      const itemsByType = filterType ? this.items.filter(item => item.type === filterType) : this.items
      return itemsByType
        .filter(item => {
          const itemDate = new Date(item.date)
          if (startDate && endDate) {
            return startDate <= itemDate && itemDate <= endDate;
          }
          if (startDate && !endDate) {
            return startDate <= itemDate;
          }
          if (!startDate && endDate) {
            return itemDate <= endDate;
          }
          return true;
        })
    }
  },
  methods: {
    localizeDate(date) {
      // Normalize ISO format dates from date picker with locale specific format provided in the data
      // For comparison with local timezone
      if (!date || !date.includes('-')) return date
      const [yyyy, mm, dd] = date.split('-')
      return new Date(`${mm}/${dd}/${yyyy}`)
    },
    formatDate(date) {
      return new Intl.DateTimeFormat('en-US', { dateStyle: 'long' }).format(new Date(date))
    }
  }
})
.list-item {
  margin-top: 50px;
}

.card {
  box-shadow: 0px 10px 16px rgba(0, 0, 0, 0.16);
  width: 400px;
  padding: 20px 30px;
  margin-bottom: 30px;
}

select,input {
  border: none;
  padding: 10px 15px;
  background-color: #c1c1c1;
  border-radius: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <label for="">Type</label>
  <select v-model="selectedType">
    <option value="" disabled selected hidden>Type</option>
    <option value="mercedes">Mercedes</option>
    <option value="bmw">BMW</option>
  </select>
  
  <label for="">From</label>
  <input type="date" v-model="startDate">
  
  <label for="">To</label>
  <input type="date" v-model="endDate">
  
  <div class="list-item" v-for="item in filterItem">
    <div class="card">
      <p>Name: {{ item.name }}</p>
      <p>Car: {{ item.type }}</p>
      <p>Date: {{ formatDate(item.date) }}</p>
      <p>Country: {{ item.country }}</p>
    </div>
  </div>
</div>

Answer №2

This particular inquiry pertains more to JavaScript rather than Vue.js. It is recommended to utilize the Date type instead of the string type for date data. For instance,

new Date('2020-01-01') < new Date('2020-01-02')
evaluates to true

  computed: {
    filterItem: function () {
      const filterType = this.selectedType  // string or null
      const startDate = this.startDate;    // Date or null
      const endDate = this.endDate;  // Date or null
      
      return this.items.filter(item => {
        if (filterType === null) return true;  // when filterType not selected
        return item.type == filterType;
      }).filter(item => {
        const itemDate = new Date(item.date)
        if (startDate !== null && endDate !== null)) {
          return startDate <= itemDate && itemDate <= endDate;
        }
        if (startDate !== null && endDate === null) {
          return startDate <= itemDate;
        }
        if (startDate === null && endDate !== null) {
          return                          itemDate <= endDate;
        }
        return true;  // when neither startDate nor endDate selected
      })
    }

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

Visual Studio Code encounters a JavaScript NPM error that is causing unexpected issues

When using Visual Studio Code, I want my JavaScript program to automatically run through a server as I am learning online. I followed the steps from a tutorial on setting up my IDE and installed Git and Node. Now, when I open Visual Studio and save my Hel ...

Automatically navigate to a specific element as the user scrolls down the page

I am attempting to achieve a similar effect as seen on the App Builder Website. When the user reaches the header with the background image/video and scrolls down, the website smoothly transitions to the next div/section. If the user scrolls back up and ret ...

How to eliminate ampersands from a string using jQuery or JavaScript

I'm having trouble with a seemingly simple task that I can't seem to find any help for online. My CSS class names include ampersands in them (due to the system I'm using), and I need to remove these using jQuery. For example, I want to chan ...

How can you create a table cell that is only partially editable while still allowing inline JavaScript functions to work?

Just a few days back, I posted a question similar to this one and received an incredibly helpful response. However, my attempt at creating a table calculator has hit a snag. Each table row in a particular column already has an assigned `id` to transform t ...

Vue alert: A duplicate key with the value of '10' has been identified. This could potentially lead to an issue with updates

I've been encountering a persistent error that I can't seem to resolve: [Vue warn]: Duplicate keys detected: '10'. This issue is causing an update error in my application. Despite trying the following steps, the error continues to appe ...

When I include scroll-snap-type: y; in the body tag, the scroll-snapping feature does not function properly

Hey there! I've been trying to implement scroll-snapping on my project but unfortunately, I couldn't get it to work. I tested it out on both Chrome and Firefox, but no luck so far. Here's the code snippet I've been working with, would a ...

Conceal form upon submission with jQuery

Is it possible to have a html form inside a table and then hide it once the form is submitted? The Form: <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <tr> <td colspan="3"> <h ...

When implementing 'useGlobalGuards' in NestJS, remember to exclude endpoints for enhanced security

After implementing the useGlobalGuards method in my main.ts file, all endpoints now utilize the AuthGuard. This guard triggers a 401 error if a valid auth token is not present in the request header. Previously, I used @UseGuards(AuthGuard) on individual cl ...

The Null object within localStorage is identified as a String data type

As someone transitioning from Java development to Javascript, I am seeking clarification on a particular issue. In my project, I am utilizing localStorage to keep track of the user's token in the browser. localStorage.token = 'xxx' When a ...

Passing a unique data value from Ajax to PHP using Ajax and PHP techniques

Currently, I'm working with Google Charts to set up various line charts. These charts are using data from a MySQL database, which is retrieved through an Ajax call to a PHP script. Right now, I have everything working smoothly by manually inputting t ...

Is there a way to programmatically select an HTML tab or filter in puppeteer?

I am currently developing a web scraping application for a website that utilizes tab headers to filter the contents of a table. In order to extract the data from the table, I need to first select a specific filter by clicking on a tab item. However, I&apos ...

Convert items to an array utilizing lodash

I need assistance converting an object into an array format. Here is the input object: { "index": { "0": 40, "1": 242 }, "TID": { "0": "11", "1": "22" }, "DepartureCity": { "0": "MCI", "1": "CVG" }, "ArrivalCity": { ...

Design a model class containing two arrow functions stored in variables with a default value

I am looking to create a model class with two variables (label and key) that store functions. Each function should take data as an input object. If no specific functions are specified, default functions should be used. The default label function will retur ...

instructions for executing this javascript within the <p> tag

This is the code I have written : <p onload=javascript:alert('sss')>www</p> Unfortunately, the code does not alert 'sss', Can someone please tell me what's wrong with my code? Thank you ...

Looking to parse and iterate over JSON data retrieved from a query using Express and Jade?

As a newcomer to nodejs, I am facing an issue with passing JSON data from a select query to the Jade view. Using Node.js Tools for Visual Studio and Express + Jade in my project, here is a snippet from my index.js file: exports.products = function (req, r ...

Prevent the display of hyperlinks in the status bar when hovering over a hyperlink or button

The application I'm working on has a default status bar at the bottom of each screen that displays URLs linked to buttons and icons. For example: https://i.stack.imgur.com/ZFTsp.jpg I am trying to prevent the display of URLs associated with hyperlin ...

vuejs default properties initialized with vue-i18n

I am trying to establish a default property from a dictionary in this way: props: { title: { type: String, default: this.$t("basic.confirm"), }, description: { type: String, } }, ... The $t function is part of the vu ...

Illuminated Box with Text Beneath Image Overlay

Is there a way to customize the text displayed under each zoomed-in image even further, using images, etc. instead of just relying on the alt text? An ideal solution would involve displaying the text in a div. You can find the codepen here: // Looking ...

Transferring information between two tables in a MongoDb database

My current database in mongo is named "sell" and it contains two tables: "Car" and "Order". In the "Car" table, there is an attribute called "price". When I run the following command in the mongo shell: db.Order.aggregate([ { $lookup: { from: ...

What is the most effective method for transferring and accessing data within a child form component?

This is how I am currently handling it: Parent.vue: // Template <form-child :schema="schema"><form-child> // JS data () { return { schema: [{ // name: '', value: '', type: '' }, { //etc ... }] } } For ...