Key part is this wrapper:

Fragment

Use Fragment to append #... to the generated URL:

<>
	~>doors.ALink{
		Model: Path{Docs: true},
		Fragment: "api",
	} <a>API</a>
</>

Active

Use Active when a link should reflect the current location.

<>
	~>doors.ALink{
		Model: Path{
			Dashboard: true,
			ID:        f.id,
		},
		Active: doors.Active{
			Indicator: doors.IndicatorOnlyAttr("aria-current", "page"),
		},
	} <a>Current page</a>
</>

When the current location matches, Doors applies the given indicators to the link element.

If Active.Indicator is empty, there is no active-link behavior.

Path

Active.PathMatcher controls how the path is compared.

Options:

  • doors.PathMatcherFull()
  • doors.PathMatcherStarts()
  • doors.PathMatcherSegments(i...)

If you do not set one, Doors defaults to full-path matching.

Query

Active.QueryMatcher controls query-string matching.

Available matchers:

  • doors.QueryMatcherIgnoreSome(params...)
  • doors.QueryMatcherIgnoreAll()
  • doors.QueryMatcherSome(params...)
  • doors.QueryMatcherIfPresent(params...)

The query matchers are applied in order, then Doors compares any remaining query parameters.

In practice:

  • IgnoreSome removes some keys from comparison
  • IgnoreAll ignores all remaining query parameters
  • Some compares only the listed keys at that step
  • IfPresent compares listed keys only when they exist

Helpers:

  • doors.QueryMatcherOnlyIgnoreSome(params...)
  • doors.QueryMatcherOnlyIgnoreAll()
  • doors.QueryMatcherOnlySome(params...)
  • doors.QueryMatcherOnlyIfPresent(params...)

Fragment Match

Set Active.FragmentMatch when #... should also be part of active matching.

By default, fragments are ignored for active-link matching.

Path Source

For programmatic navigation, update the current page's path source directly.

The doors.Source[Path] passed into your page is not just state. It is also the current route model for that page.

When you update or mutate that source:

  • Doors re-encodes the path model
  • the browser location is updated
  • the page reacts as if the user navigated there

This is the right approach when navigation belongs to a button, wizard step, form flow, or other interaction that is not naturally an anchor tag.

Mutate

Use Mutate when you want to preserve part of the current path and change the rest:

type App struct {
	path doors.Source[Path]
}

elem (a *App) goToCity(cityID int) {
	<button
		(doors.AClick{
			On: func(ctx context.Context, r doors.RequestEvent[doors.PointerEvent]) bool {
				a.path.Mutate(ctx, func(p Path) Path {
					p.Selector = false
					p.Dashboard = true
					p.ID = cityID
					return p
				})
				return false
			},
		})>
		Open city
	</button>
}

Update

Use Update when you already know the full target model:

a.path.Update(ctx, Path{
	Dashboard: true,
	ID:        cityID,
})

Lifecycle Actions

When an ALink upgrades to same-model dynamic navigation, it participates in the same request pipeline as other Doors attributes.

That is why it supports:

  • Scope
  • Indicator
  • Before
  • After
  • OnError

One useful special case: if OnError is left nil on a dynamic ALink, Doors falls back to a location reload.

For the action types themselves, see Actions.