Overriding Introduction
Overriding allows you to override how Iridium resolves your components inside it's rendering pipeline.
We recommend giving the Varients section a quick read before progressing.
Varients
A varient is just the term Iridium uses to describe the state of a component at different points in it's rendering journey. There are three typical varients.
- Resolvable
- Concrete
- View
Resolvable
A resolvable is the entry point to a host of Iridium's components. It's a representation of some state that needs to be resolved at runtime.
A FormInput field on your form is a typical example of a resolvable component. You can provide static state like a label through it's Label method, or a callback function (LabelFn) that can use the current request context to determine the state of the label
// static
FormInput("name").
Label("Your Name")
// callback
FormInput("name").
LabelFn(
func (ctx FieldContext) string {
// You can access the current request context through the
// ctx field here to set your label dynamically
if ctx.Request.URL.Path == "/admin/users/create" {
return "Label is on user's create page"
}
return "Your Name"
}
)Behind the scenese, both Label and LabelFn set the same value, either as a callback or static value
type InputResolvable[T any] struct {
LabelStr util.Resolvable[*context.FieldContext[T], string]
}You can see we defined a resolvable LabelStr field here. util.Resolvable can contain a callback that returns a string when provided that *context.FieldContext[T] struct, or simply a static string. Why LabelStr not just Label?
Are a FormInput and InputResolvable[T] different?
No, a FormInput is a alias for InputResolvable[T] you receive through type generation.
Type generation docs are here
Converting a Resolvable To a Concrete
Once you're finished defining your form for example FieldContext struct for you, passes it to your resolvable component, to produce a static form of your input called a concrete input.
Generating context and defining how a resolvable is converted to it's concrete form is an overridable process that you can learn more about here.
Concrete Varients
Concrete varients represent the state of your component after it has resolved all its state based on the current request.
type InputConcrete struct {
LabelStr string
}You can see now we have a finalized form of that LabelStr.
TIP
Concrete varients can live on their own. In fact, in custom pages, you can call on them directly to borrow our components and place them in your custom pages.
You can learn about re-using our components in your own custom pages here
Passing a Concrete Varient to a View Varient
Concrete varients register which view (or templ.Component) will be produced from their state in a callback function.
This is where most users will spend time overriding Iridium's defaults. Dedicated docs
Example
Here's how you might bind the concrete varient of an input to a templ.Component so that some HTML can be rendered out whenever an Input is created
bootstrap.RegisterNamedView[components.InputConcrete](
views.Input, // <- a simple constant to identify a view. Allows for multiple views per component
func(u components.InputConcrete) (templ.Component, error) {
// Here you are passed your concrete input varient whenever one is generated
// Now you can choose which templ.Component to return.
// You can choose any templ.Component here, allowing you to override Iridium's default view
// and provide your own.
},
)View Varient
The view varient is simple to understand. Generally view varients just embed their concrete forms and contain a Component method that returns the final templ.Component for rendering.