I try to highlight text in a input on typing, I use two method in this case. As I understand I need return on search something like this: <mark>${item}<mark/>
fuzzyContains = (text, search) => {
debugger
if (!text)
return false
if (!search)
return true
search = search.toLowerCase()
text = text.toString().toLowerCase()
let previousLetterPosition = -1
return search.split('').every(s => {
debugger
previousLetterPosition = text.indexOf(s, previousLetterPosition + 1)
return previousLetterPosition !== -1
})
}
handleSearch = search => {
const {data} = this.state
debugger
let filteredData = data.filter(x => Object.keys(x).some(key => {
debugger
this.fuzzyContains(x[`<mark>${key}<mark/>`], search)}))
this.setState({filteredData, search})
}
I try to highlight text in a input on typing, I use two method in this case. As I understand I need return on search something like this: <mark>${item}<mark/>
fuzzyContains = (text, search) => {
debugger
if (!text)
return false
if (!search)
return true
search = search.toLowerCase()
text = text.toString().toLowerCase()
let previousLetterPosition = -1
return search.split('').every(s => {
debugger
previousLetterPosition = text.indexOf(s, previousLetterPosition + 1)
return previousLetterPosition !== -1
})
}
handleSearch = search => {
const {data} = this.state
debugger
let filteredData = data.filter(x => Object.keys(x).some(key => {
debugger
this.fuzzyContains(x[`<mark>${key}<mark/>`], search)}))
this.setState({filteredData, search})
}
Share
Improve this question
edited Aug 17, 2017 at 13:48
Palaniichuk Dmytro
asked Aug 17, 2017 at 13:40
Palaniichuk DmytroPalaniichuk Dmytro
3,18313 gold badges39 silver badges69 bronze badges
3
- 1 Please explain the use-case a bit better. Your explanation is too vague as it currently stands. What do you mean by "search" exactly? You want a substring highlighted as you are typing in a text-input? – Chris Commented Aug 17, 2017 at 13:43
- @Chris yes when typing in a text-input – Palaniichuk Dmytro Commented Aug 17, 2017 at 13:47
- Simply store the entered text in a variable in the render method. use javascript's split method by words and add css styling to each word inside of a map function. – fungusanthrax Commented Aug 17, 2017 at 16:04
1 Answer
Reset to default 7The code you provide is too little to understand what's actually going on in your app. Instead, I have made a simple example below.
In the following snippet I start by creating an application with a fixed text and an input element. The input element has a listener that has an onChange
trigger. Whenever you type something, the changeInput
function is fired.
The function starts by getting the innerText
of the related DOM node where the text is printed. It then tries to find your entered substring with indexOf
. If there's a match, we split the string into three pieces (the matching text, and the substrings before and after that matching text, if any).
If there is no match, we reset the text back to the initial value.
The whole thing is then entered into an array; the 1st and 3rd items are plain strings, whereas the 2nd item (the match) is a React Element of type strong
which is used to highlight the matching text.
class MyApp extends React.Component {
constructor() {
super();
this.initialText = "Lorem ipsum dolor sit amet";
this.state = {
text: this.initialText,
inputValue: ""
};
}
changeInput = (e) => {
let value = e.target.value;
let txt = document.getElementById("myText").innerText;
let idx = txt.indexOf(value);
if(idx >= 0) {
let newText = [txt.substring(0, idx), <strong>{txt.substring(idx, idx + value.length)}</strong>, txt.substring(idx + value.length)];
this.setState({inputValue: value, text: newText});
} else {
this.setState({inputValue: value, text: this.initialText});
}
}
render() {
return (
<div>
<p id="myText">{this.state.text}</p>
<input onChange={this.changeInput} value={this.state.inputValue} />
</div>
);
}
}
ReactDOM.render(<MyApp />, document.getElementById("app"));
strong {
background: red;
color: white;
font-weight: inherit;
}
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Note that this can be done with using refs
if you prefer. If you want to avoid DOM lookups and the use of refs
, you could always use 2 state variables; one that holds the resulting JSX and one that holds the plain text representation.
Also note that this will only highlight the first matching substring. For example, if you had the string: "Lorem ipsum, Lorem ipsum", and you searched for "Lorem", only the first occurrence of that word would be highlighted. If you want multiple hightlights, you could try using some kind of regex.