C&C Docs
Log in

cnc-block

A scrollable pane that can hold another route. Point href at a block and that block renders inside — server-side on the first paint, then re-fetched and swapped when the href changes. With no href it is simply a flex column that scrolls, holding whatever you slot into it.

Quick start

Name a route in href. Nothing is fetched on mount — the fragment is already in the HTML the server sent.

block-content

Fragment A — /widgets/block-content

A block of its own, rendered by the server and spliced in where the cnc-block sits. It has its own controller and its own request.

no query on the href

<cnc-block href="/widgets/block-content"></cnc-block>

cnc-block and x-block

The embedding itself is x-block, a directive that works on any element — see Reactive embed . cnc-block is that directive plus three conveniences:

  • A layout. The host is flex flex-col flex-1 and the content area is flex-1 overflow-auto, so the pane takes the space it is given and scrolls its content rather than the page.
  • An attribute instead of an expression. x-block takes a JavaScript expression, so a literal route has to be written x-block="'/route'" with the inner quotes. href is a plain attribute.
  • name, which nothing on the raw directive offers.
Want Write
A fixed route inline, no layout of its own <div x-block="'/route'">
A scrolling pane in an application shell <cnc-block href="/route">
A pane whose route is part of the page's address <cnc-block name="panel" href="/route">

Things to know

  • An href that names no route renders nothing. Not an error, not a message, not the children you slotted — the pane is simply empty. There is no fallback slot, so check the route exists.
  • The embedded block is a real block. It brings its own controller, its own $req, its own scope and its own hydration. It is not a template partial sharing the parent's state; pass what it needs through the query string.
  • The pane wants a height to be worth using. Its scrolling comes from flex-1 and overflow-auto, which do nothing until an ancestor constrains the height. Inside an app-layout centre area that is already true; on a free-flowing page, set one.
  • name is inert. It resolves in the widget's init() by reading $req.query['__' + name], but a widget's init() runs against the render scope, where $req is only { path } — the query string never reaches it. Only a block controller is given $req.query. Use the $href workaround above.

Usage guidance

Reach for cnc-block when a region of the page has a life of its own — a detail pane beside a list, the body of a tabbed workspace, a dashboard cell that reloads on its own schedule. Each region stays a route you can open, test and cache by itself. When the region is just markup that belongs to this page, slot it in directly; a block boundary you do not need costs a controller and a scope. For a pane the user can drag and resize, use cnc-workspace, and for one that overlays the page rather than sitting in it, use cnc-drawer or cnc-modal.

← Back to Widgets