2

I'm quite new to ReactJS and work on a simple application which shows many different data (called apps). I want to implement a live free text search-filter. For that I'm using an Input Element, calling a JavaScript function if the value is changing. It's working quite good. But only for one string. If I want to filter for more words it's handled as an "AND" filter. But I want an "OR" filter.

I have the apps and filter them with a searchString. The User has to input at least three characters. If the user enters two words with three characters f.e. 'app' and 'red', I want to filter for the elements which has the words 'app' OR 'red' in the title. If min. one of the filter-strings matches, the app is shown. That's the plan.

I tried with .indexOf(), .includes() and nothing matches, even in the documentation I found nothing like an "OR" filter-search.

Here is my code, working for one string:

  updateSearch(event) {
    let searchString = event.target.value.toLowerCase()

    let searchStringSplit = searchString.split(/(\s+)/).filter( function(e) { return e.trim().length >=3; } ); //Only words with at least 3 chars are allowed in the array

    if (searchString.length >= 3) { //Check if the minimun amount of characters is fullfilled

      let allApps = this.props.applications;
      let apps = allApps.filter(app =>
        app.title.toLowerCase().includes(searchString)
      );
      this.props.updateApplications(apps);
    } else {
      this.clearSearch()
    } 
  }

my Input element:

 <Input
      id="freeTextSearch"
      className="searchInput"
      onChange={this.updateSearch.bind(this)}
      autoComplete="off"
      action={
        <Button
          id="freeTextSearchButton"
          name="search"
          icon="search"
          onClick={() => this.clearSearch()}
        />
      }
      placeholder="Search"
    />

Thanks for the help Yvonne

ANSWER:

Thank you 'Silvio Biasiol'. Your Solution gave me the right hint. Now I have an 'OR' filter-search matching at least one word. The function now looks like:

updateSearch(event) {
  let searchString = event.target.value.toLowerCase()
  let searchStringSplit = searchString.split(/(\s+)/).filter( function(e) { return e.trim().length >=3; } )

  if (searchStringSplit.length >=1) { //Check if there is at least on word with tree letters

    let allApps = this.props.applications
      // If at least a word is matched return it!
    let apps = allApps.filter(app => {
      let containsAtLeastOneWord = false
        searchStringSplit.forEach(searchWord => {
            if (app.title.toLowerCase().includes(searchWord))
                containsAtLeastOneWord = true;
        })
        if (containsAtLeastOneWord)
            return app
      }
    );
    this.props.updateApplications(apps)
  } else { // user deletes manually every word
    this.clearSearch()
  } 
}

Thanks at everyone

4
  • 1
    I see you are not using searchStringSplit? Commented Feb 12, 2019 at 14:11
  • Also you should provide a Minimal, Complete, and Verifiable example stackoverflow.com/help/mcve Commented Feb 12, 2019 at 14:37
  • 1
    Yes, Silvio. It was the single line of code, were I can split the serachString into words depending on the blank between them. But until now I didn't figured out how to work with this array Commented Feb 13, 2019 at 8:56
  • Very glad it helped :) Commented Feb 13, 2019 at 9:55

3 Answers 3

2

If you just want to match at least one word than it's pretty easy :)

let string = "My cool string"
let possibleStrings = [
  'My cool string', 
  'My super cool string', 
  'Another', 
  'I am lon but sadly empty',
  'Bruce Willis is better than Pokemon',
  'Another but with the word string in it',
  'Such string much wow cool']

// Split spaces
let searchString = string.toLowerCase().split(' ')
// Log the result, just wrap it in your react script
console.log(possibleStrings.filter(string => {
    let containsAtLeastOneWord = false;
    // If at least a word is matched return it!
    searchString.forEach(word => {
        if (string.toLowerCase().includes(word))
            containsAtLeastOneWord = true;
    })
    if (containsAtLeastOneWord)
        return string
}))

Sign up to request clarification or add additional context in comments.

Comments

1

You are not using your searchStringSplit array. Using this array you could do the following:

const searchRegex = new RegExp(searchStringSplit.join("|"))
let apps = allApps.filter(app =>
    searchRegex.test(app.title.toLowerCase())
);

You join your searchStringSplit array into a regex with the form term1|term2|term3... and match it aginst the title.


Another option would be to use the Array.prototype.some() function like this:

let apps = allApps.filter(app => 
    searchStringSplit.some(searchString => app.title.toLowerCase().includes(searchString))
);

You fitler all your apps and for each app you check if it's title includes 'some' of the search strings.

Comments

-1

trying to understand your code, suppose that searchString is "facebook twitter youtube"

let searchStringSplit = searchString.split(/(\s+)/).filter( function(e) { return e.trim().length >=3; } );

//searchStringSplit is like [ "facebook", "twitter", "youtube" ]

//allApps is like ["TWITTER","INSTAGRAM"]
allApps.filter(app=> searchStringSplit.includes(app.toLowerCase()))

//returning me all apps in allApps that are includes in searchStringSplit
// so return ["TWITTER"]

not sure if it's exactly what you need...if it's not please let me know so I can change the answer...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.