Skip to content

Commit 0089efe

Browse files
feat: add support for locale + regex + simpler code
1 parent 194deda commit 0089efe

File tree

9 files changed

+284
-106
lines changed

9 files changed

+284
-106
lines changed

README.md

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,47 @@ or
4242
npm install react-native-use-form
4343
```
4444

45+
46+
47+
## Import some localized strings
48+
Ideally you do this somewhere in your `index.js` before `react-native-paper-dates` is used.
49+
Currently we have en/nl/de/pl/pt/ar/ko/fr translations but it's really easy to add one extra since it are only some labels and error messages.
50+
51+
```tsx
52+
// e.g in your index.js
53+
import {
54+
en,
55+
registerTranslation,
56+
registerDefaultLocale
57+
} from 'react-native-use-form'
58+
registerTranslation('en', en)
59+
// you can override the locale per form
60+
registerDefaultLocale('en') // optional (default = en)
61+
// registerTranslation('nl', nl)
62+
```
63+
64+
### or register your own
65+
Please send a PR with your language to make sure all locales are there next time
66+
```tsx
67+
import {
68+
registerTranslation,
69+
} from 'react-native-use-form'
70+
registerTranslation("en", {
71+
required: (params) => `${params.fieldKey || params.fieldKey} is required`,
72+
lengtShouldBeLongerThan: (params) =>
73+
`${params.fieldKey || params.fieldKey} length should be longer than ${
74+
params.requiredLength
75+
}`,
76+
lengthShouldBeShorterThan: (params) =>
77+
`${params.fieldKey || params.fieldKey} length should be shorter than ${
78+
params.requiredLength
79+
}`,
80+
shouldFollowRegex: (params) =>
81+
params.errorMessage ||
82+
`${params.fieldKey || params.fieldKey} is not in the right format`,
83+
})
84+
```
85+
4586
## Usage
4687
```tsx
4788

@@ -51,6 +92,9 @@ import { View } from 'react-native';
5192
import { useFormState, Form } from 'react-native-use-form';
5293
import { Button, HelperText, TextInput } from 'react-native-paper';
5394

