2222 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2323 THE SOFTWARE.
2424*/
25+ import isEmpty from 'lodash/isEmpty' ;
26+ import filter from 'lodash/filter' ;
27+ import { DispatchField } from '@jsonforms/react' ;
2528import capitalize from 'lodash/capitalize' ;
26- import IconButton from '@material-ui/core/IconButton' ;
2729import React from 'react' ;
28- import { Table , TableBody , TableCell , TableHead , TableRow , Typography } from '@material-ui/core' ;
30+ import {
31+ FormHelperText ,
32+ Table ,
33+ TableBody ,
34+ TableCell ,
35+ TableHead ,
36+ TableRow ,
37+ Typography
38+ } from '@material-ui/core' ;
2939import {
3040 ArrayControlProps ,
3141 ControlElement ,
42+ formatErrorMessage ,
3243 Generate ,
3344 Helpers ,
3445 JsonSchema ,
3546 Paths
3647} from '@jsonforms/core' ;
37- import { DispatchField } from '@jsonforms/react ' ;
48+ import IconButton from '@material-ui/core/IconButton ' ;
3849import DeleteIcon from '@material-ui/icons/Delete' ;
3950import { WithDeleteDialogSupport } from './DeleteDialog' ;
4051import { ErrorObject } from 'ajv' ;
@@ -60,35 +71,38 @@ const generateCells = (
6071) => {
6172
6273 if ( scopedSchema . type === 'object' ) {
63- return getValidColumnProps ( scopedSchema )
64- . map ( prop => {
65- const cellPath = Paths . compose ( rowPath , prop ) ;
66- const props = {
67- propName : prop ,
68- scopedSchema,
69- rowPath,
70- cellPath,
71- errors : cellErrors
72- } ;
74+ return getValidColumnProps ( scopedSchema ) . map ( prop => {
75+ const cellPath = Paths . compose (
76+ rowPath ,
77+ prop
78+ ) ;
79+ const props = {
80+ propName : prop ,
81+ scopedSchema,
82+ rowPath,
83+ cellPath,
84+ errors : cellErrors
85+ } ;
7386
74- return ( < Cell key = { cellPath } { ...props } /> ) ;
75- } ) ;
87+ return < Cell key = { cellPath } { ...props } /> ;
88+ } ) ;
7689 } else {
7790 // primitives
7891 const props = {
7992 scopedSchema,
8093 rowPath,
8194 cellPath : rowPath ,
82- errors : cellErrors ,
95+ errors : cellErrors
8396 } ;
84- return ( < Cell key = { rowPath } { ...props } /> ) ;
97+ return < Cell key = { rowPath } { ...props } /> ;
8598 }
8699} ;
87100
88101const getValidColumnProps = ( scopedSchema : JsonSchema ) => {
89102 if ( scopedSchema . type === 'object' ) {
90- return Object . keys ( scopedSchema . properties )
91- . filter ( prop => scopedSchema . properties [ prop ] . type !== 'array' ) ;
103+ return Object . keys ( scopedSchema . properties ) . filter (
104+ prop => scopedSchema . properties [ prop ] . type !== 'array'
105+ ) ;
92106 }
93107 // primitives
94108 return [ '' ] ;
@@ -118,9 +132,21 @@ interface NonEmptyCellProps {
118132 rowPath : string ;
119133 propName ?: string ;
120134 scopedSchema : JsonSchema ;
135+ errors ?: any [ ] ;
121136}
122137
123- const NonEmptyCell = ( { rowPath, propName, scopedSchema } : NonEmptyCellProps ) => (
138+ const NonEmptyCell = ( {
139+ rowPath,
140+ propName,
141+ scopedSchema,
142+ errors
143+ } : NonEmptyCellProps ) => {
144+ const errorsPerEntry : any [ ] = filter (
145+ errors ,
146+ error => error . dataPath === rowPath + '.' + propName
147+ ) . map ( e => e . message ) ;
148+ const isValid = isEmpty ( errorsPerEntry ) ;
149+ return (
124150 < React . Fragment >
125151 < NoBorderTableCell >
126152 < DispatchField
@@ -130,11 +156,14 @@ const NonEmptyCell = ({ rowPath, propName, scopedSchema }: NonEmptyCellProps) =>
130156 scopedSchema . type === 'object' ? `#/properties/${ propName } ` : '#'
131157 ) }
132158 path = { rowPath }
133- showError
134159 />
160+ < FormHelperText error = { ! isValid } >
161+ { ! isValid && formatErrorMessage ( errorsPerEntry ) }
162+ </ FormHelperText >
135163 </ NoBorderTableCell >
136164 </ React . Fragment >
137165 ) ;
166+ } ;
138167
139168interface NonEmptyRowProps {
140169 childPath : string ;
@@ -143,22 +172,17 @@ interface NonEmptyRowProps {
143172 rowData : any ;
144173}
145174
146- const NonEmptyRow = (
147- {
148- childPath,
149- scopedSchema,
150- childErrors,
151- rowData,
152- openDeleteDialog
153- } : NonEmptyRowProps & WithDeleteDialogSupport ) => (
154-
155- < TableRow
156- key = { childPath }
157- hover
158- >
175+ const NonEmptyRow = ( {
176+ childPath,
177+ scopedSchema,
178+ childErrors,
179+ rowData,
180+ openDeleteDialog
181+ } : NonEmptyRowProps & WithDeleteDialogSupport ) => (
182+ < TableRow key = { childPath } hover >
159183 { generateCells ( NonEmptyCell , scopedSchema , childPath , childErrors ) }
160184 < NoBorderTableCell style = { styles . fixedCell } >
161- < div style = { { display : 'flex' , justifyContent : 'center' } } >
185+ < div style = { { display : 'flex' , justifyContent : 'center' } } >
162186 < IconButton
163187 aria-label = { `Delete` }
164188 onClick = { ( ) => openDeleteDialog ( childPath , rowData ) }
@@ -197,9 +221,10 @@ const TableRows = (
197221 } ) ;
198222} ;
199223
200- export class MaterialTableControl
201- extends React . Component < ArrayControlProps & WithDeleteDialogSupport , any > {
202-
224+ export class MaterialTableControl extends React . Component <
225+ ArrayControlProps & WithDeleteDialogSupport ,
226+ any
227+ > {
203228 render ( ) {
204229 const {
205230 label,
0 commit comments