Add Expense
{/* Add Expense Form - using $value binding */}
{
const desc = newDescription.get().trim();
const amt = parseFloat(newAmount.get());
const cat = newCategory.get().trim() || "Other";
if (desc && !isNaN(amt) && amt > 0) {
expenses.push({
description: desc,
amount: amt,
category: cat,
date: todayDate,
});
// Clear form
newDescription.set("");
newAmount.set("");
newCategory.set("Other");
}
}}
>
Add Expense
{/* Expense List with Remove */}
Expenses ({expenseCount})
{expenses.map((expense) => (
{expense.description} - ${expense.amount} ({expense.category})
{
const current = expenses.get();
const index = current.findIndex((el) =>
Cell.equals(expense, el)
);
if (index >= 0) {
expenses.set(current.toSpliced(index, 1));
}
}}
>
×
))}
{/* Budget Management */}
Set Budget Limit
{
const cat = budgetCategory.get().trim();
const limitVal = parseFloat(budgetLimit.get());
if (cat && !isNaN(limitVal) && limitVal >= 0) {
const current = budgets.get();
const existingIndex = current.findIndex((b) =>
b.category === cat
);
if (existingIndex >= 0) {
budgets.set(
current.map((
b,
i,
) => (i === existingIndex ? { ...b, limit: limitVal } : b)),
);
} else {
budgets.push({ category: cat, limit: limitVal });
}
// Clear form
budgetCategory.set("");
budgetLimit.set("");
}
}}
>
Set Budget
{/* Budget List */}
Budgets ({budgetCount})
{budgets.map((budget) => (
{budget.category}: ${budget.limit}
{
const current = budgets.get();
const index = current.findIndex((b) =>
Cell.equals(budget, b)
);
if (index >= 0) {
budgets.set(current.toSpliced(index, 1));
}
}}
>
×
))}
{/* Debug */}
Debug: Form State
{computed(() =>
JSON.stringify(
{
newDescription: newDescription.get(),
newAmount: newAmount.get(),
newCategory: newCategory.get(),
budgetCategory: budgetCategory.get(),
budgetLimit: budgetLimit.get(),
},
null,
2
)
)}
Debug: Raw Data
{computed(() =>
JSON.stringify(
{
expenses: expenses.get(),
budgets: budgets.get(),
},
null,
2
)
)}
),
// Export bound handlers as Streams (not shared cells - parent owns those)
addExpense,
setBudget,
removeBudget,
};
});