Properties
You can pass information from a parent component down to a child using properties.
In order to declare a property, you must use the prop
macro:
prop name, type, options
Where:
-
name
- is the name of the property. -
type
- an atom defining the type of the property. See all available types in section "Property types". -
options
- a keyword list of options for additional customization.
Supported options
-
required
- declares the property as required. Default isfalse
. -
default
- defines a default value for an optional property. -
values
- the list or range of values suggested for the property. -
values!
- the list or range of all possible values for the property. Unlikevalues
, this option enforces validation of the default value against the given list. -
accumulate
- instructs Surface to group all different values provided for that property into a single list. Default isfalse
, i.e. only the last value is passed.
Property types
When declaring a property, you can define the type of the assign using one of the following types:
:any
, :css_class
, :list
, :event
,
:boolean
, :string
, :time
, :date
, :datetime
, :naive_datetime
,
:number
, :integer
, :decimal
, :map
,
:fun
, :atom
, :module
, :changeset
, :form
, :keyword
,
:struct
, :tuple
, :pid
, :port
, :reference
, :bitstring
,
:range
, :mapset
, :regex
, :uri
and :path
.
Note: Currently, some of the types above work just as annotations and don't have any practical use aside from documentation. If the type you need is not in that list, you can safely use
:any
instead. However, some other types like:css_class
,:list
and:event
are handled differently, i.e. there are extra rules and behaviours applied to them.
CSS class property
In order to avoid working with string concatenation, which is annoying and error-prone,
Surface allows passing keyword lists directly to the class
property and improves
developer experience by automatically handling conditional classes.
Let's see how it works.
Imagine you want to create a button component that sets CSS classes based on the following rules:
-
button
- always set -
is-info
- always set -
is-loading
- set if@loading
is truthy -
is-rounded
- set if@rounded
is truthy
We can define our component like this:
defmodule MyButton do
use Surface.Component
prop loading, :boolean
prop rounded, :boolean
slot default
def render(assigns) do
~F"""
<button class={"button", "is-info", "is-loading": @loading, "is-rounded": @rounded}>
<#slot />
</button>
"""
end
end
Let's try it out.
Note: For regular HTML tags like
<button>
, theclass
attribute will be handled automatically as expected. For custom components, you need to instruct Surface to do so by setting the type of the property as:css_class
.
Event property
In order to declare an event property, you must use the prop
macro and
define the type as :event
:
prop name, :event, options
Where:
-
name
- is the name of the event. -
options
- a keyword list of options for additional customization.
Supported options
-
required
- declares the event as required. Default isfalse
. -
default
- defines a default value for an optional event.
Example:
defmodule MyButton do
use Surface.Component
@doc "Triggers on click"
prop click, :event
slot default
def render(assigns) do
~F"""
<button class="button" :on-click={@click}>
<#slot />
</button>
"""
end
end