Skip to content

Commit ac0ad3a

Browse files
committed
[TextInput] returnKeyType, enablesReturnKeyAutomatically, secureTextEntry, more keyboardTypes
Summary: This diff completes adding support for the following UITextField properties: - returnKeyType: what the return key on the keyboard says - enablesReturnKeyAutomatically: the return key is disabled iff there is no text entered. This too could be implemented in React but it feels better in UIKit right now because it is handled synchronously. - secureTextEntry: obscure passwords - keyboardType: added all the keyboard types, they are useful in different scenarios There were varying degrees of support for these properties so it looks like this diff continues some unfinished work. I also updated the keyboardType enum to use native constants instead of strings like the other properties here. Added examples to the UIExplorer. Closes facebook#265 Github Author: James Ide <[email protected]> Test Plan: Imported from GitHub, without a `Test Plan:` line.
1 parent a9167a2 commit ac0ad3a

File tree

7 files changed

+199
-3
lines changed

7 files changed

+199
-3
lines changed

Examples/UIExplorer/TextInputExample.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,89 @@ exports.examples = [
174174
);
175175
}
176176
},
177+
{
178+
title: 'Keyboard types',
179+
render: function() {
180+
var keyboardTypes = [
181+
'default',
182+
'ascii-capable',
183+
'numbers-and-punctuation',
184+
'url',
185+
'number-pad',
186+
'phone-pad',
187+
'name-phone-pad',
188+
'email-address',
189+
'decimal-pad',
190+
'twitter',
191+
'web-search',
192+
'numeric',
193+
];
194+
var examples = keyboardTypes.map((type) => {
195+
return (
196+
<WithLabel key={type} label={type}>
197+
<TextInput
198+
keyboardType={type}
199+
style={styles.default}
200+
/>
201+
</WithLabel>
202+
);
203+
});
204+
return <View>{examples}</View>;
205+
}
206+
},
207+
{
208+
title: 'Return key types',
209+
render: function() {
210+
var returnKeyTypes = [
211+
'default',
212+
'go',
213+
'google',
214+
'join',
215+
'next',
216+
'route',
217+
'search',
218+
'send',
219+
'yahoo',
220+
'done',
221+
'emergency-call',
222+
];
223+
var examples = returnKeyTypes.map((type) => {
224+
return (
225+
<WithLabel key={type} label={type}>
226+
<TextInput
227+
returnKeyType={type}
228+
style={styles.default}
229+
/>
230+
</WithLabel>
231+
);
232+
});
233+
return <View>{examples}</View>;
234+
}
235+
},
236+
{
237+
title: 'Enable return key automatically',
238+
render: function() {
239+
return (
240+
<View>
241+
<WithLabel label="true">
242+
<TextInput enablesReturnKeyAutomatically={true} style={styles.default} />
243+
</WithLabel>
244+
</View>
245+
);
246+
}
247+
},
248+
{
249+
title: 'Secure text entry',
250+
render: function() {
251+
return (
252+
<View>
253+
<WithLabel label="true">
254+
<TextInput secureTextEntry={true} style={styles.default} value="abc" />
255+
</WithLabel>
256+
</View>
257+
);
258+
}
259+
},
177260
{
178261
title: 'Event handling',
179262
render: function(): ReactElement { return <TextEventsExample /> },

Libraries/Components/TextInput/TextInput.js

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ var invariant = require('invariant');
3232
var merge = require('merge');
3333

3434
var autoCapitalizeConsts = RCTUIManager.UIText.AutocapitalizationType;
35+
var keyboardTypeConsts = RCTUIManager.UIKeyboardType;
36+
var returnKeyTypeConsts = RCTUIManager.UIReturnKeyType;
3537

3638
var RCTTextViewAttributes = merge(ReactIOSViewAttributes.UIView, {
3739
autoCorrect: true,
@@ -43,6 +45,9 @@ var RCTTextViewAttributes = merge(ReactIOSViewAttributes.UIView, {
4345
fontStyle: true,
4446
fontWeight: true,
4547
keyboardType: true,
48+
returnKeyType: true,
49+
enablesReturnKeyAutomatically: true,
50+
secureTextEntry: true,
4651
mostRecentEventCounter: true,
4752
placeholder: true,
4853
placeholderTextColor: true,
@@ -82,6 +87,10 @@ var AndroidTextInput = createReactIOSNativeComponentClass({
8287
uiViewClassName: 'AndroidTextInput',
8388
});
8489

90+
var crossPlatformKeyboardTypeMap = {
91+
'numeric': 'decimal-pad',
92+
};
93+
8594
type DefaultProps = {
8695
bufferDelay: number;
8796
};
@@ -154,8 +163,47 @@ var TextInput = React.createClass({
154163
*/
155164
keyboardType: PropTypes.oneOf([
156165
'default',
166+
// iOS
167+
'ascii-capable',
168+
'numbers-and-punctuation',
169+
'url',
170+
'number-pad',
171+
'phone-pad',
172+
'name-phone-pad',
173+
'email-address',
174+
'decimal-pad',
175+
'twitter',
176+
'web-search',
177+
// Cross-platform
157178
'numeric',
158179
]),
180+
/**
181+
* Determines how the return key should look.
182+
*/
183+
returnKeyType: PropTypes.oneOf([
184+
'default',
185+
'go',
186+
'google',
187+
'join',
188+
'next',
189+
'route',
190+
'search',
191+
'send',
192+
'yahoo',
193+
'done',
194+
'emergency-call',
195+
]),
196+
/**
197+
* If true, the keyboard disables the return key when there is no text and
198+
* automatically enables it when there is text. Default value is false.
199+
*/
200+
enablesReturnKeyAutomatically: PropTypes.bool,
201+
202+
/**
203+
* If true, the text input obscures the text entered so that sensitive text
204+
* like passwords stay secure. Default value is false.
205+
*/
206+
secureTextEntry: PropTypes.bool,
159207
/**
160208
* If true, the text input can be multiple lines. Default value is false.
161209
*/
@@ -351,6 +399,12 @@ var TextInput = React.createClass({
351399
var autoCapitalize = autoCapitalizeConsts[this.props.autoCapitalize];
352400
var clearButtonMode = RCTUIManager.UITextField.clearButtonMode[this.props.clearButtonMode];
353401

402+
var keyboardType = keyboardTypeConsts[
403+
crossPlatformKeyboardTypeMap[this.props.keyboardType] ||
404+
this.props.keyboardType
405+
];
406+
var returnKeyType = returnKeyTypeConsts[this.props.returnKeyType];
407+
354408
if (!this.props.multiline) {
355409
for (var propKey in onlyMultiline) {
356410
if (this.props[propKey]) {
@@ -364,7 +418,10 @@ var TextInput = React.createClass({
364418
ref="input"
365419
style={[styles.input, this.props.style]}
366420
enabled={this.props.editable}
367-
keyboardType={this.props.keyboardType}
421+
keyboardType={keyboardType}
422+
returnKeyType={returnKeyType}
423+
enablesReturnKeyAutomatically={this.props.enablesReturnKeyAutomatically}
424+
secureTextEntry={this.props.secureTextEntry}
368425
onFocus={this._onFocus}
369426
onBlur={this._onBlur}
370427
onChange={this._onChange}
@@ -406,6 +463,10 @@ var TextInput = React.createClass({
406463
children={children}
407464
mostRecentEventCounter={this.state.mostRecentEventCounter}
408465
editable={this.props.editable}
466+
keyboardType={keyboardType}
467+
returnKeyType={returnKeyType}
468+
enablesReturnKeyAutomatically={this.props.enablesReturnKeyAutomatically}
469+
secureTextEntry={this.props.secureTextEntry}
409470
onFocus={this._onFocus}
410471
onBlur={this._onBlur}
411472
onChange={this._onChange}

React/Base/RCTConvert.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
+ (UITextFieldViewMode)UITextFieldViewMode:(id)json;
5353
+ (UIScrollViewKeyboardDismissMode)UIScrollViewKeyboardDismissMode:(id)json;
5454
+ (UIKeyboardType)UIKeyboardType:(id)json;
55+
+ (UIReturnKeyType)UIReturnKeyType:(id)json;
5556

5657
+ (UIViewContentMode)UIViewContentMode:(id)json;
5758
+ (UIBarStyle)UIBarStyle:(id)json;

React/Base/RCTConvert.m

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,33 @@ + (NSDate *)NSDate:(id)json
144144
}), UIScrollViewKeyboardDismissModeNone, integerValue)
145145

146146
RCT_ENUM_CONVERTER(UIKeyboardType, (@{
147-
@"numeric": @(UIKeyboardTypeDecimalPad),
148147
@"default": @(UIKeyboardTypeDefault),
148+
@"ascii-capable": @(UIKeyboardTypeASCIICapable),
149+
@"numbers-and-punctuation": @(UIKeyboardTypeNumbersAndPunctuation),
150+
@"url": @(UIKeyboardTypeURL),
151+
@"number-pad": @(UIKeyboardTypeNumberPad),
152+
@"phone-pad": @(UIKeyboardTypePhonePad),
153+
@"name-phone-pad": @(UIKeyboardTypeNamePhonePad),
154+
@"email-address": @(UIKeyboardTypeEmailAddress),
155+
@"decimal-pad": @(UIKeyboardTypeDecimalPad),
156+
@"twitter": @(UIKeyboardTypeTwitter),
157+
@"web-search": @(UIKeyboardTypeWebSearch),
149158
}), UIKeyboardTypeDefault, integerValue)
150159

160+
RCT_ENUM_CONVERTER(UIReturnKeyType, (@{
161+
@"default": @(UIReturnKeyDefault),
162+
@"go": @(UIReturnKeyGo),
163+
@"google": @(UIReturnKeyGoogle),
164+
@"join": @(UIReturnKeyJoin),
165+
@"next": @(UIReturnKeyNext),
166+
@"route": @(UIReturnKeyRoute),
167+
@"search": @(UIReturnKeySearch),
168+
@"send": @(UIReturnKeySend),
169+
@"yahoo": @(UIReturnKeyYahoo),
170+
@"done": @(UIReturnKeyDone),
171+
@"emergency-call": @(UIReturnKeyEmergencyCall),
172+
}), UIReturnKeyDefault, integerValue)
173+
151174
RCT_ENUM_CONVERTER(UIViewContentMode, (@{
152175
@"scale-to-fill": @(UIViewContentModeScaleToFill),
153176
@"scale-aspect-fit": @(UIViewContentModeScaleAspectFit),

React/Modules/RCTUIManager.m

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,32 @@ - (NSDictionary *)constantsToExport
13011301
@"always": @(UITextFieldViewModeAlways),
13021302
},
13031303
},
1304+
@"UIKeyboardType": @{
1305+
@"default": @(UIKeyboardTypeDefault),
1306+
@"ascii-capable": @(UIKeyboardTypeASCIICapable),
1307+
@"numbers-and-punctuation": @(UIKeyboardTypeNumbersAndPunctuation),
1308+
@"url": @(UIKeyboardTypeURL),
1309+
@"number-pad": @(UIKeyboardTypeNumberPad),
1310+
@"phone-pad": @(UIKeyboardTypePhonePad),
1311+
@"name-phone-pad": @(UIKeyboardTypeNamePhonePad),
1312+
@"decimal-pad": @(UIKeyboardTypeDecimalPad),
1313+
@"email-address": @(UIKeyboardTypeEmailAddress),
1314+
@"twitter": @(UIKeyboardTypeTwitter),
1315+
@"web-search": @(UIKeyboardTypeWebSearch),
1316+
},
1317+
@"UIReturnKeyType": @{
1318+
@"default": @(UIReturnKeyDefault),
1319+
@"go": @(UIReturnKeyGo),
1320+
@"google": @(UIReturnKeyGoogle),
1321+
@"join": @(UIReturnKeyJoin),
1322+
@"next": @(UIReturnKeyNext),
1323+
@"route": @(UIReturnKeyRoute),
1324+
@"search": @(UIReturnKeySearch),
1325+
@"send": @(UIReturnKeySend),
1326+
@"yahoo": @(UIReturnKeyYahoo),
1327+
@"done": @(UIReturnKeyDone),
1328+
@"emergency-call": @(UIReturnKeyEmergencyCall),
1329+
},
13041330
@"UIView": @{
13051331
@"ContentMode": @{
13061332
@"ScaleToFill": @(UIViewContentModeScaleToFill),

React/Views/RCTTextField.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
3131
[self addTarget:self action:@selector(_textFieldEndEditing) forControlEvents:UIControlEventEditingDidEnd];
3232
[self addTarget:self action:@selector(_textFieldSubmitEditing) forControlEvents:UIControlEventEditingDidEndOnExit];
3333
_reactSubviews = [[NSMutableArray alloc] init];
34-
self.returnKeyType = UIReturnKeyDone;
3534
}
3635
return self;
3736
}

React/Views/RCTTextFieldManager.m

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ - (UIView *)view
2929
RCT_EXPORT_VIEW_PROPERTY(text, NSString)
3030
RCT_EXPORT_VIEW_PROPERTY(clearButtonMode, UITextFieldViewMode)
3131
RCT_EXPORT_VIEW_PROPERTY(keyboardType, UIKeyboardType)
32+
RCT_EXPORT_VIEW_PROPERTY(returnKeyType, UIReturnKeyType)
33+
RCT_EXPORT_VIEW_PROPERTY(enablesReturnKeyAutomatically, BOOL)
34+
RCT_EXPORT_VIEW_PROPERTY(secureTextEntry, BOOL)
3235
RCT_REMAP_VIEW_PROPERTY(color, textColor, UIColor)
3336
RCT_REMAP_VIEW_PROPERTY(autoCapitalize, autocapitalizationType, UITextAutocapitalizationType)
3437
RCT_CUSTOM_VIEW_PROPERTY(fontSize, CGFloat, RCTTextField)

0 commit comments

Comments
 (0)