Vulcan/packages/vulcan-forms/lib/components/FormNested.jsx

104 lines
2.9 KiB
React
Raw Normal View History

2018-03-22 19:22:54 +09:00
import React, { PureComponent } from 'react';
2018-03-24 11:16:11 +09:00
import PropTypes from 'prop-types';
2018-03-22 19:22:54 +09:00
import { Components, registerComponent } from 'meteor/vulcan:core';
import Button from 'react-bootstrap/lib/Button';
2018-03-22 19:22:54 +09:00
2018-03-25 10:54:45 +09:00
const FormNestedItem = (
{ isDeleted, nestedFields, name, path, subDocument, removeItem, itemIndex, ...props },
{ errors }
) => {
2018-03-22 19:22:54 +09:00
return (
<div className={`form-nested-item ${isDeleted ? 'form-nested-item-deleted' : ''}`}>
<div className="form-nested-item-inner">
{nestedFields.map((field, i) => {
2018-03-24 11:16:11 +09:00
// note: default value to '' to avoid uncontrolled component error
2018-03-25 10:54:45 +09:00
let value = (subDocument && subDocument[field.name]) || '';
if (props.control === 'number') value = Number(value);
return (
<Components.FormComponent
key={i}
{...props}
{...field}
path={`${path}.${field.name}`}
value={value}
itemIndex={itemIndex}
/>
);
})}
</div>
<div className="form-nested-item-remove">
<Button
bsStyle="danger"
onClick={() => {
removeItem(name);
}}
>
</Button>
</div>
2018-03-25 10:54:45 +09:00
<div className="form-nested-item-deleted-overlay" />
2018-03-22 19:22:54 +09:00
</div>
);
};
2018-03-22 19:22:54 +09:00
2018-03-25 10:54:45 +09:00
FormNestedItem.contextTypes = {
errors: PropTypes.array,
};
2018-03-22 19:22:54 +09:00
registerComponent('FormNestedItem', FormNestedItem);
class FormNested extends PureComponent {
addItem = () => {
2018-03-25 10:54:45 +09:00
this.props.updateCurrentValues({ [`${this.props.path}.${this.props.value.length}`]: {} });
};
2018-03-22 19:22:54 +09:00
removeItem = index => {
2018-03-25 10:54:45 +09:00
this.props.updateCurrentValues({ [`${this.props.path}.${index}`]: null });
};
2018-03-22 19:22:54 +09:00
2018-03-24 11:16:11 +09:00
/*
Go through this.context.deletedValues and see if any value matches both the current field
and the given index (ex: if we want to know if the second address is deleted, we
look for the presence of 'addresses.1')
*/
isDeleted = index => {
2018-03-25 10:54:45 +09:00
return this.context.deletedValues.includes(`${this.props.path}.${index}`);
2018-03-24 11:16:11 +09:00
};
2018-03-22 19:22:54 +09:00
render() {
return (
<div className="form-group row form-nested">
<label className="control-label col-sm-3">{this.props.label}</label>
<div className="col-sm-9">
{this.props.value &&
2018-03-25 10:54:45 +09:00
this.props.value.map(
(subDocument, i) =>
!this.isDeleted(i) && (
<FormNestedItem
{...this.props}
key={i}
itemIndex={i}
subDocument={subDocument}
path={`${this.props.path}.${i}`}
removeItem={() => {
this.removeItem(i);
}}
/>
)
)}
<Button bsStyle="success" onClick={this.addItem}>
</Button>
2018-03-22 19:22:54 +09:00
</div>
</div>
);
2018-03-22 19:22:54 +09:00
}
}
2018-03-24 11:16:11 +09:00
FormNested.contextTypes = {
2018-03-25 10:54:45 +09:00
deletedValues: PropTypes.array,
};
2018-03-24 11:16:11 +09:00
registerComponent('FormNested', FormNested);