95+
96+
97+
5498
export default function App() {
5599
const [
56100
{ errors, submit, formProps, hasError },
@@ -62,8 +106,9 @@ export default function App() {
62106
password: '',
63107
},
64108
{
109+
locale: 'en', // optional override
65110
onChange: (latestValues) => {
66-
// do something with latestValues
111+
// optional: do something with latestValues
67112
},
68113
onSubmit: (submittedValues) => {
69114
// do something with submittedValues
@@ -79,47 +124,34 @@ export default function App() {
79124
}}
80125
>
81126
<Form {...formProps}>
82-
<TextInput
127+
<TextInputWithError
83128
mode="outlined"
84-
error={hasError('email')}
85129
{...email('email', {
86130
validate: (v) => {
87131
return looksLikeMail(v) ? true : 'Email-address is invalid';
88132
},
133+
label: "E-mail"
89134
})}
90-
label="E-mail"
91135
/>
92-
<HelperText type="error" visible={hasError('email')}>
93-
{errors.email}
94-
</HelperText>
95-
<TextInput
136+
<TextInputWithError
96137
mode="outlined"
97138
{...telephone('telephone', {
98139
validate: (v) => {
99140
console.log({ v });
100141
return looksLikeTelephone(v) ? true : 'Telephone is invalid';
101142
},
143+
label: "Telefoon"
102144
})}
103-
label="Telefoon"
104-
error={hasError('telephone')}
105145
/>
106-
<HelperText type="error" visible={hasError('telephone')}>
107-
{errors.telephone}
108-
</HelperText>
109-
110-
<TextInput
146+
<TextInputWithError
111147
mode="outlined"
112148
{...password('password', {
113149
required: true,
114150
minLength: 3,
115151
maxLength: 10,
152+
label: "Wachtwoord"
116153
})}
117-
label="Wachtwoord"
118-
error={hasError('password')}
119154
/>
120-
<HelperText type="error" visible={hasError('password')}>
121-
{errors.password}
122-
</HelperText>
123155
<Button mode="contained" onPress={submit}>
124156
Save
125157
</Button>
@@ -128,6 +160,20 @@ export default function App() {
128160
);
129161
}
130162

163+
164+
165+
function TextInputWithError({ errorMessage, ...rest }: React.ComponentProps<typeof TextInput> & { errorMessage?: string }) {
166+
return (
167+
<>
168+
<TextInput {...rest} />
169+
<HelperText type="error" visible={rest.error}>
170+
{errorMessage || ' '}
171+
</HelperText>
172+
</>
173+
);
174+
}
175+
176+
131177
// you can add your own validate functions
132178
function looksLikeTelephone(str: string): boolean {
133179
if (str.length !== 10) {

example/index.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { registerRootComponent } from 'expo';
22

33
import App from './src/App';
4-
5-
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
6-
// It also ensures that whether you load the app in the Expo client or in a native build,
7-
// the environment is set up appropriately
4+
import { en, registerTranslation, registerDefaultLocale } from '../src/index';
5+
registerTranslation('en', en);
6+
registerDefaultLocale('en');
87
registerRootComponent(App);

example/src/App.tsx

Lines changed: 18 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,8 @@ import * as React from 'react';
22

33
import { StyleSheet, View } from 'react-native';
44
import { Form, useFormState } from '../../src/index';
5-
import {
6-
Button,
7-
HelperText,
8-
Surface,
9-
TextInput,
10-
Title,
11-
} from 'react-native-paper';
5+
import { Button, Surface, TextInput, Title } from 'react-native-paper';
6+
import TextInputWithError from './TextInputWithError';
127

138
type AddressCompany = {
149
name: string;
@@ -65,83 +60,64 @@ export default function App() {
6560
return (
6661
<View style={styles.root}>
6762
<Form {...formProps}>
68-
<TextInput
63+
<TextInputWithError
6964
mode="outlined"
7065
error={hasError('email')}
7166
{...fh.email('email', {
7267
validate: (v) => {
7368
return looksLikeMail(v) ? true : 'Email-address is invalid';
7469
},
70+
label: 'Email',
7571
})}
76-
label="E-mail"
7772
/>
78-
<HelperText type="error" visible={hasError('email')}>
79-
{errors.email}
80-
</HelperText>
81-
<TextInput
73+
<TextInputWithError
8274
mode="outlined"
8375
{...fh.telephone('telephone', {
8476
validate: (v) => {
8577
return looksLikeTelephone(v) ? true : 'Telephone is invalid';
8678
},
79+
label: 'Telephone',
8780
})}
88-
label="Telephone"
89-
error={hasError('telephone')}
9081
/>
91-
<TextInput
82+
<TextInputWithError
9283
mode="outlined"
9384
{...fh.text('postalCode', {
9485
enhance: (v) => {
9586
return (v || '').toUpperCase();
9687
},
97-
// validate: (v) => {
98-
// return looksLikeTelephone(v || '')
99-
// ? true
100-
// : 'Telephone is invalid';
101-
// },
88+
label: 'Postalcode',
10289
})}
103-
label="Postalcode"
104-
error={hasError('postalCode')}
10590
/>
106-
<HelperText type="error" visible={hasError('telephone')}>
107-
{errors.postalCode}
108-
</HelperText>
10991

110-
<TextInput
92+
<TextInputWithError
11193
mode="outlined"
11294
{...fh.password('password', {
11395
required: true,
11496
minLength: 3,
11597
maxLength: 10,
98+
label: 'Password',
11699
})}
117-
label="Password"
118-
error={hasError('password')}
119100
/>
120-
<HelperText type="error" visible={hasError('password')}>
121-
{errors.password}
122-
</HelperText>
123101

124-
<TextInput
102+
<TextInputWithError
125103
mode="outlined"
126104
{...fh.number('age', {
127105
required: true,
128106
minLength: 3,
129107
maxLength: 10,
108+
label: 'Age',
130109
})}
131-
label="Age"
132-
error={hasError('age')}
133110
/>
134-
<TextInput
111+
<TextInputWithError
135112
mode="outlined"
136113
{...fh.decimal('money', {
137114
required: true,
138115
minLength: 3,
139116
maxLength: 10,
117+
label: 'Money bank account',
140118
})}
141-
label="Money bank account"
142-
error={hasError('money')}
143119
/>
144-
<TextInput
120+
<TextInputWithError
145121
mode="outlined"
146122
{...fh.text('organization.telephone', {
147123
required: true,
@@ -152,14 +128,10 @@ export default function App() {
152128
? true
153129
: 'Telephone is invalid';
154130
},
131+
label: 'Organization telephone',
155132
})}
156-
label="Organization telephone"
157-
error={hasError('organization.telephone')}
158133
/>
159-
<HelperText type="error" visible={hasError('organization.telephone')}>
160-
{errors.organization?.telephone}
161-
</HelperText>
162-
<TextInput
134+
<TextInputWithError
163135
mode="outlined"
164136
{...fh.number('organization.revenue', {
165137
required: true,
@@ -171,14 +143,9 @@ export default function App() {
171143
}
172144
return undefined;
173145
},
146+
label: 'Organization revenue',
174147
})}
175-
label="Organization revenue"
176-
error={hasError('organization.revenue')}
177148
/>
178-
<HelperText type="error" visible={hasError('organization.revenue')}>
179-
{errors.organization?.revenue}
180-
</HelperText>
181-
182149
<AddressEdit {...fh.raw('address')} />
183150
<AddressCompanyEdit {...fh.raw('address.company')} />
184151
<Button mode="contained" onPress={submit} style={{ marginTop: 24 }}>

example/src/TextInputWithError.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { HelperText, TextInput } from 'react-native-paper';
2+
import * as React from 'react';
3+
4+
export default function TextInputWithError({
5+
errorMessage,
6+
...rest
7+
}: React.ComponentProps<typeof TextInput> & { errorMessage?: string }) {
8+
return (
9+
<>
10+
<TextInput {...rest} />
11+
<HelperText type="error" visible={rest.error}>
12+
{errorMessage || ' '}
13+
</HelperText>
14+
</>
15+
);
16+
}

src/index.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,12 @@ export { default as useFormState } from './useFormState';
22
export { default as Form } from './Form';
33
export { default as ScrollView } from './ScrollView';
44
export type { ErrorUtility, BooleanUtility } from './types';
5+
6+
export type { TranslationsType } from './translations/utils';
7+
export {
8+
registerTranslation,
9+
registerDefaultLocale,
10+
getTranslation,
11+
} from './translations/utils';
12+
export { default as nl } from './translations/nl';
13+
export { default as en } from './translations/en';

src/translations/en.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { TranslationsType } from './utils';
2+
3+
const en: TranslationsType = {
4+
required: (params) => `${params.fieldKey || params.fieldKey} is required`,
5+
lengtShouldBeLongerThan: (params) =>
6+
`${params.fieldKey || params.fieldKey} length should be longer than ${
7+
params.requiredLength
8+
}`,
9+
lengthShouldBeShorterThan: (params) =>
10+
`${params.fieldKey || params.fieldKey} length should be shorter than ${
11+
params.requiredLength
12+
}`,
13+
shouldFollowRegex: (params) =>
14+
params.errorMessage ||
15+
`${params.fieldKey || params.fieldKey} is not in the right format`,
16+
};
17+
export default en;

src/translations/nl.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { TranslationsType } from './utils';
2+
3+
const nl: TranslationsType = {
4+
required: (params) => `${params.fieldKey || params.fieldKey} is required`,
5+
lengtShouldBeLongerThan: (params) =>
6+
`${params.fieldKey || params.fieldKey} moet langer zijn dan ${
7+
params.requiredLength
8+
}`,
9+
lengthShouldBeShorterThan: (params) =>
10+
`${params.fieldKey || params.fieldKey} moet korter zijn dan ${
11+
params.requiredLength
12+
}`,
13+
shouldFollowRegex: (params) =>
14+
params.errorMessage ||
15+
`${params.fieldKey || params.fieldKey} is niet in het juiste formaat`,
16+
};
17+
export default nl;

0 commit comments

Comments
 (0)