nenu-lang / page-apis-and-ui
Stable

Page APIs, Navigation, And UI

  • Import an API from its root-qualified api path and call the local alias.
  • Use goto with a known page route and primitive dynamic parameters.
  • Open a modal with one imported component object and use toast for visible feedback.

Import And Call An API

code
1use api/expenses/list as ListExpensesApi2use "api/expenses/create" as CreateExpenseApi34fn refreshExpenses() {5  result = ListExpensesApi({ room_id })6  expenses = result.expenses7}89fn createExpense() {10  created = CreateExpenseApi({11    room_id12    payer_id13    title: draft_title14    amount: draft_amount15    note: draft_note16  })1718  expenses = expenses + [created.expense]19}
  • Use a root-qualified target beginning with api/.
  • An unquoted target and a quoted target are equivalent.
  • The alias is required and becomes the callable name.
  • Call the alias with no payload only when the Request contract permits it.
  • Pass one map payload when fields are required; missing or incompatible fields are type errors.
  • The call result is typed from the API Response contract.

Name A Type From An API Response

code
1type ExpenseRow as Response("/expenses/list").expenses.item23ExpenseRow[] expenses = []45fn refreshExpenses() {6  result = ListExpensesApi({ room_id })7  expenses = result.expenses8}
  • Use type Name as Response("/route"); the alias keyword is as, not =.
  • The quoted route identifies an API Response contract known to the project.
  • Add selectors such as .expenses.item to name a nested field or an array item type.
  • An entity item alias includes its generated system fields, including id, createdAt, and updatedAt.
  • Response aliases are supported at Page Script top level. There is no corresponding public Request(...) alias form.
code
1goto("/expenses")
  • The route string must identify a known Page path.
  • Dynamic values must be string, number, or bool.
  • The explicit params map is canonical, especially for a dotted value such as expense.id.
  • Omit the map only when every bracket parameter has a same-name primitive local.
  • A guaranteed goto() makes later statements on that path unreachable.

Open A Typed Modal

Import a library component, then pass exactly one component object to modal.show. The component’s Page Script need block defines the required values and callbacks.

code
1use library/AddExpense as AddExpenseModal23fn handleSaved(Expense expense) {4  expenses = expenses + [expense]5  toast.success("Expense added")6}78fn openAddExpense() {9  modal.show(AddExpenseModal {10    room_id11    onSaved: handleSaved12  })13}1415fn cancelModal() {16  modal.close()17}
  • The component must be imported before use.
  • Component values use name: value fields inside the object.
  • Callback values are handler references, not calls.
  • The owner page decides how to update its state after the modal succeeds.

Show Feedback With toast

code
1toast.success("Expense saved")2toast.warning("Some shares are still missing")3toast.error("Expense could not be saved")

A toast is visible page feedback. It is not a backend log, a durable audit record, or an API error contract. Put it after the page knows which outcome occurred.

Complete Room Page Script

code
1use api/expenses/list as ListExpensesApi2use api/expenses/create as CreateExpenseApi3use library/AddExpense as AddExpenseModal45need {6  room_id: string7}89Expense[] expenses = []10bool loading = false11Expense? selected_expense = ?1213fn refreshExpenses() {14  loading = true15  result = ListExpensesApi({ room_id })16  expenses = result.expenses17  loading = false18}1920fn handleSaved(Expense expense) {21  expenses = expenses + [expense]22  toast.success("Expense added")23}2425fn openCreate() {26  modal.show(AddExpenseModal {27    room_id28    onSaved: handleSaved29  })30}3132fn openExpense(Expense expense) {33  goto("/expenses/[id]", { id: expense.id })34}3536on load() {37  refreshExpenses()38}

Common Mistakes

WrongCorrect
Direct api(...)use api/path as Alias, then Alias(...).
Target apis/expenses/listTarget api/expenses/list.
goto("/expenses/[expense.id]")goto("/expenses/[id]", { id: expense.id })
modal.show("AddExpense")Import the component and pass one typed component object.
Use backend log for feedbackUse a Page Script toast.

Continue Learning