Last active
February 24, 2020 16:27
-
-
Save calebklc/34f8ecf60488b3670fc5a35f4015f2a1 to your computer and use it in GitHub Desktop.
Question about dynamic fields in ArrayField
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { asField } from 'informed'; | |
import { Form, Input } from 'antd'; | |
const AntdInput = asField(({ fieldState, fieldApi, ...props }) => { | |
const { value } = fieldState; | |
const { setValue, setTouched } = fieldApi; | |
const { | |
onChange, | |
onBlur, | |
initialValue, | |
forwardedRef, | |
formItemProps, | |
...rest | |
} = props; | |
const validateStatus = fieldState.error ? 'error' : ''; | |
const help = fieldState.error || null; | |
return ( | |
<Form.Item validateStatus={validateStatus} help={help} {...formItemProps}> | |
<Input | |
{...rest} | |
ref={forwardedRef} | |
value={!value && value !== 0 ? '' : value} | |
onChange={e => { | |
setValue(e.target.value); | |
if (onChange) { | |
onChange(e); | |
} | |
}} | |
onBlur={e => { | |
setTouched(true); | |
if (onBlur) { | |
onBlur(e); | |
} | |
}} | |
/> | |
</Form.Item> | |
); | |
}); | |
export default AntdInput; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Fragment, cloneElement, PureComponent } from 'react'; | |
import { ArrayField } from 'informed'; | |
import PropTypes from 'prop-types'; | |
import { Icon, Button, Row, Col } from 'antd'; | |
import { | |
MatrixDynamicTable, | |
MatrixDynamicRowItem, | |
MatrixDynamicAddRowBtn, | |
} from './matrix-dynamic.less'; | |
import { AntdInput } from '.'; | |
class AntdMatrixDynamic extends React.Component { | |
static propTypes = { | |
columnHeaders: PropTypes.array.isRequired, | |
columns: PropTypes.array.isRequired, | |
fields: PropTypes.array.isRequired, | |
add: PropTypes.func.isRequired, | |
columnWidths: PropTypes.array, | |
indexHeader: PropTypes.element, | |
indexColumn: PropTypes.oneOf([PropTypes.func, PropTypes.element]), | |
minRowCount: PropTypes.number, | |
maxRowCount: PropTypes.number | |
}; | |
static defaultProps = { | |
columnWidths: [], | |
indexHeader: null, | |
indexColumn: null, | |
minRowCount: 1, | |
maxRowCount: 0 | |
}; | |
labelTdWidth = '2%'; | |
deleteBtnTdWidth = '2%'; | |
fieldTdWidths = []; | |
constructor(props) { | |
super(props); | |
this.addMinRows(); | |
this.calculateTdWidths(); | |
} | |
addMinRows = () => { | |
const { minRowCount, add } = this.props; | |
for (let i = 0; i < minRowCount; i++) { | |
add(); | |
} | |
}; | |
calculateTdWidths = () => { | |
const { columnWidths, columns, indexColumn, indexHeader } = this.props; | |
if (columnWidths.length === 0) { | |
let tdWidths = []; | |
const tdWidth = `${Math.round(100 / columns.length)}%`; | |
if (indexColumn || indexHeader) { | |
tdWidths.push(this.labelTdWidth); | |
} | |
tdWidths = tdWidths.concat([ | |
...columns.map(c => tdWidth), | |
this.deleteBtnTdWidth | |
]); | |
return tdWidths; | |
} | |
const newLabelTdWidth = columnWidths.shift(); | |
const newDeleteBtnTdWidth = columnWidths.pop(); | |
if (newLabelTdWidth != null) { | |
this.labelTdWidth = newLabelTdWidth; | |
} | |
if (newDeleteBtnTdWidth != null) { | |
this.deleteBtnTdWidth = newDeleteBtnTdWidth; | |
} | |
const remainedWidth = columnWidths | |
.filter(columnWidth => columnWidth != null) | |
.reduce((total, columnWidth) => total - columnWidth, 100); | |
const useDefaultWidthCount = columnWidths.filter( | |
columnWidth => columnWidth == null | |
).length; | |
const defaultTdWidth = `${Math.round( | |
remainedWidth / useDefaultWidthCount | |
)}%`; | |
return columnWidths.map( | |
columnWidth => (columnWidth == null ? defaultTdWidth : `${columnWidth}%`) | |
); | |
}; | |
renderAddButton = ({ colspan }) => { | |
const { add } = this.props; | |
return ( | |
<td colSpan={colspan}> | |
<Button | |
type="dashed" | |
onClick={() => { | |
add(); | |
}} | |
className={MatrixDynamicAddRowBtn} | |
> | |
<Icon type="plus" /> Add | |
</Button> | |
</td> | |
); | |
}; | |
renderFields = fields => { | |
const { maxRowCount, minRowCount, indexColumn, columns } = this.props; | |
const displayRemoveBtn = fields.length > minRowCount; | |
const displayAddBtn = fields.length !== maxRowCount; | |
return ( | |
<Fragment> | |
{fields.map(({ field, key, remove, initialValue }, index) => { | |
const newColumns = columns.map(({ name, component }) => { | |
const defaultValue = initialValue && initialValue[name]; | |
return ( | |
<td key={`${key}.${field}.${name}.td`}> | |
{component({ | |
field: `${field}.${name}`, | |
className: MatrixDynamicRowItem, | |
initialValue: defaultValue | |
})} | |
</td> | |
); | |
}); | |
return ( | |
<tr key={key}> | |
{indexColumn && <td>{indexColumn(index + 1)}</td>} | |
{newColumns} | |
<td> | |
{displayRemoveBtn && ( | |
<Button | |
type="danger" | |
icon="delete" | |
htmlType="button" | |
onClick={() => { | |
remove(); | |
}} | |
/> | |
)} | |
</td> | |
</tr> | |
); | |
})} | |
<tr> | |
{displayAddBtn && this.renderAddButton({ colspan: columns.length })} | |
<td /> | |
</tr> | |
</Fragment> | |
); | |
}; | |
render() { | |
const { columnHeaders, indexHeader = null, fields } = this.props; | |
return ( | |
<Fragment> | |
<Row> | |
<table className={MatrixDynamicTable}> | |
<tr> | |
{indexHeader && <th width={this.labelTdWidth}>{indexHeader}</th>} | |
{columnHeaders.map((header, index) => ( | |
<th | |
key={`${header}.th${index}`} | |
width={this.fieldTdWidths[index]} | |
> | |
{header} | |
</th> | |
))} | |
<th width={this.deleteBtnTdWidth}> </th> | |
</tr> | |
{this.renderFields(fields)} | |
</table> | |
</Row> | |
</Fragment> | |
); | |
} | |
} | |
export default AntdMatrixDynamic; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Button, Checkbox, Col, Row } from "antd"; | |
import { LicFormPanel, intl } from "@my/common-modules"; | |
import { ArrayField } from "informed"; | |
import React from "react"; | |
import { | |
AntdCheckboxGroup, | |
AntdDatepicker, | |
AntdInput, | |
AntdMatrixDynamic | |
} from "../../../../../components/informed"; | |
const MainPage = () => { | |
return ( | |
<LicFormPanel title={intl.get("formsPart0")}> | |
<ArrayField field="matrixdynamic"> | |
{props => ( | |
<AntdMatrixDynamic | |
columnHeaders={[ | |
"First Name", | |
<span style={{ color: "red" }}>Last Name</span>, | |
"Date" | |
]} | |
columns={[ | |
{ | |
name: "firstName", | |
component: columnProps => <AntdInput {...columnProps} /> | |
}, | |
{ | |
name: "lastName", | |
component: columnProps => <AntdInput {...columnProps} /> | |
}, | |
{ | |
name: "date", | |
component: columnProps => ( | |
<AntdDatepicker {...columnProps} style={{ width: "100%" }} /> | |
) | |
} | |
]} | |
{...props} | |
/> | |
)} | |
</ArrayField> | |
</LicFormPanel> | |
); | |
}; | |
MainPage.displayName = "MainPage"; | |
export default MainPage; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment