Skip to content
These are temporary community docs. The official docs are in progress.Help improve them
Markless
Esc
↑↓navigate↵open⌘Jpreview
On this page

Elements

Reach a real page element with element() handles, link elements without ids, and run setup code with attach.

A handler can change count. Sometimes it also needs the real <input>, to focus it or measure it.

An element is not state. Your component sets up the page before the element exists. So Markless gives you a handle: a name that points at one element once that element is on the page.

Click +1 and focus in the figure.

What does a handle point at?

Press +1 and focus. Watch the input get the number and the focus.

The pageTry it
Counter

The page's HTML. You never wrote an id.

<label for="a1">Count</label> <input id="a1" value="0"> <button>+1 and focus</button>
Your code: Counter.tsrx
import { element, state } from '@markless/core'; export default function Counter() @{ let count = state(0); const field = element<HTMLInputElement>(); (a handle) <section> <label for={field}>Count</label> (no id written) <input el={field} value={count} /> (links it here) <button onClick={() => { count++; field?.focus(); }}>+1 and focus</button> </section>}
What Markless did
What field points atthe inputfrom the moment it is on the page
Times focus moved0
  1. noteYour component ran and set up the page. The input did not exist yet, so field pointed at nothing.
  2. noteThe page is on screen. Now field points at the real input.

Simplified. Markless makes the id for you. Its real value looks different from "a1".

Notice that the handler reaches the real input. You never wrote an id, but the label still points at the input.

import { element, state } from '@markless/core';

export default function Counter() @{
	let count = state(0);
	const field = element<HTMLInputElement>();

	<section>
		<label for={field}>Count</label>
		<input el={field} value={count} />
		<button onClick={() => { count++; field?.focus(); }}>+1 and focus</button>
	</section>
}

el={field} links the handle to the <input>. In a handler, field is the element itself, or undefined if the element is not on the page. That is why the code writes field?.focus().

Look at for={field}. You never write an id. The compiler makes one and puts it on both elements. This works in for, aria-labelledby, aria-controls, aria-describedby, and popovertarget.

Setup code with attach

attach gives an element to your function. Use it for observers and outside libraries. If your function returns a cleanup function, Markless calls it when the element goes away.

<button
	attach={(button) => {
		const observer = new ResizeObserver(() => {});
		observer.observe(button);
		return () => observer.disconnect();
	}}
	onClick={() => count++}
>{count}</button>

attach works on page elements like <button>, not on components. On a component, it gives MARKLESS_ATTACH_HOST_ELEMENT_REQUIRED.

Next: What if a value comes from a slow network call? Async values →

Was this page helpful?