Skip to content

Commit

Permalink
Include default values in plugable entities forms
Browse files Browse the repository at this point in the history
Changes in #2114 caused another issue with the pluggable entities forms:
default values were shown in forms, but never submitted to the server.

These changes move the logic taking care of default values to the
`ConfigurationForm` component, also removing incorrect uses of
`defaultValue` in inputs.

In this way, the object containing the data will contain the default
values at the beginning, and they will be overriden by any input the
user type in them.

Refs #2108
  • Loading branch information
Edmundo Alvarez committed Apr 21, 2016
1 parent 788335b commit d33267b
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 30 deletions.
@@ -1,6 +1,8 @@
import React from 'react';
import FieldHelpers from './FieldHelpers';

import FormsUtils from 'util/FormsUtils';

const BooleanField = React.createClass({
propTypes: {
autoFocus: React.PropTypes.bool,
Expand All @@ -14,14 +16,13 @@ const BooleanField = React.createClass({
const field = this.props.field;
const typeName = this.props.typeName;
const title = this.props.title;
const value = this._getEffectiveValue();
return (
<div className="form-group">
<div className="checkbox">
<label>
<input id={typeName + '-' + title}
type="checkbox"
checked={value}
checked={this.props.value}
name={`configuration[${title}]`}
onChange={this.handleChange}/>

Expand All @@ -34,12 +35,8 @@ const BooleanField = React.createClass({
</div>
);
},
_getEffectiveValue() {
return (this.props.value === undefined ? this.props.field.default_value : this.props.value);
},
handleChange() {
const newValue = !this._getEffectiveValue();
this.setState({value: newValue});
handleChange(event) {
const newValue = FormsUtils.getValueFromInput(event.target);
this.props.onChange(this.props.title, newValue);
},
});
Expand Down
Expand Up @@ -5,22 +5,19 @@ import BootstrapModalForm from 'components/bootstrap/BootstrapModalForm';
import { BooleanField, DropdownField, NumberField, TextField } from 'components/configurationforms';

const ConfigurationForm = React.createClass({
getInitialState() {
return this._copyStateFromProps(this.props);
},
componentWillMount() {
this.setState({values: $.extend({}, this.props.values)});
},
componentWillReceiveProps(props) {
this.setState(this._copyStateFromProps(props));
},
getDefaultProps() {
return {
values: {},
includeTitleField: true,
titleValue: '',
};
},
getInitialState() {
return this._copyStateFromProps(this.props);
},
componentWillReceiveProps(props) {
this.setState(this._copyStateFromProps(props));
},
getValue() {
const data = {};
const values = this.state.values;
Expand All @@ -31,16 +28,23 @@ const ConfigurationForm = React.createClass({
data.configuration = {};

$.map(this.state.configFields, function(field, name) {
data.configuration[name] = values[name] || '';
// Replace undefined with null, as JSON.stringify will leave out undefined fields from the DTO sent to the server
data.configuration[name] = (values[name] === undefined ? null : values[name]);
});

return data;
},
_copyStateFromProps(props) {
const effectiveTitleValue = (this.state && this.state.titleValue !== undefined ? this.state.titleValue : props.titleValue);
const defaultValues = {};

Object.keys(props.configFields).forEach(field => {
defaultValues[field] = props.configFields[field].default_value;
});

return {
configFields: $.extend({}, props.configFields),
values: $.extend({}, props.values),
values: $.extend({}, defaultValues, props.values),
titleValue: effectiveTitleValue,
};
},
Expand Down
Expand Up @@ -44,7 +44,7 @@ const DropdownField = React.createClass({
{FieldHelpers.optionalMarker(field)}
</label>

<select id={field.title} defaultValue={field.default_value} value={this.state.value}
<select id={field.title} value={this.state.value}
className="input-xlarge form-control" onChange={this.handleChange}
autoFocus={this.props.autoFocus} disabled={this.props.disabled}>
{options}
Expand Down
@@ -1,7 +1,7 @@
import React from 'react';
import FieldHelpers from './FieldHelpers';

import NumberUtils from 'util/NumberUtils';
import FormsUtils from 'util/FormsUtils';

const NumberField = React.createClass({
propTypes: {
Expand Down Expand Up @@ -36,15 +36,14 @@ const NumberField = React.createClass({
return this._getDefaultValidationSpecs();
},
handleChange(evt) {
const numericValue = NumberUtils.isNumber(evt.target.value) ? Number(evt.target.value) : undefined;
const numericValue = FormsUtils.getValueFromInput(evt.target);
this.props.onChange(this.props.title, numericValue);
},
render() {
const typeName = this.props.typeName;
const field = this.props.field;
const isRequired = !field.is_optional;
const validationSpecs = this.validationSpec(field);
const fieldValue = this.props.value !== undefined ? this.props.value : field.default_value;

// TODO: replace with bootstrap input component
return (
Expand All @@ -55,7 +54,7 @@ const NumberField = React.createClass({
</label>

<input id={field.title} type="number" required={isRequired} onChange={this.handleChange}
defaultValue={fieldValue} className="input-xlarge validatable form-control"
value={this.props.value} className="input-xlarge validatable form-control"
{...validationSpecs} autoFocus={this.props.autoFocus} />

<p className="help-block">{field.description}</p>
Expand Down
Expand Up @@ -25,30 +25,26 @@ const TextField = React.createClass({
this.props.onChange(this.state.title, evt.target.value);
this.setState({value: evt.target.value});
},
_fieldValue(field) {
return field.default_value;
},
render() {
const field = this.state.field;
const title = this.state.title;
const typeName = this.state.typeName;

let inputField;
const value = this._fieldValue(field);
const isRequired = !field.is_optional;
const fieldType = (!FieldHelpers.hasAttribute(field.attributes, 'textarea') && FieldHelpers.hasAttribute(field.attributes, 'is_password') ? 'password' : 'text');

if (FieldHelpers.hasAttribute(field.attributes, 'textarea')) {
inputField = (
<textarea id={title} className="form-control" rows={10}
name={'configuration[' + title + ']'} required={isRequired} defaultValue={value} value={this.state.value}
name={'configuration[' + title + ']'} required={isRequired} value={this.state.value}
onChange={this.handleChange} autoFocus={this.props.autoFocus}>
</textarea>
);
} else {
inputField = (
<input id={title} type={fieldType} className="form-control" name={'configuration[' + title + ']'} value={this.state.value}
onChange={this.handleChange} required={isRequired} defaultValue={this._fieldValue(field)} autoFocus={this.props.autoFocus} />
onChange={this.handleChange} required={isRequired} autoFocus={this.props.autoFocus} />
);
}

Expand Down

0 comments on commit d33267b

Please sign in to comment.