stepheniok
stepheniok

Reputation: 405

React- Filter array based on search and dropdown values

I have a page that is displaying a list of article titles. On this page, I've added a search bar and a drop-down menu to be able to filter through this array. onChange of the input field for the search I am calling setSearchTerm. I also have a drop-down filter menu for All, True and False there is an object completed in this array. Upon clicking true/or false it filters and returns based on if the article is completed or not.

Individually they are both functioning as expected, but I am having issues coming up when I am getting them both to work together. I would like to be able to search within the filtered article titles. For example. If I select "True" I would like to be able to search through all "True" articles. So the array would be filtered by both the drop-down value "True" and the words typed into the search bar.

This is where I am struggling with:

  } else if (searchTerm != "" && filter != "") {
            console.log('here')

           // return what includes the search term
            val.title.toLowerCase().includes(searchTerm.toLowerCase())
            return val
          }

With the logic, I am expecting when searching and filter are both not empty, to return what matches with the search term. At the moment, there is nothing being returned when both the drop-down and search is used.

Here is the entire logic set up:

 let posts =  articles.filter((val) => {
  // if search is empty and if "all" or nothing is selected return the entire array
  if (searchTerm == "" && filter == "" || filter == "all") {
    return val

 // if the filter is not selected, return whats included with the search term 
  } else if (filter == "" && val.title.toLowerCase().includes(searchTerm.toLowerCase())) {
      return val

 // if search is empty and filter drop down value exists return what matches with the filter 
  } else if (searchTerm == "" && val.completed.toString().includes(filter)) {
    return val

 // if there neither are empty do logic here
  } else if (searchTerm != "" && filter != "") {
    console.log('here')

   // return what includes the search term
    val.title.toLowerCase().includes(searchTerm.toLowerCase())
    return val
  }
})

Here is my full code snippet:

 import { useState, useEffect } from 'react';

const Posts = ({ articles }) => {
 

  const [searchTerm, setSearchTerm] = useState("");
  const [filter, setFilter] = useState("")

      let posts =  articles.filter((val) => {
  // if search is empty and if "all" or nothing is selected return the entire array
  if (searchTerm == "" && filter == "" || filter == "all") {
    return val

 // if the filter is not selected, return whats included with the search term 
  } else if (filter == "" && val.title.toLowerCase().includes(searchTerm.toLowerCase())) {
      return val

 // if search is empty and filter drop down value exists return what matches with the filter 
  } else if (searchTerm == "" && val.completed.toString().includes(filter)) {
    return val

 // if there neither are empty do logic here
  } else if (searchTerm != "" && filter != "") {
    console.log('here')

   // return what includes the search term
    val.title.toLowerCase().includes(searchTerm.toLowerCase())
    return val
  }
})


 return (
      <> 
<select value={filter} onChange={(event) => {setFilter(event.target.value)}} className="dropmenu dropdown-menu"> 
    <option value="">All</option>
                <option value="true">True</option>
                <option value="false">False</option>

    </select>
       <input
        type="text"
        placeholder="Search..."
        onChange={(event) => {
          setSearchTerm(event.target.value);
        }}
      />
       <h1>h1</h1>
    <ul className='list-group mb-4'>
      {posts && posts.map(post => (
        <li key={post.id} className='list-group-item'>
          {post.title}
        </li>
      ))}
    </ul>
   
    </>

  );
};

export default Posts;

How can I set up this condition to where the user can search when the articles are filtered by True or False?

Articles array:

const articles = [{"title": "title one", completed: false}, 
{"title": "article two", completed: true}, 
{"title": "testing three", completed: false}, 
{"title": "title four", completed: false}, 
{"title": "title five", completed: true}] 

Upvotes: 1

Views: 4136

Answers (2)

Hossam Tarek
Hossam Tarek

Reputation: 164

All you need to do is add this line in the last case like this

else if (searchTerm !== "" && filter !== "") {
    console.log('here')
   // return what includes the search term
    if(val.title.toLowerCase().includes(searchTerm.toLowerCase()) && val.completed.toString().toLowerCase().includes(filter.toLowerCase()))
      return val
  }

what it basically does is check if completed property in val is equal to filter and searchTerm is equal to title I just combined your logic but it code be a little neater by doing this

else if (val.title.toLowerCase().includes(searchTerm.toLowerCase()) && val.completed.toString().toLowerCase().includes(filter.toLowerCase())) {
   // return what includes the search term
      return val
  }

since it won't reach this else if and only if searchTerm and filter are both != "" so I just moved the inside condition to the else if

Upvotes: 0

knicholas
knicholas

Reputation: 530

Following your original format, just move the conditional into the if statement

} else if (searchTerm != "" && filter != "" && 
              val.title.toLowerCase().includes(searchTerm.toLowerCase())) {
            console.log('here')

           // return what includes the search term
            
            return val
          }

Upvotes: 2

Related Questions