#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>