mirror of
https://github.com/vale981/Vulcan
synced 2025-03-09 12:16:37 -04:00
117 lines
3.4 KiB
JavaScript
117 lines
3.4 KiB
JavaScript
import React, { PureComponent } from 'react';
|
|
import PropTypes from 'prop-types';
|
|
import { intlShape } from 'meteor/vulcan:i18n';
|
|
import { Components, registerComponent, instantiateComponent } from 'meteor/vulcan:core';
|
|
import classNames from 'classnames';
|
|
|
|
class FormComponentInner extends PureComponent {
|
|
renderClear = () => {
|
|
if (['datetime', 'time', 'select', 'radiogroup'].includes(this.props.input)) {
|
|
return (
|
|
<a
|
|
href="javascript:void(0)"
|
|
className="form-component-clear"
|
|
title={this.context.intl.formatMessage({ id: 'forms.clear_field' })}
|
|
onClick={this.props.clearField}
|
|
>
|
|
<span>✕</span>
|
|
</a>
|
|
);
|
|
}
|
|
};
|
|
|
|
getProperties = () => {
|
|
const { name, path, options, label, onChange, value, disabled, inputType } = this.props;
|
|
|
|
// these properties are whitelisted so that they can be safely passed to the actual form input
|
|
// and avoid https://facebook.github.io/react/warnings/unknown-prop.html warnings
|
|
const inputProperties = {
|
|
name,
|
|
path,
|
|
options,
|
|
label,
|
|
onChange: event => {
|
|
// FormComponent's handleChange expects value as argument; look in target.checked or target.value
|
|
const inputValue = inputType === 'checkbox' ? event.target.checked : event.target.value;
|
|
onChange(inputValue);
|
|
},
|
|
value,
|
|
disabled,
|
|
...this.props.inputProperties,
|
|
};
|
|
|
|
return {
|
|
...this.props,
|
|
inputProperties,
|
|
};
|
|
};
|
|
|
|
render() {
|
|
const {
|
|
inputClassName,
|
|
name,
|
|
input,
|
|
beforeComponent,
|
|
afterComponent,
|
|
errors,
|
|
showCharsRemaining,
|
|
charsRemaining,
|
|
renderComponent,
|
|
formComponents,
|
|
} = this.props;
|
|
|
|
const FormComponents = formComponents;
|
|
|
|
const hasErrors = errors && errors.length;
|
|
|
|
const inputName = typeof input === 'function' ? input.name : input;
|
|
const inputClass = classNames(
|
|
'form-input',
|
|
inputClassName,
|
|
`input-${name}`,
|
|
`form-component-${inputName || 'default'}`,
|
|
{ 'input-error': hasErrors }
|
|
);
|
|
const properties = this.getProperties();
|
|
|
|
const FormInput = this.props.formInput;
|
|
|
|
return (
|
|
<div className={inputClass}>
|
|
{instantiateComponent(beforeComponent, properties)}
|
|
<FormInput {...properties}/>
|
|
{hasErrors ? <FormComponents.FieldErrors errors={errors} /> : null}
|
|
{this.renderClear()}
|
|
{showCharsRemaining && (
|
|
<div className={classNames('form-control-limit', { danger: charsRemaining < 10 })}>{charsRemaining}</div>
|
|
)}
|
|
{instantiateComponent(afterComponent, properties)}
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
|
|
FormComponentInner.propTypes = {
|
|
inputClassName: PropTypes.string,
|
|
name: PropTypes.string.isRequired,
|
|
input: PropTypes.any,
|
|
beforeComponent: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
afterComponent: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
clearField: PropTypes.func.isRequired,
|
|
errors: PropTypes.array.isRequired,
|
|
help: PropTypes.node,
|
|
onChange: PropTypes.func.isRequired,
|
|
showCharsRemaining: PropTypes.bool.isRequired,
|
|
charsRemaining: PropTypes.number,
|
|
charsCount: PropTypes.number,
|
|
charsMax: PropTypes.number,
|
|
inputComponent: PropTypes.func,
|
|
};
|
|
|
|
FormComponentInner.contextTypes = {
|
|
intl: intlShape,
|
|
};
|
|
|
|
FormComponentInner.displayName = 'FormComponentInner';
|
|
|
|
registerComponent('FormComponentInner', FormComponentInner);
|