MongoDB  >  Linking CRUD to Frontend

Linking CRUD to Frontend

Add Documents

You need to input the payload object on Line 5 and this try catch can go inside a function that can be triggered on a button click.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
try { const res = await fetch('/api/trades', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }); if (!res.ok) { setMessage('Save All failed'); return; } setCart([]); setQuery(''); setResults([]); setSuccessMessage('New Trades Saved!'); setSearchInfo(''); } catch (e) { console.error('save error', e); setSuccessMessage('Save All failed'); }

Search Documents

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const [page, setPage] = useState(1); const [nameQ, setNameQ] = useState(""); async function load(p = page) { try { const params = new URLSearchParams({ page: String(p), pageSize: String(pageSize), q: nameQ, status }); const res = await fetch('/api/trades?{params}'); const data = await res.json(); setRows(data.items || []); setTotal(data.total || 0); setPage(data.page || p); } catch { setError("Failed to load trades"); } finally { setLoading(false); } }
  • nameQ is the search term using when searching.
  • {params} should be ${params.toString()} on Line 7

Edit Document

Editing Documents is longer due to having to mutiple actions the user can take while editing.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
const [editingId, setEditingId] = useState(null); const [form, setForm] = useState({ buyPrice: "", sellPrice: "", shares: "", boughtAt: "", soldAt: "", leverage: "" }); const [savingId, setSavingId] = useState(null); const startEdit = (r) => { setEditingId(r._id); setForm({ buyPrice: r.buyPrice?.toFixed?.(2) ?? "", sellPrice: r.sellPrice != null ? Number(r.sellPrice).toFixed(2) : "", shares: r.shares ?? "", boughtAt: r.boughtAt ? new Date(r.boughtAt).toISOString().slice(0, 10) : "", soldAt: r.soldAt ? new Date(r.soldAt).toISOString().slice(0, 10) : "", leverage: r.leverage != null ? String(r.leverage) : "1", }); setError(""); }; const cancelEdit = () => { setEditingId(null); setForm({ buyPrice: "", sellPrice: "", shares: "", boughtAt: "", soldAt: "", leverage: "" }); }; const onEdit = (e) => setForm((prev) => ({ ...prev, [e.target.name]: e.target.value })); const saveRow = async (id) => { try { setSavingId(id); const body = { buyPrice: Number(form.buyPrice), shares: Number(form.shares), boughtAt: form.boughtAt || null, soldAt: form.soldAt || null, sellPrice: hasSellPrice ? Number(form.sellPrice) : null, leverage: form.leverage === "" ? 1 : Number(form.leverage), }; const res = await fetch('/api/trades/{id}', { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) }); if (!res.ok) throw new Error("Update failed"); await load(page); cancelEdit(); } catch { setError("Failed to save changes."); } finally { setSavingId(null); } };

{id} should be ${id} on Line 34

Delete Documents

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const [selectedIds, setSelectedIds] = useState(new Set()); // Delete Sigle Document const deleteRow = async (id) => { if (!confirm("Delete this trade?")) return; try { const res = await fetch('/api/trades/{id}', { method: "DELETE" }); if (!res.ok) throw new Error("Delete failed"); await load(page); } catch { setError("Failed to delete trade."); } }; // Delete Mutiple Documents const deleteSelected = async () => { if (selectedIds.size === 0) return; if (!confirm('Delete {selectedIds.size} selected trade(s)?')) return; try { const res = await fetch('/api/trades/bulk-delete', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ids: Array.from(selectedIds) }), }); if (!res.ok) throw new Error('Bulk delete failed'); clearSelection(); await load(page); } catch { setError('Failed to delete some trades.'); } };
  • {id} should be ${id} on Line 6
  • {selectedIds.size} should be ${selectedIds.size} on Line 16

🙌 Congrats, your application is now set up with a mongo backend!