Тестовый объект VueJS (или Vanilla JS) для отфильтрованных результатов, включающий вторичный поиск

#javascript #vue.js #filter #include

#javascript #vue.js #Фильтр #включить

Вопрос:

Я работал над интересной ситуацией, в которой я не смог определить, почему она работает не так, как ожидалось. Приведенный здесь код является последней попыткой, и я считаю, что он близок, просто чего-то не хватает. Если бы кто-нибудь мог мне помочь, это было бы здорово. (Это волонтерский проект, который я выполняю для агентства по усыновлению животных)

Вот настройка:

У меня есть база данных firebase, которая насчитывает около 7000 пользователей. Они разбиваются на объект следующим образом:

 {
  ApplicantCellPhone: "ADOPTERS ACTUAL INFORMATION",
  ApplicantCity: "ADOPTERS ACTUAL INFORMATION",
  ApplicantDLNum: "ADOPTERS ACTUAL INFORMATION",
  ApplicantEmail: "ADOPTERS ACTUAL INFORMATION",
  ApplicantEmployerName: "ADOPTERS ACTUAL INFORMATION",
  ApplicantFirstName: "ADOPTERS ACTUAL INFORMATION",
  ApplicantHomePhone: "ADOPTERS ACTUAL INFORMATION",
  ApplicantLastName: "ADOPTERS ACTUAL INFORMATION",
  ApplicantStreet: "ADOPTERS ACTUAL INFORMATION",
  ApplicantZip: "ADOPTERS ACTUAL INFORMATION",
  CoapplicantCellPhone: "ADOPTERS ACTUAL INFORMATION",
  CoapplicantCity: "ADOPTERS ACTUAL INFORMATION",
  CoapplicantDLNum: "ADOPTERS ACTUAL INFORMATION",
  CoapplicantEmail: "ADOPTERS ACTUAL INFORMATION",
  CoapplicantEmployerName: "ADOPTERS ACTUAL INFORMATION",
  CoapplicantFirstName: "ADOPTERS ACTUAL INFORMATION",
  CoapplicantHomePhone: "ADOPTERS ACTUAL INFORMATION",
  CoapplicantLastName: "ADOPTERS ACTUAL INFORMATION",
  CoapplicantStreet: "ADOPTERS ACTUAL INFORMATION",
  CoapplicantZip: "ADOPTERS ACTUAL INFORMATION",
}
  

Теперь у меня есть окно поиска, подобное этому:

 <b-form-input id="searchInputString" v-model="searchInputString" name="searchInputString" type="text" placeholder="Search Adopters" class="form-control mb-3" autocomplete="off" @keyup.native="filterAdopters" />
  

С помощью @keyup выполняется переход к этой функции:

 filterAdopters: function(event) {
  this.$nextTick(() => {
    this.adoptersFilteredDataCollection = {}
    this.spiltFilteredData = []

    if (!this.isNullOrEmpty(this.searchInputString)) {
      let searchArray = this.searchInputString.split(" ")
      console.log('Search Array =>', searchArray)

      for (let i = 0; i <= searchArray.length; i  ) {
        this.spiltFilteredData.push(this.allAdoptersData.filter(s =>
          s.ApplicantCellPhone.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.ApplicantCity.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.ApplicantDLNum.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.ApplicantEmail.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.ApplicantEmployerName.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.ApplicantFirstName.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.ApplicantHomePhone.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.ApplicantLastName.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.ApplicantStreet.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.ApplicantZip.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.CoapplicantCellPhone.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.CoapplicantCity.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.CoapplicantDLNum.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.CoapplicantEmail.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.CoapplicantEmployerName.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.CoapplicantFirstName.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.CoapplicantHomePhone.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.CoapplicantLastName.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.CoapplicantStreet.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1 ||
          s.CoapplicantZip.toLowerCase().indexOf(this.searchInputString.toLowerCase()) > -1
        ))
      }
    }
    else {
      this.searchInputString = ''
      this.spiltFilteredData = {}
    }

    console.log('spiltFilteredData', this.spiltFilteredData)
  })
},
  

Я не хочу ничего предполагать, поэтому я просто хочу объяснить, что я делаю…

Удалив параметр let searchArray = this.searchInputString.split(» «), если я введу Kimberly, он вернет 345 результатов, теперь я хочу отфильтровать по пробелу, чтобы начать поиск заново, с 345 результатов. Итак, если я наберу Kimberly Brown, он должен вернуть 13 результатов, теперь, нажав еще раз, из 13 результатов я начинаю вводить Хиллсборо (это город), он вернет 2 результата, затем я и введите 345 Center St, затем он вернет 1 результат с правильным Kimberly. Я думал, что я бы преобразовал их в массив, а затем использовал includes , хотя это не так хорошо, как я думал… Есть предложения?

Ответ №1:

Вы должны присвоить все строки переменной results , а затем for продолжать фильтровать результаты с помощью

 results = results.filter(s => {....
  

Для каждого слова, введенного вами для поиска, он будет продолжать сужать соответствующие строки.

Я не тестировал это, но это должно сработать

 filterAdopters: function(event) {
  this.spiltFilteredData = []

  if (!this.isNullOrEmpty(this.searchInputString)) {
    let searchArray = this.searchInputString.split(" ")
    console.log('Search Array =>', searchArray)

    // get all rows
    let results = this.allAdoptersData.map(s => {
      // concatenate all props and lowercase them to avoid doing it multiple times in `for` loop
      // add new helper property `concatenatedProps` to all rows - we will remove it after
      s.concatenatedProps  = [
        s.ApplicantCellPhone,
        s.ApplicantCity,
        s.ApplicantDLNum,
        s.ApplicantEmail,
        s.ApplicantEmployerName,
        s.ApplicantFirstName,
        s.ApplicantHomePhone,
        s.ApplicantLastName,
        s.ApplicantStreet,
        s.ApplicantZip,
        s.CoapplicantCellPhone,
        s.CoapplicantCity,
        s.CoapplicantDLNum,
        s.CoapplicantEmail,
        s.CoapplicantEmployerName,
        s.CoapplicantFirstName,
        s.CoapplicantHomePhone,
        s.CoapplicantLastName,
        s.CoapplicantStreet,
        s.CoapplicantZip
      ].join(' ') // because we don't search ' ', we can use it to join text
       .toLowerCase()

      return s
    });

    for (let i = 0; i < searchArray.length; i  ) {
      let searchText = searchArray[i].toLowerCase();

      results = results.filter( s => s.concatenatedProps.indexOf( searchText) !== -1 )
    }

    this.spiltFilteredData = results.map(s => {
      // remove helper property
      delete s.concatenatedProps

      return s
    })

  } else {
    this.searchInputString = ''
    this.spiltFilteredData = []
  }

  console.log('spiltFilteredData', this.spiltFilteredData)
},
  

Комментарии:

1. Удивительно, мне не хватало сопоставления всех элементов и объединения их пробелом, а затем фильтрации оттуда. Это действительно сработало потрясающе, и я очень благодарен.

2. Объединение пробелом не требовалось, это было просто для того, чтобы избежать всего этого toLowerCase на каждой for итерации. И я просто считаю, что его легче читать 🙂 Вам просто не хватало присвоения отфильтрованных результатов той же переменной и повторной фильтрации. Кроме того, вы выполняли итерацию searchArray , но сравнивали значения с this.searchInputString (полный текст поиска, а не поисковые слова). Вы были почти на месте! Я рад, что смог помочь