Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
95
rated 0 times [  96] [ 1]  / answers: 1 / hits: 5396  / 3 Years ago, fri, march 19, 2021, 12:00:00

I am using selectionStart and selectionEnd in order to get the starting and ending point of a text selection.


Code: https://codesandbox.io/s/busy-gareth-mr04o


However, I am struggling to defined the type of the event on which they can be called on.
If I use any, the code works properly but I would prefer to know the right event.


I tried with these types:
Element
React.SyntheticEvent<HTMLDivElement>
<HTMLDivElement>
with no luck


export default function App() {
const [startText, setStartText] = useState<number | undefined>();
const [endText, setEndText] = useState<number | undefined>();

const handleOnSelect = (event: any) => { <--- I CANNOT FIND THE RIGHT EVENT TYPE
setStartText(event.target.selectionStart);
setEndText(event.target.selectionEnd);
};

return (
<Grid container direction="column" className="App">
You can type here below:
<TextField
value={"This is a example, select a word from this string"}
onSelect={(event) => handleOnSelect(event)}
/>
<br />
<Grid item>The selected word starts at character: {startText}</Grid>
<Grid item>The selected word ends at character: {endText}</Grid>
</Grid>
);
}

More From » reactjs

 Answers
2

This is a tricky one because the material-ui TextField component involves multiple nested nodes. The argument that is passed to the onSelect function is a div. However the event itself occurs on an input inside the div.


const handleOnSelect = (event: React.SyntheticEvent<HTMLDivElement, Event>) => {
console.log(event.target, event.currentTarget);
};

This logs the input and then the div.


Using event.currentTarget gets very specific Typescript information. We know that it is an HTMLDivElement. But the div doesn't have the properties selectionStart and selectionEnd that we want to access. Those exist on the input.


event.target gives us a very vague type for an EventTarget. We don't know that the target is an input.


One option is to verify the element at runtime.


const handleOnSelect = (event: React.SyntheticEvent<HTMLDivElement, Event>) => {
if ( event.target instanceof HTMLInputElement ) {
setStartText(event.target.selectionStart);
setEndText(event.target.selectionEnd);
}
};

Since you know that the event will always occur on an HTMLInputElement, I think it's safe to make an assertion.


const handleOnSelect = (event: React.SyntheticEvent<HTMLDivElement, Event>) => {
const target = event.target as HTMLInputElement;
setStartText(target.selectionStart);
setEndText(target.selectionEnd);
};

Note that selectionStart and selectionEnd properties use null instead of undefined. So you'll want to either change your state type to <number | null> or replace null with undefined by using null coalescing event.target.selectionStart ?? undefined.


[#1628] Friday, March 12, 2021, 3 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
makaylahk

Total Points: 166
Total Questions: 94
Total Answers: 117

Location: Gabon
Member since Sat, Jul 25, 2020
4 Years ago
;