Closed yelled3 closed 7 years ago
Also, my initial intuition was to use DocumentSelectionState
, which is fairly undocumented:
http://facebook.github.io/react-native/docs/textinput.html#selectionstate
https://github.com/facebook/react-native/blob/master/Libraries/vendor/document/selection/DocumentSelectionState.js
but it seems all you can do with it is listen to update
events, when the selection changes:
https://github.com/facebook/react-native/blob/master/Libraries/Components/TextInput/TextInput.js#L555-L558
although the documentation says
It is intended for... and for programatically setting browser selection when components re-render. https://github.com/facebook/react-native/blob/master/Libraries/vendor/document/selection/DocumentSelectionState.js#L27-L28
So this seems like a very important feature that is actually quite hard to implement due to the asynchronous nature of React Native. @vjeux and @sahrens are surely the most qualified people to discuss this :) I would love to see support for this.
@brentvatne
actually quite hard to implement due to the asynchronous nature of React Native
wouldn't be possible to add a property:
RCT_EXPORT_VIEW_PROPERTY(selectedTextRange, NSRange)
which then converts the NSRange
to UITextRange
, like the example:
+ (void)selectTextForInput:(UITextField *)input atRange:(NSRange)range {
UITextPosition *start = [input positionFromPosition:[input beginningOfDocument]
offset:range.location];
UITextPosition *end = [input positionFromPosition:start
offset:range.length];
[input setSelectedTextRange:[input textRangeFromPosition:start toPosition:end]];
}
also, it might be easier to create an RCTextRange
that conforms to UITextRange
and RCTextPosition
that conforms to UITextPosition
,
since you can only create a UITextPosition
from an instance of UITextField
.
for example: https://github.com/allending/Notekata/blob/master/Classes/NKTTextRange.h https://github.com/allending/Notekata/blob/master/Classes/NKTTextPosition.h http://stackoverflow.com/a/26013327/2857906
other refs: http://stackoverflow.com/questions/1500233/control-cursor-position-in-uitextfield/11532718#11532718
@vjeux @sahrens /cc
I'm doing something similar and I also need to move the cursor to the end after inserting text.
Would it be possible to accomplish this with an extension module until the react-native team has figured out the proper way to do this in core? Or would I have to change existing implementation methods?
@ehd based on this example: http://stackoverflow.com/questions/1500233/control-cursor-position-in-uitextfield/11532718#11532718
I can imagine you could somehow hack a solution to this... if only to move the cursor to the end, after insertion. but i'm not sure it's gonna be pretty :-)
Yeah, we have a more fully featured TextInput internally that has some dependencies and funkiness that make it hard to open source, but most of the js (like DocumentSelectionState
) leaked out in a slightly broken state unfortunately.
It shouldn't be too hard to add selection state control to the open source TextInput. If someone wants to put up a PR, that would be great, otherwise we'll add it to our list of desired features. Note it should probably use the same synchronization trick as text updates to preserve auto-complete functionality, etc.
It shouldn't be too hard to add selection state control to the open source TextInput.
What do you think the API should look like? Maybe as a method on the TextInput class?
textInputRef.setSelection({start, end})
Note it should probably use the same synchronization trick as text updates to preserve auto-complete functionality, etc.
I looked into the implementation code and the recent controlled TextInputs PR. Does "sync trick" mean checking the event count in RCTTextField's setText method to avoid races between selection changes and text updates?
@ehd how about we stick to the iOS naming
textInputRef.selectedTextRange({start, end})
it might also be useful to have a helper to method that just moves the cursor (i.e when start == end
)
textInputRef.placeCursor(index)
// or
textInputRef.updateCursor(index)
// same as doing
textInputRef.selectedTextRange({index, index})
seems more readable to me...
@sahrens WDYT?
@yelled3 Yeah, I'm all for making it fit with react-native/iOS/Android nomenclature. Regarding the cursor-placement method, unless it's difficult (which doesn't seem so) I'd maybe put it in a "cursor placement" subsection of TextInput's upcoming selection documentation?
Does "sync trick" mean checking the event count
Yup.
how about we stick to the iOS naming
We want this on Android and other platforms too, and in general should prefer web naming conventions. setSelectionRange
seems nice and clear: https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange
@sahrens @yelled3 I'd be interested in creating a PR unless anyone is really into it or already on it? :)
I'm not aware of anyone else working on it, so go for it ;)
@ehd great, go ahead.
@sahrens @yelled3 Here's my first stab at this: https://github.com/facebook/react-native/commit/be41c4536ab84f7841ffd1941b24247c386549ad
Short description:
setSelectionRange(start, end)
on TextInput
selectionRange
view property as NSDictionary
in TextField
's and TextView
's managerssetSelectionRange
in RCTTextField
and RCTTextView
I also had some open questions:
NSDictionary
or another type for the selectionRange
native property?setSelectionRange
be put into a single function and called from setSelectionRange
functions? Not sure what the best approach is to do this is in Obj-C.@ehd
Should this use an NSDictionary or another type for the selectionRange native property
how about using NSRange
, like I mentioned before https://github.com/facebook/react-native/issues/2478#issuecomment-136303797
you may need to extend RCTConvert
to support NSRange
Where can I add documentation and tests as part of a PR?
add docs here: https://github.com/facebook/react-native/blob/master/docs/Text.md
and maybe add a new UIExample
or extend the current one:
https://github.com/facebook/react-native/blob/master/Examples/UIExplorer/TextInputExample.ios.js
Thanks @yelled3! Yeah, I prefer using NSRange
over a generic NSDictionary
and we should then add a conversion for it. I think I was put off by the fact that setSeelctionRange
is start
and end
whereas NSRange
has location
and length
. So maybe we compute the length in the JavaScript method and pass that down as a native prop.
I'll add docs and a extend the UIExample
.
One more question: As it happens I also do need selection change notification support. Is this something that'll be open sourced anyway, or something that could be done as part of this or another PR?
@ehd
So maybe we compute the length in the JavaScript method and pass that down as a native prop.
sounds like a good idea :+1:
As it happens I also do need selection change notification support.
IMO, this can be very useful, as well. @sahrens WDYT?
Is this something that'll be open sourced anyway, or something that could be done as part of this or another PR?
I would suggest splitting this to a separate PR, to keep each PR short and minimal and also too keep the discussion focused on the issue...
Smaller PRs better :)
An event for selection change would be great.
On NSRange vs NSDictionary, you probably want to do whatever is more natural and doesn't require conversion back and forth. If you're going to translate the NSRange into a dictionary anyway to serialize to JS, might as well just keep it as a dict? Less code, fewer errors, more performant. On Sep 10, 2015 5:39 AM, "Adam Farhi" notifications@github.com wrote:
So maybe we compute the length in the JavaScript method and pass that down as a native prop.
sounds like a good idea [image: :+1:]
As it happens I also do need selection change notification support.
IMO, this can be very useful, as well. @sahrens https://github.com/sahrens WDYT?
Is this something that'll be open sourced anyway, or something that could be done as part of this or another PR?
I would suggest splitting this to a separate PR, to keep each PR short and minimal and also too keep the discussion focused on the issue...
— Reply to this email directly or view it on GitHub https://github.com/facebook/react-native/issues/2478#issuecomment-139222697 .
Great, I'll create a PR in a bit :)
:+1: would love a fix for this, thanks!
+1, I need it too for my phone masking implementation. Can anyone recommend any existing input masks for react native?
@nodkrot On iOS you could use 0.15.0-rc's TextInput to tokenize the text and render it accordingly. That commit also includes a nice example in the UIExplorer app where it's rendering hashtags as bold. No reason you can't tokenize into segments and add margin in-between tokens.
Ill take a look thx @ehd
The problem is when the value after masking changes length, for example:
input: 55555
output: (555) 55
Then the cursor position needs to be updated to be at the end of the value.
Has someone tried this extension? https://github.com/DickyT/react-native-textinput-utils
FWIW: I think it'd be hard to go wrong if you patterned this after the HTML equivalent: https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange
I.e.: ref.setSelectionRange(startIndex, endIndex, direction)
.
Especially since I assume that react-native appeals especially to web devs -- who are likely to be familiar with a web standard -- than traditional iOS devs.
@tomprogers Yeah, that's what we started to do in #2668 but then decided that a controlled prop would actually better. If you think about it it's not much different from value
and onChange[Value]
events. The controlled prop API was actually easier to work with.
Are you guys planning to do something like this for Android also? I think I can do a PR using the [setSelection](https://developer.android.com/reference/android/widget/EditText.html#setSelection%28int, int%29) method from EditText
.
@tegon Did you end up implementing this feature for Android?
@RGreenberger Nope, I wasn't sure if it was on the React Native plans.
There is now a selection
prop on the TextInput so I think this should be resolved by https://github.com/facebook/react-native/pull/8958
I'm implementing a custom autocomplete UI (a
TextInput
with aScrollView
with a list of suggestions). I'm keeping the keyboard open (by usingScrollView
keyboardDismissMode="none"
&keyboardShouldPersistTaps={true}
props) and updating theTextInput
's value when a suggestion is chosen.the only issue so far is I would like to update the
TextInput
's cursor each time I add a suggestion to point to the end of the text - so you can keep writing naturally.from my little research, it seems that what keeps the cursor in place is this: (well sort of) https://github.com/facebook/react-native/blob/master/Libraries/Text/RCTTextField.m#L46-L48
I also found: https://github.com/facebook/react-native/blob/master/Libraries/Text/RCTTextFieldManager.m#L45-L49 but this is a
UITextFieldDelegate
method that's only called when the user edits the textfield manually (not when I change theTextInput
's value)this seems like the way to do this, according to: http://stackoverflow.com/a/11532718/2857906
is there currently a way to do this?
@ide @brentvatne /cc