Stateful components like Surface.LiveView and Surface.LiveComponent hold their state in the socket's assigns. In Surface, those assigns are called data assigns.

In order to declare a data assign, you must use the data function:

data name, type, options


  • name - is the name of the assign.
  • type - an atom defining the type of the assign. See all available types in section "Properties > Property types".
  • options - a keyword list of options for additional customization.

Supported options

  • default - defines a default value for the assign.
  • values - the list of possible values for the assign.

In the following example, we create a simple Counter component that has its state defined by a single assign named count. You can use the - and + buttons to decrement/increment the counter's value.


defmodule Counter do
use Surface.LiveComponent

data count, :integer, default: 0

def render(assigns) do
<h1 class="title">
{{ @count }}
<button class="button is-info" :on-click="dec"> - </button>
<button class="button is-info" :on-click="inc"> + </button>

def handle_event("inc", _value, socket) do
{:noreply, update(socket, :count, & &1 + 1)}

def handle_event("dec", _value, socket) do
{:noreply, update(socket, :count, & &1 - 1)}

Note: Since we defined a default value for count, we don't need to implement the mount/1 callback to initialize it. All data assigns with default values will be automatically initialized by Surface.