Skip to content

Commit bd7b6ed

Browse files
authored
Support passing a custom formatter to TextField (#1528)
* Support passing a static validation message (#1486) * Support passing a static validation message regardless to the validate prop * Fix typing * Fix validate typing * Add leading accessory to example * Update TextField formatter signature
1 parent 0fb9d67 commit bd7b6ed

File tree

5 files changed

+36
-3
lines changed

5 files changed

+36
-3
lines changed

demo/src/screens/incubatorScreens/IncubatorTextFieldScreen.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import {Assets, Colors, Spacings, Typography, View, Text, Button, Keyboard, Incu
55
const {TextField} = Incubator;
66
const {KeyboardAwareInsetsView} = Keyboard;
77

8+
const priceFormatter = Intl.NumberFormat('en-US');
9+
810
export default class TextFieldScreen extends Component {
911
input = React.createRef<TextInput>();
1012
input2 = React.createRef<TextInput>();
@@ -47,7 +49,7 @@ export default class TextFieldScreen extends Component {
4749
}
4850

4951
render() {
50-
const {errorPosition, shouldDisable} = this.state;
52+
const {errorPosition, shouldDisable, price} = this.state;
5153
return (
5254
<ScrollView keyboardShouldPersistTaps="always">
5355
<View flex padding-page>
@@ -218,6 +220,21 @@ export default class TextFieldScreen extends Component {
218220
hint="1-6 chars including numeric chars"
219221
fieldStyle={styles.withUnderline}
220222
/>
223+
<Text h3 blue50 marginV-s4>
224+
Formatter
225+
</Text>
226+
<TextField
227+
value={price}
228+
onChangeText={value => this.setState({price: value})}
229+
label="Price"
230+
placeholder="Enter price"
231+
validate={'number'}
232+
validationMessage="Invalid price"
233+
// @ts-expect-error
234+
formatter={(value) => (isNaN(value) ? value : priceFormatter.format(Number(value)))}
235+
leadingAccessory={<Text marginR-s1 grey30>$</Text>}
236+
fieldStyle={styles.withUnderline}
237+
/>
221238
</View>
222239
<KeyboardAwareInsetsView/>
223240
</ScrollView>

generatedTypes/src/incubator/TextField/Input.d.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@ export interface InputProps extends Omit<TextInputProps, 'placeholderTextColor'>
1515
* placeholder text color
1616
*/
1717
placeholderTextColor?: ColorType;
18+
/**
19+
* Custom formatter for the input value (used only when input if not focused)
20+
*/
21+
formatter?: (value?: string) => string | undefined;
1822
}
1923
declare const Input: {
20-
({ style, hint, color, forwardedRef, ...props }: InputProps & ForwardRefInjectedProps): JSX.Element;
24+
({ style, hint, color, forwardedRef, formatter, ...props }: InputProps & ForwardRefInjectedProps): JSX.Element;
2125
displayName: string;
2226
};
2327
export default Input;

generatedTypes/src/incubator/TextField/usePreset.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export default function usePreset({ preset, ...props }: InternalTextFieldProps):
1919
hint?: string | undefined;
2020
color?: import("./types").ColorType | undefined;
2121
placeholderTextColor?: import("./types").ColorType | undefined;
22+
formatter?: ((value?: string | undefined) => string | undefined) | undefined;
2223
style?: import("react-native").StyleProp<import("react-native").TextStyle>;
2324
testID?: string | undefined;
2425
removeClippedSubviews?: boolean | undefined;
@@ -344,6 +345,7 @@ export default function usePreset({ preset, ...props }: InternalTextFieldProps):
344345
hint?: string | undefined;
345346
color?: import("./types").ColorType | undefined;
346347
placeholderTextColor?: import("./types").ColorType | undefined;
348+
formatter?: ((value?: string | undefined) => string | undefined) | undefined;
347349
style?: import("react-native").StyleProp<import("react-native").TextStyle>;
348350
testID?: string | undefined;
349351
removeClippedSubviews?: boolean | undefined;
@@ -669,6 +671,7 @@ export default function usePreset({ preset, ...props }: InternalTextFieldProps):
669671
hint?: string | undefined;
670672
color?: import("./types").ColorType | undefined;
671673
placeholderTextColor?: import("./types").ColorType | undefined;
674+
formatter?: ((value?: string | undefined) => string | undefined) | undefined;
672675
style: false | import("react-native").TextStyle | import("react-native").RegisteredStyle<import("react-native").TextStyle> | import("react-native").RecursiveArray<import("react-native").TextStyle | import("react-native").Falsy | import("react-native").RegisteredStyle<import("react-native").TextStyle>> | {
673676
lineHeight: undefined;
674677
height: number | undefined;

src/components/textField/TextFieldMigrator.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ const propsMigrationMap: Dictionary<string> = {
1313
titleColor: 'labelColor',
1414
titleStyle: 'labelStyle',
1515
/* CHAR COUNTER */
16-
showCharacterCounter: 'showCharCounter'
16+
showCharacterCounter: 'showCharCounter',
17+
transformer: 'formatter'
1718
};
1819

1920
const specialMigrationMap: Dictionary<string> = {

src/incubator/TextField/Input.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,18 @@ export interface InputProps
2727
* placeholder text color
2828
*/
2929
placeholderTextColor?: ColorType;
30+
/**
31+
* Custom formatter for the input value (used only when input if not focused)
32+
*/
33+
formatter?: (value?: string) => string | undefined;
3034
}
3135

3236
const Input = ({
3337
style,
3438
hint,
3539
color = DEFAULT_INPUT_COLOR,
3640
forwardedRef,
41+
formatter,
3742
...props
3843
}: InputProps & ForwardRefInjectedProps) => {
3944
const inputRef = useImperativeInputHandle(forwardedRef);
@@ -42,10 +47,13 @@ const Input = ({
4247
const inputColor = getColorByState(color, context);
4348
const placeholderTextColor = getColorByState(props.placeholderTextColor, context);
4449

50+
const value = formatter && !context.isFocused ? formatter(props.value) : props.value;
51+
4552
return (
4653
<TextInput
4754
style={[styles.input, !!inputColor && {color: inputColor}, style]}
4855
{...props}
56+
value={value}
4957
placeholder={placeholder}
5058
placeholderTextColor={placeholderTextColor}
5159
// @ts-expect-error

0 commit comments

Comments
 (0)