Выделение искомого текста внутри таблицы

#javascript #reactjs

#javascript #reactjs

Вопрос:

Я пытаюсь создать таблицу фильтров / поиска в react material-ui. Я использую метод filter для фильтрации данных таблицы по вводу. Теперь мне нужно выделить соответствующие искомые ключевые слова в таблице. Я не смог найти никакого способа сделать это в моем сценарии.

У меня такое состояние. Сохранены все записи таблицы и метод фильтрации. (Я упростил код)

 const [records, setRecords] = useState(tableService.getAllTableData)
const [filterFn, setFilterFn] = useState({ fn: items => { return items; } })
  

И поле ввода и метод фильтрации

     const handleSearch = e => {
        let target = e.target;
        const searchFields = ["fullName", "email", "mobileNumber"];
        setFilterFn({
            fn: items => {
                if (target.value == "")
                    return items;
                else
                    return items.filter(item => {
                        return searchFields.some(field => item[field].toLowerCase().includes(target.value.toLowerCase()))
                    })
            }
        })
    }

    <Input
        label = "Search"
        onChange = { handleSearch }
    />
  

И я таким образом отображаю данные.

 const recordsAfterPagingAndSorting = () => {
    return stableSort(filterFn.fn(records), getComparator(order, orderBy)).slice(page * rowsPerPage, (page   1) * rowsPerPage)
}

<TableBody>
    recordsAfterPagingAndSorting().map(record => (
    <TableRow key={record.id}>
        <TableCell size='small'>{record.fullName}</TableCell>
        <TableCell size='small'>{record.email}</TableCell>
        <TableCell size='small'>{record.mobileNumber}</TableCell>
        <TableCell size='small'>{record.selectBoxTitle}</TableCell>
    </TableRow>
)
</TableBody>
  

Как правильно это сделать?
Могу ли я обработать логику выделения слов внутри метода filter?

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

1. как насчет добавления тега стиля к элементу, когда фильтр соответствует вашему условию

Ответ №1:

То, что вы написали, поможет вам определить, какие записи содержат эту поисковую фразу. Часть, которую вы упускаете из виду в выделении, заключается в том, что вам нужна соответствующая часть и часть вокруг нее.

Например:
если кто-то искал ‘HAN’, ваше имя ‘Eshan Rajapakshe’ должно быть отфильтровано, но чтобы выделить отфильтрованную часть, вам нужно что-то вроде ['Es', 'han', ' Rajapakshe'] и получить информацию о совпадении, вы можете либо сравнить ее со строчной поисковой фразой, либо добавить эту логику в сам массив [{text:'Es', match:false}, {text:'han', match: true}, {text:' Rajapakshe', match: false}]

Вы можете получить вышеуказанное, используя пакет, который я опубликовал

или

Первый массив можно получить простым разделением с использованием регулярных выражений 'Eshan'.split(new RegExp(`(${search_phrase})`, 'gi'))

В вашем случае вы можете вызвать модуль в своей функции. Вам придется соответствующим образом изменить логику рендеринга

 import getParts from 'ec-highlighter-core'
...

const handleSearch = e => {
  let target = e.target
  const searchFields = ['fullName', 'email', 'mobileNumber']
  setFilterFn({
    fn: items => {
      let filteredItems
      // Get filtered items
      if (target.value === '') filteredItems = items
      else
        filteredItems = items.filter(item => {
          return searchFields.some(field =>
            item[field].toLowerCase().includes(target.value.toLowerCase())
          )
        })
      // Get the arrays for highlighting
      return filteredItems.map(item => {
        const out = item
        searchFields.forEach(field => {
          out[field] = getParts(item[field], target.value)
        })
        return out
      })
    }
  })
}

<Input
    label = "Search"
    onChange = { handleSearch }
/>

  

Ответ №2:

Я нашел это альтернативное решение. Возможно, не так, как реагирует. onKeyUp событие и выберите все элементы dom с querySelectorAll

 //onKeyUp function
    const searchedWordsHighlight = (event) => {
        var searchedPara = document.querySelectorAll('.searchCell-body');
        var words = event.target.value;
        var regex = RegExp(words, 'gi') // case insensitive
        var replacement = '<b>'   words   '</b>';
        for (let i = 0; i < searchedPara.length; i  ) {
            const element = searchedPara[i].innerText;
            if (words != "") {
                let newHTML = element.replace(regex, replacement)
                searchedPara[i].innerHTML = newHTML;
            } else {
                let newHTML = element.replace()
                searchedPara[i].innerHTML = newHTML;
            }
        }
    }
    
//Input field
    <Input
        label = "Search"
        onChange = { handleSearch }
        onKeyUp={searchedWordsHighlight}
    />
//Table
    <TableRow key={record.id}>
        <TableCell className="searchCell-body" size='small'>{record.fullName}</TableCell>
        <TableCell className="searchCell-body" size='small'>{record.email}</TableCell>
        <TableCell className="searchCell-body" size='small'>{record.mobileNumber}</TableCell>
        <TableCell size='small'>{record.selectBoxTitle}</TableCell>
    </TableRow>