Closed firaskrichi closed 7 years ago
I'd love to use this in my React + Redux project in Redux-Forms - however, we use specific, custom components and redux form controls the value
of the <input>
in our form. Thus all we can do is format the data for display.... I would love to use the functions from Cleave using something like:
<Input
{...phone}
errorText={phone.touched && phone.error}
id={'phone'}
placeholder="Phone Number"
value={Cleave.getFormattedValue(value)}
/>
Does that make sense? We can't adopt the entire <Cleave>
input component because we need to preserve the behavior of our forms. Any suggestions?
Great work!
Thanks guys, let me have a look at redux-form first
I'm having problem with cleave and redux-form handling backspace. It works like double backspace. Problem described here - https://github.com/nosir/cleave.js/issues/129 It would be great to see them working properly together.
@nosir any news on this one?
Hey guys I got it working like this:
First I installed cleave.js via npm, then added the cleave.min.js to my index.html (not the react one, but the common js one)
<script src='%PUBLIC_URL%/cleave.min.js'></script>
Then I created my componente like any react component with redux form could be:
import React, { Component } from 'react'
import PropTypes from 'prop-types';
import { reduxForm, Field } from 'redux-form';
import { Button } from 'react-bootstrap';
import Input from './input'; // Custom input
const form = reduxForm({
form: 'bankAccountPaymentForm'
});
class BankAccountPayment extends Component {
static propTypes = {
handleFormSubmit: PropTypes.func.isRequired,
}
componentDidMount() {
/* Inject cleave.js into the redux form Field component.
The Input component value will be the cleave formatted value
Disable the next line: eslint will complain cause Cleave is not imported in the file.*/
new Cleave('#bankAccountNumber', { // eslint-disable-line
blocks: [4, 4, 2, 10],
});
}
handleSubmit = (values) => {
this.props.handleFormSubmit({ type: 'bankAccount', ...values });
}
render() {
const { handleSubmit } = this.props;
return (
<div className="centerContentColumn">
<form onSubmit={handleSubmit(this.handleSubmit)}>
<Field name="bankAccountNumber" id="bankAccountNumber" placeholder="Bank account number" component={Input} /> // Input is a custom input component with our styles and so on
<div className="centerContentColumn">
<Button type="submit" bsStyle="success">Submit</Button>
</div>
</form>
</div>
)
}
}
export default form(BankAccountPayment);
Results:
I hope it is useful to you :)
Hi guys, @firaskrichi, sorry for the delay, I had a look at redux-form
, good news, seems it's fairly easy to integrate cleave.js
into it.
So you only need to create a stateless function for the redux-form
Field
, http://redux-form.com/6.8.0/docs/api/Field.md/#2-a-stateless-function
How to:
import Cleave from 'cleave.js/react';
const rederCleaveField = (field) => ( <Cleave {...field.input} options={{creditCard: true}} /> )
2. Render it into the normal `redux-form` `Field`
![image](https://user-images.githubusercontent.com/352617/27959608-7b42e3c4-636b-11e7-8cce-d6044bb25d60.png)
@hielfx That also works, thanks :)
Thanks for your solution. But in redux field is formatted value, is it possible to save into redux field rawValue?
@Tommy10802 Redux-form only grabs the exact value from what is it in the input field, so you will need to register onChange event on cleave component and get the raw value from event callback manually.
Or just put something in redux action to sanitize the input value.
I think the original issue was solved, will close it for now. Thanks guys.
A better way would be to use the normalize abstraction at redux Field level
`import Cleave from 'cleave.js';
function dobDay(value) {
const input = document.createElement("input");
input.value = value;
var cleave = new Cleave(input, {
date: true,
datePattern: ['d', 'm', 'Y']
});
return cleave.getFormattedValue();
}
and then use it this way
<Field name='dob' normalize={dobDay} />
@nathanvale you saved my life right now... works perfect!
Thanks, I will add it to how-to doc
@nathanvale are you having issues deleting the forward slashes? I can only delete the year and it stops at the forward slash.
I'm getting:
Uncaught TypeError: cleave.getFormattedValue is not a function
I see that the function is not available, any idea? I'm using 1.4.4.
Seeing that error as well, seems the api was updated
@devakone , did you do import Cleave from 'cleave.js'
or import Cleave from 'cleave.js/React'
.
The first one should work.
@DarrylD For me, I solved it by doing sth. like this:
const formattedValue = cleave.getFormattedValue()
return formattedValue[formattedValue.length - 1] === delimiter
? formattedValue.slice(0, -1)
: formattedValue
Basically we have to check if the last char is the delimiter, if yes, remove it.
I'm trying to use the same approach for formatting phone numbers:
import React from 'react';
import Cleave from "cleave.js";
import "cleave.js/dist/addons/cleave-phone.i18n";
const FormattedPhoneNumber = ({ phone }) => {
const input = document.createElement("input");
input.value = phone;
const cleave = new Cleave(input, {
phone: true,
phoneRegionCode: 'FR'
});
return cleave.getFormattedValue();
};
export default FormattedPhoneNumber;
But I get the following error:
cleave.js:224 Uncaught Error: [cleave.js] Please include phone-type-formatter.{country}.js lib
at Cleave.initPhoneFormatter (cleave.js:224)
at Cleave.init (cleave.js:165)
at new Cleave (cleave.js:139)
at FormattedPhoneNumber (FormattedPhoneNumber.js:9)
at renderWithHooks (react-dom.development.js:13452)
at mountIndeterminateComponent (react-dom.development.js:15608)
at beginWork (react-dom.development.js:16243)
at performUnitOfWork (react-dom.development.js:20287)
at workLoop (react-dom.development.js:20328)
at HTMLUnknownElement.callCallback (react-dom.development.js:149)
Using version 1.4.10.
Any ideas?
I got it as well - @DarrylD, implemented what @lzhuor wrote (and ill expend, for the future usage of newbies users)
<Field
id="date"
name="date"
placeholder="Data de emissão"
type="text"
required
component="input"
normalize={this.handleFormat}
/>
const cleaveFieldOptions = {
date: true,
delimiter: '/',
datePattern: ['d', 'm', 'Y']
};
handleFormat = value => {
return fieldFormat(value, cleaveFieldOptions);
};
export function fieldFormat(value, options) {
// Create virtual cleave object. Manipulate its value.
const input = window.document.createElement('input');
input.value = value;
var cleaveNewObject = new Cleave(input, options);
// Format it to resolve the bug - @DarrylD Solution
const formattedValue = cleaveNewObject.getFormattedValue();
return formattedValue[formattedValue.length - 1] === '/'
? formattedValue.slice(0, -1)
: formattedValue;
}
It seems this solution does not work on Android anymore.
Like any react component you can connect it to Redux and dispatch actions when events occur. Can you be more specific?