Filter Vue JS search results using an array of checkboxes

Recently, I created a custom Vue JS search feature for filtering properties on a real estate website. This search component is displayed on every page, so I decided to utilize a URL search query approach. By extracting the search parameters using this.$route.query.search, I was able to retrieve and store the values in variables.

The property data is sourced from a JSON file structured as shown below:


{
  "data": [
    {
      "id": 12,
      "sold": false,
      "isFeatured": true,
      "slug": "green-park-talbot-green-cf72-8rb",
      "address": "Green Park, Talbot Green CF72 8RB",
      "county": "Rhondda Cynon Taf",
      "price": "695000",
      "features": ["Modern fitted kitchen", "Integrated appliances", "Front and rear gardens"],
      "type": "Semi-Detached",
      "bedrooms": "3"
    }
}

An example of my search query is as follows:

/properties/?search=Address%20Here&type=Apartment&bedrooms=2&county=Maesteg

This query allows for precise filtering.

To filter the properties effectively, I initialized variables within my data object to store each query parameter like this:

data () {
    return {
      searchAddress: this.$route.query.search,
      searchType: this.$route.query.type,
      searchBedrooms: this.$route.query.bedrooms,
      searchCounty: this.$route.query.county
    }
}

Moreover, I implemented a filter in the computed properties section named filteredProperties to refine the properties displayed in the v-for:

computed: {
    filteredProperties: function(){
      return this.properties.filter((property) => {
        return property.address.match(this.searchAddress) && property.type.match(this.searchType) && property.bedrooms.match(this.searchBedroom
s) && property.county.match(this.searchCounty)
      });
    }
  }

Moving forward, I now aim to replace the current <select> dropdown menu used for selecting property types with checkboxes, allowing users to choose multiple types concurrently. However, I am uncertain about modifying this particular aspect of my filtering mechanism which currently compares against a single property type:

property.type.match(this.searchType)

I appreciate any assistance or insights provided. Thank you.

Update:

In recent attempts to enhance my filter functionality, I made the following adjustments:

computed: {
    filteredProperties: function(){
      return this.properties.filter((property) => {

        return property.address.match(this.searchAddress) &&
        this.searchAddress.some(function(val){
          return property.search.match(val)
        }) &&

        property.type.match(this.searchType) &&
        this.searchType.some(function(val){
          return property.type.match(val)
        }) &&

        property.bedrooms.match(this.searchBedrooms) &&
        this.searchBedrooms.some(function(val){
          return property.bedrooms.match(val)
        }) &&

        property.county.match(this.searchCounty) &&
        this.searchCounty.some(function(val){
          return property.county.match(val)
        })

      });
    }
  }

I need the search functionality to work seamlessly whether a URL query is present or not.

Furthermore, I experimented with an if/else statement:

computed: {
    filteredProperties: function(){
      return this.properties.filter((property) => {
        return property.address.match(this.searchAddress) &&

        if (this.searchType.length > 1) {
          this.searchType.some(function(val){
            return property.type.match(val)
          })
        } else {
          property.type.match(this.searchType)
        } &&

        property.bedrooms.match(this.searchBedrooms) &&
        property.county.match(this.searchCounty)
      });
    }
  }

Update:

After making adjustments, the filter function now operates as intended:

computed: {
    filteredProperties: function(){
      return this.properties.filter((property) => {

        let searchTypeMatch;

        if (typeof this.searchType === "object") {
          searchTypeMatch = this.searchType.some(function(val){
            return property.type.match(val)
          })
        } else {
          searchTypeMatch = property.type.match(this.searchType)
        }

      return property.address.match(this.searchAddress) &&
        searchTypeMatch &&
        property.bedrooms.match(this.searchBedrooms) &&
        property.county.match(this.searchCounty)
      });
    }
  }

Answer №1

Serialize and deserialize arrays using JSON when working with query parameters.

data () {
    return {
      searchAddress: this.$route.query.search ? JSON.parse(this.$route.query.search) : [],
      searchType: this.$route.query.type ? JSON.parse(this.$route.query.type) : [],
      searchBedrooms: this.$route.query.bedrooms ? JSON.parse(this.$route.query.bedrooms) : [],
      searchCounty: this.$route.query.county ? JSON.parse(this.$route.query.county) : []
    }
}
computed: {
    filteredProperties: function()
    {
      return this.properties.filter((property) => 
      {
        return (this.searchAddress.length ? this.searchAddress.some((address) =>
        {
          return property.address.match(address);
        }) : true) && (this.searchType.length ? this.searchType.some((type) =>
        {
          return property.type.match(type);
        }) : true) && (this.searchBedrooms.length ? this.searchBedrooms.some((bedrooms) =>
        {
          return property.bedrooms.match(bedrooms);
        }) : true) && (this.searchCounty.length ? this.searchCounty.some((county) =>
        {
          return property.county.match(county);
        }) : true)
      });
    }
  }

Use the following format to send query parameters:

this.$router.push("/search?search=" + JSON.stringify(searchArray) 
  + "&type=" + JSON.stringify(typeArray)
  + "&bedrooms=" + JSON.stringify(bedroomsArray)
  + "&county=" + JSON.stringify(countyArray)
);

Answer №2

I haven't had the chance to work with routing in Vue apps, but for this code snippet to function properly, it's important to ensure that this.$route.query.search (and other route properties) is an empty array.

return this.searchAddress.some(function(val) {
    return property.address.match(val)
}) && 
this.searchType.some(function(val){
    return property.type.match(val)
}) && ...

Please let me know if this solution works for you.

RE-EDITED:

Hello, please update the computed property as shown below

computed: {
    filteredProperties: function () {
        let self = this
        let routeConstraints = ['search', 'type', 'bedrooms', 'county'].filter(function (val) {
            return self.$route.query[val] !== undefined
        })
        if (routeConstraints.length === 0) {
            return self.properties
        } else {
            return routeConstraints.reduce(function (acc, val) {
                return acc.filter(function (property) {
                    //checking if there's a match between query parameters and properties
                    if (self.$route.query[val] !== undefined) {
                        //check if the route parameter is an array (object)
                        if (typeof this.searchType === "object") {
                            self.$route.query[val] = [self.$route.query[val]]
                        }
                    }
                    return self.$route.query[val].some(function (item) {
                        //updated the matching condition to indexOf
                        return property[val].match(item).length > 0
                    })
                })
            }, self.properties)
        }
    }
}

In essence,

  1. I'm verifying which route values are selected based on your checkbox choices
  2. Using them to filter the properties array
  3. If none are selected, all properties are returned

Hoping this resolves the issue.

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

Generating an HTML table using an array retrieved from a PHP execute_db function, displaying repeated entries

My goal is to dynamically populate an HTML table with data retrieved from a SQL query. The structure of the table, including headings, should adjust based on user selections, reflecting the results of the query. While searching for a solution, I came acros ...

How can I generate a bounding box with CSS?

I am a newcomer to vue.js and I have a question about creating a bounding box for any element. This bounding box resembles a view box in svg. For example, I have created a checkbox like this one: checkbox Below is the code to style the checkbox: /* checkb ...

How does one distinguish between the uses of "any" and "any[ ]"?

Exploring the Difference Between any and any[ ] An Illustrative Example (Functioning as Expected) variable1: any; variable2: any[]; this.variable1 = this.variable2; Another Example (Also Functioning as Intended) variable1: any; v ...

Stay connected with AJAX's latest updates on Twitter with just 13 bytes

Twitter sends a POST request of only 13 bytes when someone follows an account. This small amount of information helps to reduce latency and server load, providing advantages for web developers. However, removing unnecessary cookies and extra information f ...

parse JSON data in a MySQL query

I'm aware of the possibility of duplicated questions, but I couldn't find any solutions to help me with my specific situation. In one of my MySQL columns, I have a JSON structure as shown below: [ { "ddi": "55", &qu ...

An issue arises when using JSON.parse() with regular expression values

I am encountering an issue with parsing a JSON string encoded with PHP 5.2 json_encode(). Here is the JSON string: {"foo":"\\."} Although this JSON string is valid according to jsonlint.com, when using the native JSON.parse() method in Chrome a ...

The combination of AddEventListener in the parent and postMessage in the iframe is ineffective

As I delve into the Stripe documentation to develop a new feature, I have encountered an issue regarding the communication between a webpage and an iframe. The code in index.html: <!DOCTYPE html> <body> parent<br> <iframe src="./ ...

Attempting to create a button that will only appear for items with a defined value for a specific variable

I am currently facing an issue with a template that needs proper population. The store locator on my website lists pharmacies and displays their relevant information (phone number, address, hours of operation) along with three buttons (view store, view fl ...

Fatal Error in PHP WordPress - A catchable fatal error occurred, indicating that an object of the WP_Term class could not be converted to

I'm currently working on a WordPress website that has a child theme which throws an error when attempting to log in. The parent theme is Genesis. Everything was functioning correctly just a week ago, and I'm struggling to identify the issue with ...

The implementation of CORS headers does not appear to function properly across Chrome, Firefox, and mobile browsers

I encountered an issue while trying to consume a third party's response. The functionality works correctly in Internet Explorer, but fails in Chrome, Firefox, and on my mobile browser. Despite searching online and testing various codes, I continue to ...

"Unexpected discrepancy: Bootstrap Glyphicon fails to appear on webpage, however, is visible

I am having some trouble getting the glyphicon to display properly in my side nav. The arrow head should rotate down, which is a pretty standard feature. Here is the link to the page: The glyphicon should be visible on the "Nicky's Folders" top leve ...

Restrict Vue Router access to specific pages only

Once a user has logged in for the first time, they are directed to the CreateProfile page where they can enter their profile information. I want to restrict access to this page so that if the user manually types the URL into their browser (e.g. www.myproje ...

Leverage the power of JSON objects within your Angular.js application

Is it possible to request a JSON object, such as the one in employes.json file: {"employees":[ {"firstName":"John", "lastName":"Doe"}, {"firstName":"Anna", "lastName":"Smith"}, {"firstName":"Peter", "lastName":"Jones"} ]} Then, how can I util ...

Is it possible to iterate through HTML elements without relying on forEach()?

Currently working on my web-based system using Node.js and HTML. Are there any alternative ways to iterate through HTML elements without using forEach? I'm considering something like this (for example): <% for(var ctr=0; ctr<arrayname.length ...

Employing a script that is generated from the jQuery AJAX response

How does using script as the response for a jQuery/AJAX request benefit us? Is it possible to directly run a function from that response script after sending the AJAX request? Any simple examples would be much appreciated. ...

Node.js bulk deletion in CouchDB

Utilizing the Cloudant node module, I am making modifications to my Cloudant database by sending a set of documents to the db.bulk(params,callback) function. { docs: [ { "_id": "...", "_rev": "...", "_deleted": true }, { "_id": "...", ...

Double Marker Challenge in Brochure

I am currently using Leaflet in conjunction with VueJs. I have encountered an issue where a double marker is appearing at a specific location when I add a marker: The code responsible for this behavior is as follows: mounted() { this.map = L.ma ...

Crafting jQuery Plugins with Object-Oriented Programming

Curious about the latest techniques for creating jQuery Plugins? There are so many different methods out there, it's hard to know which one is most effective. Could you recommend any helpful resources or templates for developing jQuery Plugins using ...

Developing a realtime search feature using AJAX and CodeIgniter

Attempting to implement a live search feature in CodeIgniter for the first time. As a newcomer to web development, still in the learning process. Came across a tutorial on how to achieve this here. Struggling with adapting the code from the tutorial to fi ...

Ways to block WebSocket access on a personal computer

Is it possible to protect my server resources from being accessed by other websites, such as example.com, via WebSocket? I want to prevent them from accessing the server using a URL like "ws://47.80.151.189:1234", and utilizing its resources (bandwidth, me ...