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
This commit is contained in:
Liron Yahdav
2021-12-03 11:54:01 -08:00
committed by Facebook GitHub Bot
parent 0aee7330ff
commit 771ca921b5
2 changed files with 43 additions and 3 deletions
@@ -766,6 +766,7 @@ type ImperativeMethods = $ReadOnly<{|
clear: () => void,
isFocused: () => boolean,
getNativeRef: () => ?React.ElementRef<HostComponent<mixed>>,
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;
}
},
});
@@ -377,7 +377,7 @@ class SelectionExample extends React.Component<
$FlowFixMeProps,
SelectionExampleState,
> {
_textInput: any;
_textInput: React.ElementRef<typeof TextInput> | 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 (
<View>
<SelectionExample
testID="singlelineImperative"
style={styles.default}
value="text selection can be changed imperatively"
imperative={true}
/>
<SelectionExample
testID="multilineImperative"
multiline
style={styles.multiline}
value={'multiline text selection\ncan also be changed imperatively'}
imperative={true}
/>
</View>
);
},
},
]: Array<RNTesterModuleExample>);