AmountField
by Sébastien Castiel
HTML
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="container" />
CSS
input {
padding: 3px;
border-radius: 3px;
border: 0.5px solid lightgray;
font-size: large;
}
Babel + JSX
class AmountField extends React.Component {
constructor(props) {
super(props);
this.state = this._createStateFromProps(props);
}
componentWillReceiveProps(newProps) {
this.setState(this._createStateFromProps(newProps));
}
_createStateFromProps(props) {
return { amountString: amountToString(props.amount) };
}
handleChange = event => {
this.setState({ amountString: cleanAmountString(event.target.value) });
}
handleFocus = () => {
this.setState({ amountString: amountToString(this.props.amount) });
}
handleBlur = () => {
const amount = amountFromString(this.state.amountString);
const roundedAmount = Math.round(amount * 100) / 100;
this.props.onChange(roundedAmount);
}
render() {
const { amountString } = this.state;
return (
<input
type='text'
value={amountString}
onChange={this.handleChange}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
/>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = { amount: 2123.45 };
}
onAmountChange = (amount) => {
this.setState({ amount });
}
render() {
return (
<div>
<div><AmountField onChange={this.onAmountChange} amount={this.state.amount} /></div>
<div>Amount: <code>{this.state.amount}</code></div>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('container')
);
// UTILITY FUNCTIONS /////////////////////////////////////////////////////////////////////////////
function cleanAmountString(amountString) {
return amountString.replace(/[^\d\.,\s\$]/g, '');
}
function amountToString(amount) {
return typeof amount === 'number'
? amount.toLocaleString(
undefined,
{ minimumFractionDigits: 2, maximumFractionDigits: 2 }
) + ' $'
: '';
}
function amountFromString(amountString) {
const cleanedAmountString = amountString.replace(/[^\d\.,]/g, '').replace(',', '.');
const...