I'm implementing a search input field, which will trigger searching as the user types, and if the user pastes some text, the app needs to do some extra work after searching.
I'm using React
code demo: https://codesandbox.io/s/blazing-platform-wz7ibo?file=/src/App.js
function App() {
const [isPaste, setIsPaste] = useState(false);
const [searchText, setSearchText] = useState('');
useEffect(() => {
callSearchApi(searchText).then(() => {
if (isPaste) {
doSomeExtraWork();
}
});
}, [searchText, isPaste]);
return (
<div>
<input
value={searchText}
onChange={(e) => {
setIsPaste(false);
setSearchText(e.target.value);
}}
onPaste={(e) => {
e.preventDefault();
setIsPaste(true);
const pasteText = (e.clipboardData || window.clipboardData)
.getData('text')
.trim();
setSearchText(pasteText);
// document.execCommand('insertText', false, pasteText); // this will trigger a `change` event
}}
/>
</div>
);
}
this implementation seems fine, but because I prevent the default event in the paste handler, the undo
(Ctrl+Z) no longer works after pasting,
but if I add document.execCommand
at the end of the paste handler, it does bring the undo
feature back, but I can no longer tell if the text is changed by paste...
=== update Jun 08 2023 ==== https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand
In particular, the Clipboard API doesn't replace the insertText command, which you can use to programmatically replace text at the cursor while preserving the undo buffer (edit history) in plain textarea and input elements.