COMPONENT
Capy
function COMPONENT() function COMPONENT(props : any) function COMPONENT(request : any) function COMPONENT(props : any, request : any) function COMPONENT:NAME() function COMPONENT:NAME(props : any) function COMPONENT:NAME(request : any) function COMPONENT:NAME(props : any, request : any)
COMPONENT marks a function as a renderable fragment. Another unit reaches it with component() or component_render(); it is never routed to directly by a URL.
Every component body has props and request, both of type any. Their declarations are optional. The handler returns nothing. Everything it prints becomes the fragment's output.
Plain and named handlers
A file with a single fragment defines COMPONENT. Callers name just the file:
component_render("/doc/examples/plain_card.capy")Output
<article>Untitled</article>A file that holds several related fragments gives each one a name, and callers select it with a : suffix:
component_render("/doc/examples/card.capy:CARD")Output
<article>Untitled</article>A caller inside that same file can use the bare suffix form, component_render(":CARD"), which resolves to the current file.
Names are matched exactly and are conventionally uppercase.
Reading input
Caller-supplied props arrive through the props parameter. Read them through string(), s64(), and the other converters so a missing key has a defined value:
function COMPONENT(props : any)
{
var title := string(props.title, fallback: "Untitled")
print(title)
}Output
UntitledProps are shared objects. Changes to their contents remain visible to the caller. Each nested component receives its own props argument. Application request keys stay shared.
Request binding
This complete unit reads both implicit bindings without declaring parameters:
function COMPONENT()
{
print(<><p><?= props.title ?>: <?= request.method ?></p></>)
}
You can also declare both bindings explicitly:
function COMPONENT:CARD(props : any, request : any)
{
print(<><p><?= props.title ?>: <?= request.method ?></p></>)
}
You can declare only props : any or only request : any. If you declare both, props comes first. The names and the any type are fixed. The caller passes only the target and props, never a separate request argument.
Lifecycle
Bearer runs INIT when it loads the unit into the request workspace. Before the first render or component invocation, it runs ONCE. All named components in the unit share one ONCE call per request. Use this hook to emit shared CSS or JavaScript without repeating it for every fragment.
A component may render other components. Each nested call resolves relative paths against its own file.
print(string(props.name, fallback: "guest"))
Output
guestvar title := string(props.title, fallback: "Untitled")
var count := s64(props.count)
print("<article><h3>", title, "</h3><p>", count, "</p></article>")
Output
<article><h3>Untitled</h3><p>0</p></article>print("<section>")
component_render("/doc/examples/card.capy:CARD",
title: string(props.title, fallback: "Untitled")
)
print("</section>")
Output
<section><article>Untitled</article></section>Errors
An unresolved component sets the response status to 500 without adding fragment output. component() returns an empty string, and component_render() returns false. The caller continues, but the missing component handler never runs. Use component_resolve() to check an optional file before rendering it. This checks the file path, not whether a named handler exists.