Archived course lesson
Add a Delete Ingredient Button
Objective: Create a delete button for the GenerateIngredients component that will allow users to remove ingredients from the list.
We need to create a delete button for each ingredient to ensure that users can remove unneeded ingredients from the list. We can add an additional column by concatinating a delete column onto the list of columns that we already have.
import { Row, Col, Button, Table, Input, Dropdown } from 'antd';
import { MenuList } from './MenuList';
import * as _ from 'lodash';
type IngredientsProps = {
names?: string[];
values?: [{ amount: string; unit: string; type: string }];
handleAddIngredient: (event: any) => void;
handleDeleteIngredient: (event: any) => void;
handleInputChange: (event: any) => void;
handleDropdownChange: (event: any) => void;
};
const units = ['-', 'ounce', 'lb', 'cup', 'tb', 'tsp', 'g', 'kg'];
export const GenerateIngredients = ({
names,
values,
handleAddIngredient,
handleDeleteIngredient,
handleInputChange,
handleDropdownChange,
}: IngredientsProps) => {
const columns = _.concat(
names.map((name) => ({
title: `${name}`,
key: `${name}`,
render: (ingredient, _record, index: number) => {
return name === 'unit' ? (
<Dropdown
overlay={
<MenuList
iterableList={units}
name={`ingredients[${index}].${name}`}
handleDropdownChange={handleDropdownChange}
/>
}
placement="bottomLeft"
>
<Button>{ingredient[name]}</Button>
</Dropdown>
) : (
<Input
value={ingredient[name]}
placeholder={`${name}`}
name={`ingredients[${index}].${name}`}
onChange={handleInputChange}
/>
);
},
})),
[
{
title: 'delete',
key: 'delete',
render: (_ingredient, _record, index: number) => (
<Button
onClick={handleDeleteIngredient}
type="danger"
shape="circle"
size="small"
name={`${index}`}
>
-
</Button>
),
},
],
);
return (
<>
<Row>
<Col span={12} offset={6}>
<p>
<Button
onClick={handleAddIngredient}
type="primary"
shape="circle"
size="small"
>
+
</Button>
ingredients:
</p>
</Col>
</Row>
{values.length > 0 ? (
<Row>
<Col span={12} offset={6}>
<Table
dataSource={values}
columns={columns}
pagination={{ pageSize: 25 }}
/>
</Col>
</Row>
) : null}
</>
);
};
The delete button will call a delete ingredient handler, so we need to now create this in the submitForm hook and pass it into the <GenerateIngredients> component
import { useState } from 'react';
import * as _ from 'lodash';
export const submitForm = (initialValues, callback) => {
const [inputs, setInputs] = useState(initialValues);
const handleInputChange = (event) => {
event.persist();
setInputs((inputs) => {
const newInputs = _.cloneDeep(inputs);
_.set(newInputs, event.target.name, event.target.value);
return newInputs;
});
};
const handleDropdownChange = (event) => {
setInputs((inputs) => {
const newInputs = _.cloneDeep(inputs);
_.set(newInputs, event.item.props.title, event.key);
return newInputs;
});
};
const handleAddIngredient = (event) => {
event.persist();
setInputs((inputs) => {
const sortedIngredients = _.sortBy(inputs.ingredients, ['key']);
const key =
sortedIngredients.length > 0
? sortedIngredients[sortedIngredients.length - 1].key + 1
: 0;
return {
...inputs,
ingredients: _.concat(inputs.ingredients, [
{ key, amount: '', unit: '-', type: '' },
]),
};
});
};
const handleDeleteIngredient = (event) => {
console.log('deleted');
event.persist();
const position = parseInt(event.target.name);
setInputs((inputs) => ({
...inputs,
ingredients: _.filter(
inputs.ingredients,
(_i, index) => index !== position,
),
}));
};
const handleSubmit = () => {
callback();
setInputs(() => ({ ...initialValues }));
};
return {
inputs,
handleSubmit,
handleInputChange,
handleAddIngredient,
handleDeleteIngredient,
handleDropdownChange,
};
};