Skip to content

Commit 4e3afaa

Browse files
committed
Add delete button to vanilla array control
1 parent 5eff5d8 commit 4e3afaa

File tree

2 files changed

+97
-81
lines changed

2 files changed

+97
-81
lines changed

packages/vanilla/src/complex/TableArrayControl.tsx

Lines changed: 83 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,13 @@ export const tableArrayControlTester: RankedTester = rankWith(
6363
or(isObjectArrayControl, isPrimitiveArrayControl)
6464
);
6565

66-
class TableArrayControl extends React.Component<
67-
ArrayControlProps & VanillaRendererProps,
68-
any
69-
> {
66+
class TableArrayControl extends React.Component<ArrayControlProps & VanillaRendererProps, any> {
67+
68+
confirmDelete = (path: string, index: number) => {
69+
const p = path.substring(0, path.lastIndexOf(('.')));
70+
this.props.removeItems(p, [index])();
71+
};
72+
7073
render() {
7174
const {
7275
addItem,
@@ -124,9 +127,10 @@ class TableArrayControl extends React.Component<
124127
fpmap(prop => <th key={prop}>{startCase(prop)}</th>)
125128
)(schema.properties)
126129
) : (
127-
<th>Items</th>
128-
)}
130+
<th>Items</th>
131+
)}
129132
<th>Valid</th>
133+
<th>&nbsp;</th>
130134
</tr>
131135
</thead>
132136
<tbody>
@@ -135,72 +139,84 @@ class TableArrayControl extends React.Component<
135139
<td>No data</td>
136140
</tr>
137141
) : (
138-
data.map((_child, index) => {
139-
const childPath = Paths.compose(
140-
path,
141-
`${index}`
142-
);
143-
// TODO
144-
const errorsPerEntry: any[] = filter(childErrors, error =>
145-
error.dataPath.startsWith(childPath)
146-
);
142+
data.map((_child, index) => {
143+
const childPath = Paths.compose(
144+
path,
145+
`${index}`
146+
);
147+
// TODO
148+
const errorsPerEntry: any[] = filter(childErrors, error =>
149+
error.dataPath.startsWith(childPath)
150+
);
147151

148-
return (
149-
<tr key={childPath}>
150-
{schema.properties ? (
151-
fpflow(
152-
fpkeys,
153-
fpfilter(
154-
prop => schema.properties[prop].type !== 'array'
155-
),
156-
fpmap(prop => {
157-
const childPropPath = Paths.compose(
158-
childPath,
159-
prop.toString()
160-
);
152+
return (
153+
<tr key={childPath}>
154+
{schema.properties ? (
155+
fpflow(
156+
fpkeys,
157+
fpfilter(
158+
prop => schema.properties[prop].type !== 'array'
159+
),
160+
fpmap(prop => {
161+
const childPropPath = Paths.compose(
162+
childPath,
163+
prop.toString()
164+
);
161165

162-
return (
163-
<td key={childPropPath}>
164-
<DispatchCell
165-
schema={Resolve.schema(schema, `#/properties/${prop}`, rootSchema)}
166-
uischema={createControlElement(prop)}
167-
path={childPath + '.' + prop}
168-
/>
169-
</td>
170-
);
171-
})
172-
)(schema.properties)
173-
) : (
174-
<td
175-
key={Paths.compose(
176-
childPath,
177-
index.toString()
166+
return (
167+
<td key={childPropPath}>
168+
<DispatchCell
169+
schema={Resolve.schema(schema, `#/properties/${prop}`, rootSchema)}
170+
uischema={createControlElement(prop)}
171+
path={childPath + '.' + prop}
172+
/>
173+
</td>
174+
);
175+
})
176+
)(schema.properties)
177+
) : (
178+
<td
179+
key={Paths.compose(
180+
childPath,
181+
index.toString()
182+
)}
183+
>
184+
<DispatchCell
185+
schema={schema}
186+
uischema={createControlElement()}
187+
path={childPath}
188+
/>
189+
</td>
178190
)}
179-
>
180-
<DispatchCell
181-
schema={schema}
182-
uischema={createControlElement()}
183-
path={childPath}
184-
/>
185-
</td>
186-
)}
187-
<td>
188-
{errorsPerEntry ? (
189-
<span
190-
className={getStyleAsClassName(
191-
'array.validation.error'
191+
<td>
192+
{errorsPerEntry ? (
193+
<span
194+
className={getStyleAsClassName(
195+
'array.validation.error'
196+
)}
197+
>
198+
{join(errorsPerEntry.map(e => e.message), ' and ')}
199+
</span>
200+
) : (
201+
<span>OK</span>
192202
)}
203+
</td>
204+
<td>
205+
<button
206+
aria-label={`Delete`}
207+
onClick={() => {
208+
if (window.confirm('Are you sure you wish to delete this item?')) {
209+
this.confirmDelete(childPath, index);
210+
}
211+
}}
193212
>
194-
{join(errorsPerEntry.map(e => e.message), ' and ')}
195-
</span>
196-
) : (
197-
<span>OK</span>
198-
)}
199-
</td>
200-
</tr>
201-
);
202-
})
203-
)}
213+
Delete
214+
</button>
215+
</td>
216+
</tr>
217+
);
218+
})
219+
)}
204220
</tbody>
205221
</table>
206222
</div>

packages/vanilla/test/renderers/TableArrayControl.test.tsx

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ test('render two children', t => {
109109
t.is(tHead.children.length, 1);
110110
const headRow = tHead.children.item(0);
111111
t.is(headRow.tagName, 'TR');
112-
// two data columns + validation column
113-
t.is(headRow.children.length, 3);
112+
// two data columns + validation column + delete column
113+
t.is(headRow.children.length, 4);
114114

115115
const headColumn1 = headRow.children.item(0);
116116
t.is(headColumn1.tagName, 'TH');
@@ -125,11 +125,11 @@ test('render two children', t => {
125125
t.is(tBody.children.length, 1);
126126
const bodyRow = tBody.children.item(0);
127127
t.is(bodyRow.tagName, 'TR');
128-
// two data columns + validation column
129-
t.is(bodyRow.children.length, 3);
128+
// two data columns + validation column + delete column
129+
t.is(bodyRow.children.length, 4);
130130

131131
const tds = TestUtils.scryRenderedDOMComponentsWithTag(tree, 'td');
132-
t.is(tds.length, 3);
132+
t.is(tds.length, 4);
133133
t.is(tds[0].children.length, 1);
134134
t.is(tds[0].children[0].id, '');
135135
t.is(tds[1].children.length, 1);
@@ -176,8 +176,8 @@ test('render empty data', t => {
176176

177177
const headRow = tHead.children.item(0);
178178
t.is(headRow.tagName, 'TR');
179-
// two data columns + validation column
180-
t.is(headRow.children.length, 3);
179+
// two data columns + validation column + delete column
180+
t.is(headRow.children.length, 4);
181181

182182
const headColumn1 = headRow.children.item(0);
183183
t.is(headColumn1.tagName, 'TH');
@@ -282,8 +282,8 @@ test('render new child', t => {
282282
</Provider>
283283
) as unknown as React.Component<any>;
284284

285-
const button = TestUtils.findRenderedDOMComponentWithTag(tree, 'button') as HTMLButtonElement;
286-
TestUtils.Simulate.click(button);
285+
const addButton = TestUtils.scryRenderedDOMComponentsWithTag(tree, 'button')[0] as HTMLButtonElement;
286+
TestUtils.Simulate.click(addButton);
287287
t.is(getData(store.getState()).test.length, 2);
288288
});
289289

@@ -341,14 +341,14 @@ test('update via action', t => {
341341
const children = TestUtils.findRenderedDOMComponentWithTag(tree, 'tbody');
342342
t.is(children.childNodes.length, 1);
343343

344-
store.dispatch(update('test', () => [{x: 1, y: 3}, {x: 2, y: 3}]));
344+
store.dispatch(update('test', () => [{ x: 1, y: 3 }, { x: 2, y: 3 }]));
345345
t.is(children.childNodes.length, 2);
346346

347-
store.dispatch(update(undefined, () => [{x: 1, y: 3}, {x: 2, y: 3}, {x: 3, y: 3}]));
347+
store.dispatch(update(undefined, () => [{ x: 1, y: 3 }, { x: 2, y: 3 }, { x: 3, y: 3 }]));
348348
t.is(children.childNodes.length, 2);
349349
});
350350

351-
test('tester', t => t.is(tableArrayControlTester({type: 'Foo'}, null), -1));
351+
test('tester', t => t.is(tableArrayControlTester({ type: 'Foo' }, null), -1));
352352

353353
test('tester with recursive document ref only', t => {
354354
const control: ControlElement = {
@@ -578,7 +578,7 @@ test.skip('validation of nested schema', t => {
578578
type: 'object',
579579
properties: {
580580
middleName: { type: 'string' },
581-
lastName: { type: 'string' }
581+
lastName: { type: 'string' }
582582
},
583583
required: ['middleName', 'lastName']
584584
}
@@ -611,7 +611,7 @@ test.skip('validation of nested schema', t => {
611611
});
612612
const tree: React.Component<any> = TestUtils.renderIntoDocument(
613613
<Provider store={store}>
614-
<HorizontalLayoutRenderer schema={schema} uischema={uischema}/>
614+
<HorizontalLayoutRenderer schema={schema} uischema={uischema} />
615615
</Provider>
616616
) as unknown as React.Component<any>;
617617
const validation = TestUtils.scryRenderedDOMComponentsWithClass(tree, 'validation');

0 commit comments

Comments
 (0)