react-native-masked-text
Version:
Text and TextInput with mask for React Native applications
491 lines (398 loc) • 15.3 kB
Markdown
# react-native-masked-text

[](https://www.codetriage.com/benhurott/react-native-masked-text)

This is a simple masked text (normal text and input text) component for React-Native.
## Supported Versions
React-native: 0.32.0 or higher
## Install
`npm install react-native-masked-text --save`
## Usage (TextInputMask)
```jsx
import React, { Component } from 'react'
// import the component
import { TextInputMask } from 'react-native-masked-text'
export default class MyComponent extends Component {
constructor(props) {
super(props)
}
componentDidMount() {
// isValid method returns if the inputed value is valid.
// Ex: if you input 40/02/1990 30:20:20, it will return false
// because in this case, the day and the hour is invalid.
let valid = this.myDateText.isValid();
// get converted value. Using type=datetime, it returns the moment object.
// If it's using type=money, it returns a Number object.
let rawValue = this.myDateText.getRawValue();
}
render() {
// the type is required but options is required only for some specific types.
return (
<TextInputMask
ref={(ref) => this.myDateText = ref}
type={'datetime'}
options={{
format: 'DD-MM-YYYY HH:mm:ss'
}}
/>
)
}
}
```
### Props
#### type
_credit-card_: use the mask 9999 9999 9999 9999. It accepts options (see later in this doc). <br />
_cpf_: use the mask `999.999.999-99` and `numeric` keyboard. <br />
_cnpj_: use the mask `99.999.999/9999-99` and `numeric` keyboard. <br />
_zip-code_: use the mask `99999-999` and `numeric` keyboard. <br />
_only-numbers_: accept only numbers on field with `numeric` keyboard. <br />
_money_: use the mask `R$ 0,00` on the field with `numeric` keyboard. It accepts options (see later in this doc). <br />
_cel-phone_: use the mask `(99) 9999-9999` or `(99) 99999-9999` (changing automaticaly by length). It accepts options (see later in this doc). <br />
_datetime_: use datetime mask with moment format (default DD/MM/YYYY HH:mm:ss). It accepts options (see later in this doc). <br />
_custom_: use your custom mask (see the options props later in this doc). <br />
#### onChangeText
Invoked after new value applied to mask.
```jsx
/**
* @param {String} text the text AFTER mask is applied.
*/
onChangeText(text) {
// ...
}
<TextInputMask
type={'only-numbers'}
onChangeText={this.onChangeText.bind(this)} />
```
#### checkText
Allow you to check and prevent value to be inputed.
```jsx
/**
* @param {String} previous the previous text in the masked field.
* @param {String} next the next text that will be setted to field.
* @return {Boolean} return true if must accept the value.
*/
checkText(previous, next) {
return next === 'your valid value or other boolean condition';
}
<TextInputMask
type={'only-numbers'}
checkText={this.checkText.bind(this)} />
```
#### customTextInput
You can use this prop if you want custom text input instead native TextInput component:
```jsx
const Textfield = MKTextField.textfield()
.withPlaceholder('Text...')
.withStyle(styles.textfield)
.build();
<TextInputMask
ref={(ref) => this.myDateText = ref}
type={'money'}
style={styles.input}
customTextInput={Textfield}
placeholder="Enter text to see events"
/>
```
#### customTextInputProps
Some custom inputs like [react-native-textinput-effects](https://github.com/halilb/react-native-textinput-effects) have to set properties in mount time. For these types of components we use this property.
```jsx
import React from 'react'
import { StyleSheet, View } from 'react-native'
import { TextInputMask } from 'react-native-masked-text'
import { Kaede } from 'react-native-textinput-effects'
export default class App extends React.Component {
constructor(props) {
super(props)
this.state = {
birthday: ''
}
}
render() {
return (
<View style={styles.container}>
<TextInputMask
ref={(ref) => this.myDateText = ref}
// here we set the custom component and their props.
customTextInput={Kaede}
customTextInputProps={{
style:{ width: '80%' },
label:'Birthday'
}}
type={'datetime'}
options={{
format: 'DD-MM-YYYY HH:mm:ss'
}}
// don't forget: the value and state!
onChangeText={birthday => this.setState({ birthday })}
value={this.state.birthday} />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
}
})
```
#### TextInput Props
You can use the native props of TextInput, with this in mind:
- onChangeText is intercepted by component.
- value is intercepted by component.
- if you pass keyboardType, it will override the keyboardType of masked component.
#### TextInput Methods
If you want to use the methods of the native TextInput, use the `getElement()` method:
```jsx
export default class App extends React.Component {
onGoFocus() {
// when you call getElement method, the instance of native TextInput will returned.
this._myTextInputMask.getElement().focus()
}
render() {
return (
<View style={styles.container}>
<View>
<TextInputMask
ref={ref => (this._myTextInputMask = ref)}
type={'only-numbers'}
style={styles.input}
/>
</View>
<View>
<Button
onPress={this.onGoFocus.bind(this)}
title="Go Focus Hue"
color="#841584"
/>
</View>
</View>
)
}
}
```
#### Options
Some types accept options, use it like this: `<TextInputMask type={'money'} options={{ unit: 'US$' }} />`
**For `type={'money'}`** <br />
- _options={...}_
- `precision` (Number, default 2): the decimal places.
- `separator` (String, default ','): the decimal separator.
- `delimiter` (String, default '.'): the thousand separator.
- `unit`: (String, default 'R$'): the prefix text.
- `suffixUnit` (String, default ''): the suffix text.
- `zeroCents` (Boolean, default false): if must show cents.
**For `type={'cel-phone'}`** <br />
- _options={...}_
- `withDDD` (Boolean, default true): if the ddd will be include in the mask.
- `dddMask` (String, default '(99) '): the default mask applied if `withDDD` is true.
**For `type={'datetime'}`** <br />
- _options={...}_
- `format` (String, default DD/MM/YYYY HH:mm:ss): moment date format. It accepts the following:
- DD/MM/YYYY HH:mm:ss
- DD/MM/YYYY
- MM/DD/YYYY
- YYYY/MM/DD
- HH:mm:ss
- HH:mm
- HH
- _You can use all of dates with `-` instead of `/` if you want_
**For `type={'custom'}`** <br />
- _options={...}_
```jsx
{
/**
* mask: (String | required | default '')
* the mask pattern
* 9 - accept digit.
* A - accept alpha.
* S - accept alphanumeric.
* * - accept all, EXCEPT white space.
*/
mask: '999#AAA',
/**
* validator: (Function | optional | defaults returns true)
* use this funcion to inform if the inputed value is a valid value (for invalid phone numbers, for example). The isValid method use this validator.
*/
validator: function(value, settings) {
return true
},
/**
* getRawValue: (Function | optional | defaults return current masked value)
* use this function to parse and return values to use what you want.
* for example, if you want to create a phone number mask (999) 999-99-99 but want to get only
* the numbers for value, use this method for this parse step.
*/
getRawValue: function(value, settings) {
return 'my converted value';
},
/**
* translation: (Object | optional | defaults 9, A, S, *)
* the dictionary that translate mask and value.
* you can change defaults by simple override the key (9, A, S, *) or create some new.
*/
translation: {
// this is a custom translation. The others (9, A, S, *) still works.
// this translation will be merged and turns into 9, A, S, *, #.
'#': function(val) {
if (val === ' ') {
return val;
}
// if returns null, undefined or '' (empty string), the value will be ignored.
return null;
},
// in this case, we will override build-in * translation (allow all characters)
// and set this to allow only blank spaces and some special characters.
'*': function(val) {
return [' ', '#', ',', '.', '!'].indexOf(val) >= 0 ? val : null;
}
}
}
```
**For `type={'credit-card'}`** <br />
- _options={...}_
- `obfuscated` (Boolean, default false): if the mask must be `9999 **** **** 9999`.
- `issuer` (String, default 'visa-or-mastercard'): the credit card issuer.
- options:
- `visa-or-mastercard`: will apply the mask `9999 9999 9999 9999` / `9999 **** **** 9999`.
- `amex`: will apply the mask `9999 999999 99999` / `9999 ****** 99999`.
- `diners`: will apply the mask `9999 999999 9999` / `9999 ****** 9999`.
### Methods
- `getElement()`: return the instance of _TextInput_ component.
- `isValid()`: if the value inputed is valid for the mask.
- _credit-card_: return true if the mask is complete.
- _cpf_: return true if the mask is complete and cpf is valid.
- _cnpj_: return true if the mask is complete and cnpj is valid.
- _zip-code_: return true if the mask is complete.
- _only-numbers_: always returns true.
- _money_: always returns true.
- _cel-phone_: return true if the mask is complete.
- _datetime_: return true if the date value is valid for format.
- _custom_: use custom validation, if it not exist, always returns true.
- `getRawValue()`: get the converted value of mask.
- _credit-card_: return the array with the value parts. Ex: `1234 1234 1234 1234` returns `[1234, 1234, 1234, 1234]`.
- _cpf_: return the value without mask.
- _cnpj_: return the value without mask.
- _zip-code_: return the value without mask.
- _only-numbers_: return the value without mask.
- _money_: return the Number value. Ex: `R$ 1.234,56` returns `1234.56`.
- _cel-phone_: return the value without mask.
- _datetime_: return the `moment` object for the date and format.
- _custom_: use custom method (passed in options). If it not exists, returns the current value.
Sample usage:
```jsx
import React, { Component } from 'react'
import { StyleSheet, View } from 'react-native'
import { TextInputMask } from 'react-native-masked-text'
export default class App extends Component {
state = {
datetime: ''
}
render() {
return (
<View style={styles.container}>
<TextInputMask
{/*First, set the reference*/}
ref={ref => (this._myDatetimeField = ref)}
style={styles.input}
type={'datetime'}
options={{
format: 'DD-MM-YYYY HH:mm:ss'
}}
placeholder={'datetime DD-MM-YYYY HH:mm:ss'}
value={this.state.datetime}
onChangeText={datetime => {
this.setState({ datetime })
// Now just use =)
console.log(this._myDatetimeField.getElement())
console.log(this._myDatetimeField.isValid())
console.log(this._myDatetimeField.getRawValue())
}}
/>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF'
},
input: {
height: 50,
width: '80%',
borderColor: 'steelblue',
borderWidth: 2
}
})
```
## Usage (TextMask)
```jsx
import React, { Component } from 'react'
// import the component
import { TextMask } from 'react-native-masked-text'
export default class MyComponent extends Component {
constructor(props) {
super(props)
this.state = {
text: '4567123409871234'
}
}
render() {
// the type is required but options is required only for some specific types.
// the sample below will output 4567 **** **** 1234
return (
<TextMask
value={this.state.text}
type={'credit-card'}
options={{
obfuscated: true
}}
/>
)
}
}
```
### Props
The same of _TextInputMask_, but for React-Native _Text_ component instead _TextInput_.
<br />
_Warning_: if the value not match the mask, it will not appear.
### Methods
`getElement()`: return the instance of _Text_ component.
## Extra (MaskService)
If you want, we expose the `MaskService`. You can use it:
**Methods**
- static toMask(type, value, settings): mask a value.
- `type` (String, required): the type of the mask (`cpf`, `datetime`, etc...)
- `value` (String, required): the value to be masked
- `settings` (Object, optional): if the mask type accepts options, pass it in the settings parameter
- static toRawValue(type, maskedValue, settings): get the raw value of a masked value.
- `type` (String, required): the type of the mask (`cpf`, `datetime`, etc...)
- `maskedValue` (String, required): the masked value to be converted in raw value
- `settings` (Object, optional): if the mask type accepts options, pass it in the settings parameter
- static isValid(type, value, settings): validate if the mask and the value match.
- `type` (String, required): the type of the mask (`cpf`, `datetime`, etc...)
- `value` (String, required): the value to be masked
- `settings` (Object, optional): if the mask type accepts options, pass it in the settings parameter
- static getMask(type, value, settings): get the mask used to mask the value
Ex:
```jsx
import { MaskService } from 'react-native-masked-text'
var money = MaskService.toMask('money', '123', {
unit: 'US$',
separator: '.',
delimiter: ','
})
// money -> US$ 1.23
```
## Throubleshooting
- If the `es2015` error throw by babel, try run `react-native start --reset-cache`
## Changelog
View changelog [HERE](CHANGELOG.md)
## Thanks to
- <div>Icons made by <a href="http://www.freepik.com" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></div>
- Thanks to [vanilla-masker](https://github.com/BankFacil/vanilla-masker) =).
- Thanks to [moment](http://momentjs.com/) =).