extpoint-yii2
Version:
JavaScript part for projects on ExtPoint Yii2 Boilerplate and yii2-core
206 lines (183 loc) • 6.42 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import {FieldArray} from 'redux-form';
import _isBoolean from 'lodash-es/isBoolean';
import _get from 'lodash-es/get';
import {types, view} from 'components';
import Field from './Field';
class FieldsListArrayComponent extends React.Component {
static propTypes = {
fields: PropTypes.shape({
push: PropTypes.func,
map: PropTypes.func,
remove: PropTypes.func,
}),
columns: PropTypes.arrayOf(PropTypes.shape({
attribute: PropTypes.string,
prefix: PropTypes.string,
model: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
]),
label: PropTypes.oneOfType([
PropTypes.string,
PropTypes.bool,
PropTypes.element,
]),
hint: PropTypes.oneOfType([
PropTypes.string,
PropTypes.bool,
PropTypes.element,
]),
component: PropTypes.any,
})),
initialRowsCount: PropTypes.number,
editable: PropTypes.bool,
required: PropTypes.bool,
};
static defaultProps = {
initialRowsCount: 1,
editable: true,
};
static contextTypes = {
model: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
]),
};
componentWillMount() {
if (this.props.fields.length === 0) {
for (let i = 0; i < this.props.initialRowsCount; i++) {
this.props.fields.push();
}
}
}
render() {
const {fields, columns, ...props} = this.props;
const FieldsListView = this.props.view || view.getFormView('FieldsListView');
const errors = [].concat(_get(this.props, 'meta.error.' + this.props.attribute, []));
return (
<span>
{fields.map(
(prefix, rowIndex) => columns.map(
(column, columnIndex) => this.renderPkField(column, prefix, rowIndex, columnIndex)
)
)}
<FieldsListView
{...props}
errorProps={errors.length === 0 ? null :{
error: errors.join(', ')
}}
rows={fields.map(prefix => ({
renderField: (column) => this.renderField(column, prefix),
}))}
columns={this.props.columns
.map(column => {
const metaItem = this.getItem(column);
if (metaItem.appType === 'primaryKey') {
return null;
}
const label = column.label || column.label === false || column.label === '' ? column.label : metaItem.label || '';
return {
...column,
labelProps: label === false ? null : {
label,
hint: column.hint || column.hint === false || column.hint === '' ? column.hint : metaItem.hint || '',
required: _isBoolean(column.required) ? column.required : metaItem.required || false,
},
};
})
.filter(Boolean)
}
onAdd={() => fields.push()}
onRemove={index => fields.remove(index)}
/>
</span>
);
}
getItem(column) {
return types.getMetaItem(column.model || this.context.model, column.attribute);
}
renderPkField(column, prefix, rowIndex, columnIndex) {
const item = this.getItem(column);
if (item.appType !== 'primaryKey') {
return null;
}
if (column.prefix) {
prefix = prefix + '.' + column.prefix;
}
return (
<Field
{...column}
key={`${rowIndex}_${columnIndex}`}
prefix={prefix}
label={false}
labelProps={null}
/>
);
}
renderField(column, prefix) {
const item = this.getItem(column);
if (item.appType === 'primaryKey') {
return null;
}
if (column.prefix) {
prefix = prefix + '.' + column.prefix;
}
return (
<Field
{...column}
prefix={prefix}
label={false}
labelProps={null}
/>
);
}
}
export default class FieldsList extends React.Component {
static propTypes = {
attribute: PropTypes.string.isRequired,
model: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
]),
columns: PropTypes.arrayOf(PropTypes.shape({
attribute: PropTypes.string,
prefix: PropTypes.string,
model: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
]),
component: PropTypes.any,
})),
};
static contextTypes = {
formId: PropTypes.string.isRequired,
prefix: PropTypes.string,
};
static childContextTypes = {
model: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
]),
prefix: PropTypes.string,
};
getChildContext() {
return {
model: this.props.model,
prefix: '',
};
}
render() {
const name = (this.context.prefix ? this.context.prefix + '.' : '') + this.props.attribute;
return (
<FieldArray
{...this.props}
name={name}
component={FieldsListArrayComponent}
columns={this.props.columns}
formId={this.context.formId}
/>
);
}
}