Merge branch 'multiline-maxlength-fix' of https://github.com/SimonSelg/react-toolbox into SimonSelg-multiline-maxlength-fix
* 'multiline-maxlength-fix' of https://github.com/SimonSelg/react-toolbox: feat(dist): add newest build doc(input): add note about handleChange implementation fix(input): don't remove the maxLenght attribute from inputs feat(input): prevent insertion of characters if maxLength is reached fix(input): always recalculate size feat(input): set the default row amount for multiline inputs to 1 feat(input): implement maxLength in js rather then using the maxlength prop of the input field refactor(input): move autoresize to didUpdate fix(input): only remove resize event listerner if it exists docs(input): fix multiline example and add maxLength to it fix(multiline input): autoresize after initial render tooold
commit
beb0ca4465
|
@ -57,6 +57,7 @@ const factory = (FontIcon) => {
|
|||
componentDidMount () {
|
||||
if (this.props.multiline) {
|
||||
window.addEventListener('resize', this.handleAutoresize);
|
||||
this.handleAutoresize();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,15 +69,27 @@ const factory = (FontIcon) => {
|
|||
}
|
||||
}
|
||||
|
||||
componentDidUpdate () {
|
||||
// resize the textarea, if nessesary
|
||||
if (this.props.multiline) this.handleAutoresize();
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
window.removeEventListener('resize', this.handleAutoresize);
|
||||
if (this.props.multiline) window.removeEventListener('resize', this.handleAutoresize);
|
||||
}
|
||||
|
||||
handleChange = (event) => {
|
||||
if (this.props.multiline) {
|
||||
this.handleAutoresize();
|
||||
}
|
||||
if (this.props.onChange) this.props.onChange(event.target.value, event);
|
||||
const { onChange, multiline, maxLength } = this.props;
|
||||
const valueFromEvent = event.target.value;
|
||||
|
||||
// Trim value to maxLength if that exists (only on multiline inputs).
|
||||
// Note that this is still required even tho we have the onKeyPress filter
|
||||
// because the user could paste smt in the textarea.
|
||||
const haveToTrim = (multiline && maxLength && event.target.value.length > maxLength);
|
||||
const value = haveToTrim ? valueFromEvent.substr(0, maxLength) : valueFromEvent;
|
||||
|
||||
// propagate to to store and therefore to the input
|
||||
if (onChange) onChange(value, event);
|
||||
};
|
||||
|
||||
handleAutoresize = () => {
|
||||
|
@ -100,10 +113,31 @@ const factory = (FontIcon) => {
|
|||
this.refs.input.focus();
|
||||
}
|
||||
|
||||
onKeyPress = (event) => {
|
||||
// prevent insertion of more characters if we're a multiline input
|
||||
// and maxLength exists
|
||||
const { multiline, maxLength, onKeyPress } = this.props;
|
||||
if (multiline && maxLength) {
|
||||
// check if smt is selected, in which case the newly added charcter would
|
||||
// replace the selected characters, so the length of value doesn't actually
|
||||
// increase.
|
||||
const isReplacing = event.target.selectionEnd - event.target.selectionStart;
|
||||
const value = event.target.value;
|
||||
|
||||
if (!isReplacing && value.length === maxLength) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (onKeyPress) onKeyPress(event);
|
||||
}
|
||||
|
||||
render () {
|
||||
const { children, disabled, error, floating, hint, icon,
|
||||
name, label: labelText, maxLength, multiline, required,
|
||||
theme, type, value, ...others} = this.props;
|
||||
theme, type, value, onKeyPress, ...others} = this.props;
|
||||
const length = maxLength && value ? value.length : 0;
|
||||
const labelClassName = classnames(theme.label, {[theme.fixed]: !floating});
|
||||
|
||||
|
@ -119,7 +153,7 @@ const factory = (FontIcon) => {
|
|||
&& value !== ''
|
||||
&& !(typeof value === Number && isNaN(value));
|
||||
|
||||
const InputElement = React.createElement(multiline ? 'textarea' : 'input', {
|
||||
const inputElementProps = {
|
||||
...others,
|
||||
className: classnames(theme.inputElement, {[theme.filled]: valuePresent}),
|
||||
onChange: this.handleChange,
|
||||
|
@ -129,9 +163,17 @@ const factory = (FontIcon) => {
|
|||
disabled,
|
||||
required,
|
||||
type,
|
||||
value,
|
||||
maxLength
|
||||
});
|
||||
value
|
||||
};
|
||||
if (!multiline) {
|
||||
inputElementProps.maxLength = maxLength;
|
||||
inputElementProps.onKeyPress = onKeyPress;
|
||||
} else {
|
||||
inputElementProps.rows = 1;
|
||||
inputElementProps.onKeyPress = this.onKeyPress;
|
||||
}
|
||||
|
||||
const InputElement = React.createElement(multiline ? 'textarea' : 'input', inputElementProps);
|
||||
|
||||
return (
|
||||
<div data-react-toolbox='input' className={className}>
|
||||
|
|
|
@ -8,9 +8,9 @@ class InputTest extends React.Component {
|
|||
render () {
|
||||
return (
|
||||
<section>
|
||||
<Input type='text' label='Name' name='name' value={this.state.name} onChange={this.handleChange.bind(this, 'name')} maxLength={16 } />
|
||||
<Input type='text' label='Name' name='name' value={this.state.name} onChange={this.handleChange.bind(this, 'name')} maxLength={16} />
|
||||
<Input type='text' label='Disabled field' disabled />
|
||||
<Input type='text' multiline label='Multiline' onChange={this.handleChange.bind(this, 'multiline')} />
|
||||
<Input type='text' multiline label='Multiline' maxLength={20} value={this.state.multiline} onChange={this.handleChange.bind(this, 'multiline')} />
|
||||
<Input type='email' label='Email address' icon='email' value={this.state.email} onChange={this.handleChange.bind(this, 'email')} />
|
||||
<Input type='tel' label='Phone' name='phone' icon='phone' value={this.state.phone} onChange={this.handleChange.bind(this, 'phone')} />
|
||||
<Input type='text' value={this.state.hint} label='Required Field' hint='With Hint' required onChange={this.handleChange.bind(this, 'hint')} icon={<span>J</span>} />
|
||||
|
|
|
@ -55,10 +55,21 @@ var factory = function factory(FontIcon) {
|
|||
}
|
||||
|
||||
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_Object$getPrototypeO = Object.getPrototypeOf(Input)).call.apply(_Object$getPrototypeO, [this].concat(args))), _this), _this.handleChange = function (event) {
|
||||
if (_this.props.multiline) {
|
||||
_this.handleAutoresize();
|
||||
}
|
||||
if (_this.props.onChange) _this.props.onChange(event.target.value, event);
|
||||
var _this$props = _this.props;
|
||||
var onChange = _this$props.onChange;
|
||||
var multiline = _this$props.multiline;
|
||||
var maxLength = _this$props.maxLength;
|
||||
|
||||
var valueFromEvent = event.target.value;
|
||||
|
||||
// Trim value to maxLength if that exists (only on multiline inputs).
|
||||
// Note that this is still required even tho we have the onKeyPress filter
|
||||
// because the user could paste smt in the textarea.
|
||||
var haveToTrim = multiline && maxLength && event.target.value.length > maxLength;
|
||||
var value = haveToTrim ? valueFromEvent.substr(0, maxLength) : valueFromEvent;
|
||||
|
||||
// propagate to to store and therefore to the input
|
||||
if (onChange) onChange(value, event);
|
||||
}, _this.handleAutoresize = function () {
|
||||
var element = _this.refs.input;
|
||||
// compute the height difference between inner height and outer height
|
||||
|
@ -68,6 +79,29 @@ var factory = function factory(FontIcon) {
|
|||
// resize the input to its content size
|
||||
element.style.height = 'auto';
|
||||
element.style.height = element.scrollHeight + heightOffset + 'px';
|
||||
}, _this.onKeyPress = function (event) {
|
||||
// prevent insertion of more characters if we're a multiline input
|
||||
// and maxLength exists
|
||||
var _this$props2 = _this.props;
|
||||
var multiline = _this$props2.multiline;
|
||||
var maxLength = _this$props2.maxLength;
|
||||
var onKeyPress = _this$props2.onKeyPress;
|
||||
|
||||
if (multiline && maxLength) {
|
||||
// check if smt is selected, in which case the newly added charcter would
|
||||
// replace the selected characters, so the length of value doesn't actually
|
||||
// increase.
|
||||
var isReplacing = event.target.selectionEnd - event.target.selectionStart;
|
||||
var value = event.target.value;
|
||||
|
||||
if (!isReplacing && value.length === maxLength) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (onKeyPress) onKeyPress(event);
|
||||
}, _temp), _possibleConstructorReturn(_this, _ret);
|
||||
}
|
||||
|
||||
|
@ -76,6 +110,7 @@ var factory = function factory(FontIcon) {
|
|||
value: function componentDidMount() {
|
||||
if (this.props.multiline) {
|
||||
window.addEventListener('resize', this.handleAutoresize);
|
||||
this.handleAutoresize();
|
||||
}
|
||||
}
|
||||
}, {
|
||||
|
@ -87,10 +122,16 @@ var factory = function factory(FontIcon) {
|
|||
window.removeEventListener('resize', this.handleAutoresize);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
key: 'componentDidUpdate',
|
||||
value: function componentDidUpdate() {
|
||||
// resize the textarea, if nessesary
|
||||
if (this.props.multiline) this.handleAutoresize();
|
||||
}
|
||||
}, {
|
||||
key: 'componentWillUnmount',
|
||||
value: function componentWillUnmount() {
|
||||
window.removeEventListener('resize', this.handleAutoresize);
|
||||
if (this.props.multiline) window.removeEventListener('resize', this.handleAutoresize);
|
||||
}
|
||||
}, {
|
||||
key: 'blur',
|
||||
|
@ -122,8 +163,9 @@ var factory = function factory(FontIcon) {
|
|||
var theme = _props.theme;
|
||||
var type = _props.type;
|
||||
var value = _props.value;
|
||||
var onKeyPress = _props.onKeyPress;
|
||||
|
||||
var others = _objectWithoutProperties(_props, ['children', 'disabled', 'error', 'floating', 'hint', 'icon', 'name', 'label', 'maxLength', 'multiline', 'required', 'theme', 'type', 'value']);
|
||||
var others = _objectWithoutProperties(_props, ['children', 'disabled', 'error', 'floating', 'hint', 'icon', 'name', 'label', 'maxLength', 'multiline', 'required', 'theme', 'type', 'value', 'onKeyPress']);
|
||||
|
||||
var length = maxLength && value ? value.length : 0;
|
||||
var labelClassName = (0, _classnames5.default)(theme.label, _defineProperty({}, theme.fixed, !floating));
|
||||
|
@ -132,7 +174,7 @@ var factory = function factory(FontIcon) {
|
|||
|
||||
var valuePresent = value !== null && value !== undefined && value !== '' && !((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === Number && isNaN(value));
|
||||
|
||||
var InputElement = _react2.default.createElement(multiline ? 'textarea' : 'input', _extends({}, others, {
|
||||
var inputElementProps = _extends({}, others, {
|
||||
className: (0, _classnames5.default)(theme.inputElement, _defineProperty({}, theme.filled, valuePresent)),
|
||||
onChange: this.handleChange,
|
||||
ref: 'input',
|
||||
|
@ -141,9 +183,17 @@ var factory = function factory(FontIcon) {
|
|||
disabled: disabled,
|
||||
required: required,
|
||||
type: type,
|
||||
value: value,
|
||||
maxLength: maxLength
|
||||
}));
|
||||
value: value
|
||||
});
|
||||
if (!multiline) {
|
||||
inputElementProps.maxLength = maxLength;
|
||||
inputElementProps.onKeyPress = onKeyPress;
|
||||
} else {
|
||||
inputElementProps.rows = 1;
|
||||
inputElementProps.onKeyPress = this.onKeyPress;
|
||||
}
|
||||
|
||||
var InputElement = _react2.default.createElement(multiline ? 'textarea' : 'input', inputElementProps);
|
||||
|
||||
return _react2.default.createElement(
|
||||
'div',
|
||||
|
|
Loading…
Reference in New Issue