From 771ca921b59cc3b3fd12c8fe3b08ed150bcf7a04 Mon Sep 17 00:00:00 2001 From: Liron Yahdav Date: Fri, 3 Dec 2021 11:52:13 -0800 Subject: [PATCH] Add TextInput.setSelection method Summary: Adds a `setSelection` imperative method to `TextInput`. Changelog: [General][Added] - Adds a setSelection imperative method to TextInput Reviewed By: JoshuaGross Differential Revision: D32186514 fbshipit-source-id: 549a7d93b1c55363cf01d804b1e3d735e55c4481 --- Libraries/Components/TextInput/TextInput.js | 14 ++++++++ .../TextInput/TextInputSharedExamples.js | 32 +++++++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index 53642621c58..96f64d82e9f 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -766,6 +766,7 @@ type ImperativeMethods = $ReadOnly<{| clear: () => void, isFocused: () => boolean, getNativeRef: () => ?React.ElementRef>, + setSelection: (start: number, end: number) => void, |}>; const emptyFunctionThatReturnsTrue = () => true; @@ -1009,6 +1010,18 @@ function InternalTextInput(props: Props): React.Node { } } + function setSelection(start: number, end: number): void { + if (inputRef.current != null) { + viewCommands.setTextAndSelection( + inputRef.current, + mostRecentEventCount, + null, + start, + end, + ); + } + } + // TODO: Fix this returning true on null === null, when no input is focused function isFocused(): boolean { return TextInputState.currentlyFocusedInput() === inputRef.current; @@ -1049,6 +1062,7 @@ function InternalTextInput(props: Props): React.Node { ref.clear = clear; ref.isFocused = isFocused; ref.getNativeRef = getNativeRef; + ref.setSelection = setSelection; } }, }); diff --git a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js index 92115086f40..25d228b2bc2 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js @@ -377,7 +377,7 @@ class SelectionExample extends React.Component< $FlowFixMeProps, SelectionExampleState, > { - _textInput: any; + _textInput: React.ElementRef | null = null; constructor(props) { super(props); @@ -397,8 +397,11 @@ class SelectionExample extends React.Component< } select(start, end) { - this._textInput.focus(); + this._textInput?.focus(); this.setState({selection: {start, end}}); + if (this.props.imperative) { + this._textInput?.setSelection(start, end); + } } selectRandom() { @@ -430,7 +433,7 @@ class SelectionExample extends React.Component< // $FlowFixMe[method-unbinding] added when improving typing for this parameters onSelectionChange={this.onSelectionChange.bind(this)} ref={textInput => (this._textInput = textInput)} - selection={this.state.selection} + selection={this.props.imperative ? undefined : this.state.selection} style={this.props.style} value={this.state.value} /> @@ -666,4 +669,27 @@ module.exports = ([ ); }, }, + { + title: 'Text selection & cursor placement (imperative)', + name: 'cursorPlacementImperative', + render: function (): React.Node { + return ( + + + + + ); + }, + }, ]: Array);