react-native/Libraries/Components/TextInput/TextInput.js

609 lines
17 KiB
JavaScript
Raw Normal View History

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule TextInput
2015-03-25 19:55:10 +00:00
* @flow
*/
'use strict';
var DocumentSelectionState = require('DocumentSelectionState');
var EventEmitter = require('EventEmitter');
var NativeMethodsMixin = require('NativeMethodsMixin');
2015-03-27 18:44:43 +00:00
var Platform = require('Platform');
var PropTypes = require('ReactPropTypes');
var RCTUIManager = require('NativeModules').UIManager;
var React = require('React');
var ReactChildren = require('ReactChildren');
var StyleSheet = require('StyleSheet');
var Text = require('Text');
var TextInputState = require('TextInputState');
2015-03-24 18:35:59 +00:00
var TimerMixin = require('react-timer-mixin');
var TouchableWithoutFeedback = require('TouchableWithoutFeedback');
var View = require('View');
var createReactNativeComponentClass = require('createReactNativeComponentClass');
var emptyFunction = require('emptyFunction');
var invariant = require('invariant');
var requireNativeComponent = require('requireNativeComponent');
var onlyMultiline = {
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
onTextInput: true, // not supported in Open Source yet
children: true,
};
var notMultiline = {
onSubmitEditing: true,
};
if (Platform.OS === 'android') {
var AndroidTextInput = requireNativeComponent('AndroidTextInput', null);
} else if (Platform.OS === 'ios') {
var RCTTextView = requireNativeComponent('RCTTextView', null);
var RCTTextField = requireNativeComponent('RCTTextField', null);
}
type DefaultProps = {
blurOnSubmit: boolean;
};
2015-03-25 19:55:10 +00:00
type Event = Object;
/**
* A foundational component for inputting text into the app via a
* keyboard. Props provide configurability for several features, such as
* auto-correction, auto-capitalization, placeholder text, and different keyboard
* types, such as a numeric keypad.
*
* The simplest use case is to plop down a `TextInput` and subscribe to the
2015-07-27 13:20:37 +00:00
* `onChangeText` events to read the user input. There are also other events,
* such as `onSubmitEditing` and `onFocus` that can be subscribed to. A simple
* example:
*
* ```
* <TextInput
* style={{height: 40, borderColor: 'gray', borderWidth: 1}}
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
* onChangeText={(text) => this.setState({text})}
* value={this.state.text}
* />
* ```
*
* Note that some props are only available with `multiline={true/false}`:
* ```
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
* var onlyMultiline = {
* onSelectionChange: true, // not supported in Open Source yet
* onTextInput: true, // not supported in Open Source yet
* children: true,
* };
*
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
* var notMultiline = {
* onSubmitEditing: true,
* };
* ```
*/
var TextInput = React.createClass({
statics: {
/* TODO(brentvatne) docs are needed for this */
State: TextInputState,
},
propTypes: {
...View.propTypes,
/**
* Can tell TextInput to automatically capitalize certain characters.
*
* - characters: all characters,
* - words: first letter of each word
* - sentences: first letter of each sentence (default)
* - none: don't auto capitalize anything
*/
autoCapitalize: PropTypes.oneOf([
'none',
'sentences',
'words',
'characters',
]),
/**
2015-07-27 13:20:37 +00:00
* If false, disables auto-correct. The default value is true.
*/
autoCorrect: PropTypes.bool,
/**
2015-07-27 13:20:37 +00:00
* If true, focuses the input on componentDidMount.
* The default value is false.
*/
autoFocus: PropTypes.bool,
/**
* Set the position of the cursor from where editing will begin.
* @platform android
*/
textAlign: PropTypes.oneOf([
'start',
'center',
'end',
]),
2015-07-27 13:20:37 +00:00
/**
* Aligns text vertically within the TextInput.
* @platform android
*/
textAlignVertical: PropTypes.oneOf([
'top',
'center',
'bottom',
]),
/**
2015-07-27 13:20:37 +00:00
* If false, text is not editable. The default value is true.
*/
editable: PropTypes.bool,
/**
* Determines which keyboard to open, e.g.`numeric`.
2015-07-27 13:20:37 +00:00
*
* The following values work across platforms:
* - default
* - numeric
* - email-address
*/
keyboardType: PropTypes.oneOf([
// Cross-platform
'default',
'numeric',
'email-address',
// iOS-only
'ascii-capable',
'numbers-and-punctuation',
'url',
'number-pad',
'phone-pad',
'name-phone-pad',
'decimal-pad',
'twitter',
'web-search',
]),
/**
* Determines the color of the keyboard.
* @platform ios
*/
keyboardAppearance: PropTypes.oneOf([
'default',
'light',
'dark',
]),
/**
* Determines how the return key should look.
2015-07-27 13:20:37 +00:00
* @platform ios
*/
returnKeyType: PropTypes.oneOf([
'default',
'go',
'google',
'join',
'next',
'route',
'search',
'send',
'yahoo',
'done',
'emergency-call',
]),
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
/**
2015-07-27 13:20:37 +00:00
* Limits the maximum number of characters that can be entered. Use this
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
* instead of implementing the logic in JS to avoid flicker.
*/
maxLength: PropTypes.number,
/**
* Sets the number of lines for a TextInput. Use it with multiline set to
* true to be able to fill the lines.
* @platform android
*/
numberOfLines: PropTypes.number,
/**
* If true, the keyboard disables the return key when there is no text and
2015-07-27 13:20:37 +00:00
* automatically enables it when there is text. The default value is false.
* @platform ios
*/
enablesReturnKeyAutomatically: PropTypes.bool,
/**
2015-07-27 13:20:37 +00:00
* If true, the text input can be multiple lines.
* The default value is false.
*/
multiline: PropTypes.bool,
/**
* Callback that is called when the text input is blurred
*/
onBlur: PropTypes.func,
/**
* Callback that is called when the text input is focused
*/
onFocus: PropTypes.func,
/**
* Callback that is called when the text input's text changes.
*/
2015-03-27 18:44:43 +00:00
onChange: PropTypes.func,
/**
* Callback that is called when the text input's text changes.
* Changed text is passed as an argument to the callback handler.
*/
onChangeText: PropTypes.func,
/**
* Callback that is called when text input ends.
*/
onEndEditing: PropTypes.func,
/**
* Callback that is called when the text input's submit button is pressed.
* Invalid if multiline={true} is specified.
*/
onSubmitEditing: PropTypes.func,
/**
* Callback that is called when a key is pressed.
* Pressed key value is passed as an argument to the callback handler.
* Fires before onChange callbacks.
* @platform ios
*/
onKeyPress: PropTypes.func,
/**
2015-07-27 13:20:37 +00:00
* Invoked on mount and layout changes with `{x, y, width, height}`.
*/
onLayout: PropTypes.func,
/**
* The string that will be rendered before text input has been entered
*/
placeholder: PropTypes.string,
/**
* The text color of the placeholder string
*/
placeholderTextColor: PropTypes.string,
2015-07-27 13:20:37 +00:00
/**
* If true, the text input obscures the text entered so that sensitive text
* like passwords stay secure. The default value is false.
*/
secureTextEntry: PropTypes.bool,
/**
* See DocumentSelectionState.js, some state that is responsible for
* maintaining selection information for a document
2015-07-27 13:20:37 +00:00
* @platform ios
*/
selectionState: PropTypes.instanceOf(DocumentSelectionState),
/**
2015-07-27 13:20:37 +00:00
* The value to show for the text input. TextInput is a controlled
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
* component, which means the native value will be forced to match this
2015-07-27 13:20:37 +00:00
* value prop if provided. For most uses this works great, but in some
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
* cases this may cause flickering - one common cause is preventing edits
2015-07-27 13:20:37 +00:00
* by keeping value the same. In addition to simply setting the same value,
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
* either set `editable={false}`, or set/update `maxLength` to prevent
* unwanted edits without flicker.
*/
value: PropTypes.string,
/**
* Provides an initial value that will change when the user starts typing.
* Useful for simple use-cases where you don't want to deal with listening
* to events and updating the value prop to keep the controlled state in sync.
*/
defaultValue: PropTypes.string,
/**
* When the clear button should appear on the right side of the text view
2015-07-27 13:20:37 +00:00
* @platform ios
*/
clearButtonMode: PropTypes.oneOf([
'never',
'while-editing',
'unless-editing',
'always',
]),
/**
* If true, clears the text field automatically when editing begins
2015-07-27 13:20:37 +00:00
* @platform ios
*/
clearTextOnFocus: PropTypes.bool,
/**
2015-07-27 13:20:37 +00:00
* If true, all text will automatically be selected on focus
* @platform ios
*/
selectTextOnFocus: PropTypes.bool,
/**
* If true, the text field will blur when submitted.
* The default value is true.
* @platform ios
*/
blurOnSubmit: PropTypes.bool,
/**
* Styles
*/
style: Text.propTypes.style,
2015-03-27 18:44:43 +00:00
/**
2015-07-27 13:20:37 +00:00
* Used to locate this view in end-to-end tests
2015-03-27 18:44:43 +00:00
*/
testID: PropTypes.string,
/**
2015-07-27 13:20:37 +00:00
* The color of the textInput underline.
* @platform android
*/
underlineColorAndroid: PropTypes.string,
},
getDefaultProps: function(): DefaultProps {
return {
blurOnSubmit: true,
};
},
/**
* `NativeMethodsMixin` will look for this when invoking `setNativeProps`. We
* make `this` look like an actual native component class.
*/
mixins: [NativeMethodsMixin, TimerMixin],
viewConfig: ((Platform.OS === 'ios' ? RCTTextField.viewConfig :
(Platform.OS === 'android' ? AndroidTextInput.viewConfig : {})) : Object),
2015-03-25 19:55:10 +00:00
isFocused: function(): boolean {
return TextInputState.currentlyFocusedField() ===
React.findNodeHandle(this.refs.input);
},
getInitialState: function() {
return {
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
mostRecentEventCount: 0,
};
},
contextTypes: {
onFocusRequested: React.PropTypes.func,
focusEmitter: React.PropTypes.instanceOf(EventEmitter),
},
2015-03-25 19:55:10 +00:00
_focusSubscription: (undefined: ?Function),
componentDidMount: function() {
if (!this.context.focusEmitter) {
if (this.props.autoFocus) {
this.requestAnimationFrame(this.focus);
}
return;
}
this._focusSubscription = this.context.focusEmitter.addListener(
'focus',
(el) => {
if (this === el) {
this.requestAnimationFrame(this.focus);
} else if (this.isFocused()) {
this.blur();
}
}
);
if (this.props.autoFocus) {
this.context.onFocusRequested(this);
}
},
componentWillUnmount: function() {
this._focusSubscription && this._focusSubscription.remove();
if (this.isFocused()) {
this.blur();
}
},
2015-05-29 22:24:00 +00:00
getChildContext: function(): Object {
return {isInAParentText: true};
},
childContextTypes: {
isInAParentText: React.PropTypes.bool
},
clear: function() {
this.setNativeProps({text: ''});
},
render: function() {
2015-03-27 18:44:43 +00:00
if (Platform.OS === 'ios') {
return this._renderIOS();
2015-03-27 18:44:43 +00:00
} else if (Platform.OS === 'android') {
return this._renderAndroid();
}
},
_getText: function(): ?string {
return typeof this.props.value === 'string' ?
this.props.value :
this.props.defaultValue;
},
_renderIOS: function() {
var textContainer;
var onSelectionChange;
if (this.props.selectionState || this.props.onSelectionChange) {
onSelectionChange = (event: Event) => {
if (this.props.selectionState) {
var selection = event.nativeEvent.selection;
this.props.selectionState.update(selection.start, selection.end);
}
this.props.onSelectionChange && this.props.onSelectionChange(event);
};
}
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
var props = Object.assign({}, this.props);
props.style = [styles.input, this.props.style];
if (!props.multiline) {
for (var propKey in onlyMultiline) {
if (props[propKey]) {
throw new Error(
'TextInput prop `' + propKey + '` is only supported with multiline.'
);
}
}
textContainer =
2015-03-17 10:08:46 +00:00
<RCTTextField
ref="input"
{...props}
onFocus={this._onFocus}
onBlur={this._onBlur}
onChange={this._onChange}
onSelectionChange={onSelectionChange}
onSelectionChangeShouldSetResponder={emptyFunction.thatReturnsTrue}
text={this._getText()}
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
mostRecentEventCount={this.state.mostRecentEventCount}
/>;
} else {
for (var propKey in notMultiline) {
if (props[propKey]) {
throw new Error(
'TextInput prop `' + propKey + '` cannot be used with multiline.'
);
}
}
var children = props.children;
var childCount = 0;
ReactChildren.forEach(children, () => ++childCount);
invariant(
!(props.value && childCount),
'Cannot specify both value and children.'
);
if (childCount > 1) {
children = <Text>{children}</Text>;
}
if (props.inputView) {
children = [children, props.inputView];
}
textContainer =
2015-03-17 10:08:46 +00:00
<RCTTextView
ref="input"
{...props}
children={children}
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
mostRecentEventCount={this.state.mostRecentEventCount}
onFocus={this._onFocus}
onBlur={this._onBlur}
onChange={this._onChange}
onSelectionChange={onSelectionChange}
onTextInput={this._onTextInput}
onSelectionChangeShouldSetResponder={emptyFunction.thatReturnsTrue}
text={this._getText()}
/>;
}
return (
<TouchableWithoutFeedback
onPress={this._onPress}
rejectResponderTermination={true}
testID={props.testID}>
{textContainer}
</TouchableWithoutFeedback>
);
},
2015-03-27 18:44:43 +00:00
_renderAndroid: function() {
var autoCapitalize = RCTUIManager.UIText.AutocapitalizationType[this.props.autoCapitalize];
var textAlign =
RCTUIManager.AndroidTextInput.Constants.TextAlign[this.props.textAlign];
var textAlignVertical =
RCTUIManager.AndroidTextInput.Constants.TextAlignVertical[this.props.textAlignVertical];
var children = this.props.children;
var childCount = 0;
ReactChildren.forEach(children, () => ++childCount);
invariant(
!(this.props.value && childCount),
'Cannot specify both value and children.'
);
if (childCount > 1) {
children = <Text>{children}</Text>;
}
var textContainer =
2015-03-27 18:44:43 +00:00
<AndroidTextInput
ref="input"
style={[this.props.style]}
autoCapitalize={autoCapitalize}
autoCorrect={this.props.autoCorrect}
textAlign={textAlign}
textAlignVertical={textAlignVertical}
2015-03-27 18:44:43 +00:00
keyboardType={this.props.keyboardType}
mostRecentEventCount={this.state.mostRecentEventCount}
2015-03-27 18:44:43 +00:00
multiline={this.props.multiline}
numberOfLines={this.props.numberOfLines}
maxLength={this.props.maxLength}
2015-03-27 18:44:43 +00:00
onFocus={this._onFocus}
onBlur={this._onBlur}
onChange={this._onChange}
onTextInput={this._onTextInput}
onEndEditing={this.props.onEndEditing}
onSubmitEditing={this.props.onSubmitEditing}
onLayout={this.props.onLayout}
password={this.props.password || this.props.secureTextEntry}
2015-03-27 18:44:43 +00:00
placeholder={this.props.placeholder}
placeholderTextColor={this.props.placeholderTextColor}
text={this._getText()}
underlineColorAndroid={this.props.underlineColorAndroid}
children={children}
editable={this.props.editable}
/>;
return (
<TouchableWithoutFeedback
onPress={this._onPress}
testID={this.props.testID}>
{textContainer}
</TouchableWithoutFeedback>
2015-03-27 18:44:43 +00:00
);
},
2015-03-25 19:55:10 +00:00
_onFocus: function(event: Event) {
if (this.props.onFocus) {
this.props.onFocus(event);
}
},
2015-03-25 19:55:10 +00:00
_onPress: function(event: Event) {
if (this.props.editable || this.props.editable === undefined) {
this.focus();
}
},
2015-03-25 19:55:10 +00:00
_onChange: function(event: Event) {
if (Platform.OS === 'android') {
// Android expects the event count to be updated as soon as possible.
this.refs.input.setNativeProps({
mostRecentEventCount: event.nativeEvent.eventCount,
});
}
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
var text = event.nativeEvent.text;
var eventCount = event.nativeEvent.eventCount;
this.props.onChange && this.props.onChange(event);
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
this.props.onChangeText && this.props.onChangeText(text);
this.setState({mostRecentEventCount: eventCount}, () => {
// NOTE: this doesn't seem to be needed on iOS - keeping for now in case it's required on Android
if (Platform.OS === 'android') {
// This is a controlled component, so make sure to force the native value
// to match. Most usage shouldn't need this, but if it does this will be
// more correct but might flicker a bit and/or cause the cursor to jump.
if (text !== this.props.value && typeof this.props.value === 'string') {
this.refs.input.setNativeProps({
text: this.props.value,
});
}
[ReactNative] TextInput bug fixes and features Summary: This introduces event counts to make sure JS doesn't set out of date values on native text inputs, which can cause dropped characters and can mess with autocomplete, and obviates the need for the input buffering which added lag and complexity to the component. Made sure to test simulated super-slow JS text event processing to make sure characters aren't dropped, as well as typing obviously correctable words and making sure autocomplete works as expected. TextInput is now a controlled input by default without causing any issues for most cases, so I removed the `controlled` prop. Fixes selection state jumping by restoring it after setting new text values, so highlighting the middle of some text in the new ReWrite example and hitting space will replace that selection with an underscore and keep the cursor at a sensible position as expected, instead of jumping to the end. Ads `maxLength` prop to support the most commonly needed syncronous behavior: preventing the user from typing too many characters. It can also be used to prevent users from continuing to type after entering special characters by changing it to the current length after a regex match. Made sure to verify it works well with pasted input (including in the middle of existing text), truncating it and collapsing the selection the same way it does on the web. Fixes bug in TextEventsExample where it wouldn't show the submit and end events, even though there were firing correctly.
2015-07-21 19:37:24 +00:00
}
});
},
2015-03-25 19:55:10 +00:00
_onBlur: function(event: Event) {
this.blur();
if (this.props.onBlur) {
this.props.onBlur(event);
}
},
2015-03-25 19:55:10 +00:00
_onTextInput: function(event: Event) {
this.props.onTextInput && this.props.onTextInput(event);
},
});
var styles = StyleSheet.create({
input: {
alignSelf: 'stretch',
},
});
module.exports = TextInput;