baryjones23saturn
baryjones23saturn

Reputation: 81

Filtering multiple input fields

I'm trying to create a filter with javascript with 4 input fields so I'm guessin 16 combinations of possible searches. I can search all 4 at once or 1 input at a time but for some reason when I add other statements I get wierd results. Is there a better way to implement a filter?

var unfilteredFloorplans = floorplanJSON.floorplanData;

filteredFloorplans = [];

for (var i = 0; i < unfilteredFloorplans.length; i++) {

    if (unfilteredFloorplans[i].city == req.body.cityName && 
        unfilteredFloorplans[i].building == req.body.buildingName && 
        unfilteredFloorplans[i].bedrooms == req.body.minBedroom && 
        unfilteredFloorplans[i].baths == req.body.maxBathroom) {

           console.log(unfilteredFloorplans[i].city);
           filteredFloorplans.push(unfilteredFloorplans[i]);
    } 
}

So now I need to write 15 more if statements? Rather than copy them in I'd like to ask if this is correct and does anyone know how you could implement this with a switch statement?

Edit: And when I say 15 more statements I mean one for if they just pick city, andother if they pick city and bedrooms etc. It just seems inefficient

Upvotes: 0

Views: 2830

Answers (2)

General_Twyckenham
General_Twyckenham

Reputation: 2261

Here's a simplified example of what your code may look like (in this example, I hardcoded the values representing the input choices):

var unfilteredFloorplans = [{
  city: 'NY',
  building: 'A',
  bedrooms: 2,
  baths: 1,
}];


var filteredFloorplans = unfilteredFloorplans.filter(
  function(el) {
    return el.city === 'NY' && el.building === 'A' && el.bedrooms >= 1 && el.baths >= 1;
  }
);

console.log(filteredFloorplans);

The anonymous function being called inside the filter can be replaced with a named function like so:

function filterFloorplans(floorplan) {
  return floorplan.city === 'NY' && floorplan.building === 'A' && floorplan.bedrooms >= 1 && floorplan.baths >= 1;
}

var filteredFloorplans = unfilteredFloorplans.filter(filterFloorplans);

You'll likely want to use this route since you can have any combination of the 4 input choices. As such, you'll want the filterFloorplans function to be "built-up" from other, smaller checks:

function testCity(userInputCity, floorplanCity) {
    return userInputCity ? userInputCity === floorplanCity : true;
}

function filterFloorplans(floorplan) {
  return testCity('NY', floorplan.city) && floorplan.building === 'A' && floorplan.bedrooms >= 1 && floorplan.baths >= 1;
}

This should be enough to get you started; feel free to comment if you get stuck

Upvotes: 0

vog
vog

Reputation: 25647

A minimal fix would be to combine your "and" with "or", but note how this turns the code into a hard-to-read mess:

var unfilteredFloorplans = floorplanJSON.floorplanData;

filteredFloorplans = [];

for (var i = 0; i < unfilteredFloorplans.length; i++) {

    if ((req.body.cityName == '' || unfilteredFloorplans[i].city == req.body.cityName) && 
        (req.body.buildingName == '' || unfilteredFloorplans[i].building == req.body.buildingName) && 
        (req.body.minBedroom == '' || unfilteredFloorplans[i].bedrooms == req.body.minBedroom) && 
        (req.body.maxBathroom == '' || unfilteredFloorplans[i].baths == req.body.maxBathroom)) {

           console.log(unfilteredFloorplans[i].city);
           filteredFloorplans.push(unfilteredFloorplans[i]);
    } 
}

(BTW, this looks like a good exercise for combining conjunctions with disjunctions.)

Edit I'd recommend to put the filtering into a separate function, and to introduce an additional helper function. Also, use a more consistent naming and use "===" instead of "==".

function filterByEquality(formValue, dataValue) {
    if (formValue === '') return true;
    if (formValue === dataValue) return true;
    return false;
}

function filterFloorplan(form, data) {
    if (!filterByEquality(form.city, data.city)) return false;
    if (!filterByEquality(form.building, data.building)) return false;
    if (!filterByEquality(form.minBedrooms, data.bedrooms)) return false;
    if (!filterByEquality(form.maxBathrooms, data.bathrooms)) return false;
    return true;
}

var unfilteredFloorplans = floorplanJSON.floorplanData;
filteredFloorplans = [];
for (var i = 0; i < unfilteredFloorplans.length; i++) {
    if (filterFloorplan(req.body, unfilteredFloorplans[i]);
        console.log(unfilteredFloorplans[i].city);
        filteredFloorplans.push(unfilteredFloorplans[i]);
    } 
}

You can reduce this code even further by learning about the Array.filter method. And you should fix the bug where for some fields should use ">=" or ">=" instead of "===". But I'll leave those things as an exercise.

Upvotes: 2

Related Questions