Corex.Switch (Corex v0.1.0-alpha.29)

View Source

Phoenix implementation of Zag.js Switch.

Examples

Basic Usage

<.switch id="my-switch">
  <:label>Enable notifications</:label>
</.switch>

Controlled Mode

<.switch
  id="my-switch"
  controlled
  checked={@switch_checked}
  on_checked_change="switch_changed">
  <:label>Enable notifications</:label>
</.switch>
def handle_event("switch_changed", %{"checked" => checked}, socket) do
  {:noreply, assign(socket, :switch_checked, checked)}
end

Phoenix Form Integration

When using with Phoenix forms, you must add an id to the form using the Corex.Form.get_form_id/1 function.

Controller

defmodule MyAppWeb.PageController do
  use MyAppWeb, :controller

  def home(conn, params) do
    form = Phoenix.Component.to_form(Map.get(params, "user", %{}), as: :user)
    render(conn, :home, form: form)
  end
end
<.form :let={f} as={:user} for={@form} id={get_form_id(@form)} method="get">
  <.switch field={f[:notifications_enabled]} class="switch">
    <:label>Enable notifications</:label>
    <:error :let={msg}>
      <.icon name="hero-exclamation-circle" class="icon" />
      {msg}
    </:error>
  </.switch>
  <button type="submit">Submit</button>
</.form>

Live View

When using Phoenix form in a Live view you must also add controlled mode. This allows the Live view to be the source of truth and the component to be in sync accordingly.

defmodule MyAppWeb.SwitchLive do
  use MyAppWeb, :live_view

  def mount(_params, _session, socket) do
    form = to_form(%{"notifications_enabled" => "false"}, as: :user)
    {:ok, assign(socket, :form, form)}
  end

  def render(assigns) do
    ~H"""
    <.form as={:user} for={@form} id={get_form_id(@form)}>
      <.switch field={@form[:notifications_enabled]} class="switch">
        <:label>Enable notifications</:label>
        <:error :let={msg}>
          <.icon name="hero-exclamation-circle" class="icon" />
          {msg}
        </:error>
      </.switch>
      <button type="submit">Submit</button>
    </.form>
    """
  end
end

With Ecto changeset

When using Ecto changeset for validation and inside a Live view you must enable the controlled mode.

This allows the Live View to be the source of truth and the component to be in sync accordingly.

First create your schema and changeset:

defmodule MyApp.Accounts.User do
  use Ecto.Schema
  import Ecto.Changeset

  embedded_schema do
    field :notifications_enabled, :boolean, default: false
  end

  def changeset(user, attrs) do
    user
    |> cast(attrs, [:notifications_enabled])
    |> validate_required([:notifications_enabled])
  end
end
defmodule MyAppWeb.UserLive do
  use MyAppWeb, :live_view
  alias MyApp.Accounts.User

  def mount(_params, _session, socket) do
    {:ok, assign(socket, :form, to_form(User.changeset(%User{}, %{})))}
  end

  def handle_event("validate", %{"user" => user_params}, socket) do
    changeset = User.changeset(%User{}, user_params)
    {:noreply, assign(socket, form: to_form(changeset, action: :validate))}
  end

  def render(assigns) do
    ~H"""
    <.form for={@form} id={get_form_id(@form)} phx-change="validate">
      <.switch field={@form[:notifications_enabled]} class="switch" controlled>
        <:label>Enable notifications</:label>
        <:error :let={msg}>
          <.icon name="hero-exclamation-circle" class="icon" />
          {msg}
        </:error>
      </.switch>
    </.form>
    """
  end
end

Programmatic Control

# Client-side
<button phx-click={Corex.Switch.set_checked("my-switch", true)}>
  Turn On
</button>

<button phx-click={Corex.Switch.toggle_checked("my-switch")}>
  Toggle
</button>

# Server-side
def handle_event("turn_on", _, socket) do
  {:noreply, Corex.Switch.set_checked(socket, "my-switch", true)}
end

def handle_event("toggle", _, socket) do
  {:noreply, Corex.Switch.toggle_checked(socket, "my-switch")}
end

Styling

Use data attributes to target elements:

[data-scope="switch"][data-part="root"] {}
[data-scope="switch"][data-part="control"] {}
[data-scope="switch"][data-part="thumb"] {}
[data-scope="switch"][data-part="label"] {}
[data-scope="switch"][data-part="input"] {}
[data-scope="switch"][data-part="error"] {}

If you wish to use the default Corex styling, you can use the class switch on the component. This requires to install Mix.Tasks.Corex.Design first and import the component css file.

@import "../corex/main.css";
@import "../corex/tokens/themes/neo/light.css";
@import "../corex/components/switch.css";

You can then use modifiers

<.switch class="switch switch--accent switch--lg">

Learn more about modifiers and Corex Design

Summary

Components

Renders a switch component.

API

Sets the switch checked state from client-side. Returns a Phoenix.LiveView.JS command.

Sets the switch checked state from server-side. Pushes a LiveView event.

Toggles the switch checked state from client-side. Returns a Phoenix.LiveView.JS command.

Toggles the switch checked state from server-side. Pushes a LiveView event.

Components

switch(assigns)

Renders a switch component.

Attributes

  • id (:string) - The id of the switch, useful for API to identify the switch.
  • checked (:boolean) - The initial checked state or the controlled checked state. Defaults to false.
  • controlled (:boolean) - Whether the switch is controlled. Defaults to false.
  • name (:string) - The name of the switch input for form submission.
  • form (:string) - The form id to associate the switch with.
  • aria_label (:string) - The accessible label for the switch. Defaults to "Label".
  • disabled (:boolean) - Whether the switch is disabled. Defaults to false.
  • value (:string) - The value of the switch when checked. Defaults to "true".
  • dir (:string) - The direction of the switch. When nil, derived from document (html lang + config :rtl_locales). Defaults to nil. Must be one of nil, "ltr", or "rtl".
  • read_only (:boolean) - Whether the switch is read-only. Defaults to false.
  • invalid (:boolean) - Whether the switch has validation errors. Defaults to false.
  • required (:boolean) - Whether the switch is required. Defaults to false.
  • on_checked_change (:string) - The server event name when the checked state changes. Defaults to nil.
  • on_checked_change_client (:string) - The client event name when the checked state changes. Defaults to nil.
  • errors (:list) - List of error messages to display. Defaults to [].
  • field (Phoenix.HTML.FormField) - A form field struct retrieved from the form, for example: @form[:email]. Automatically sets id, name, checked state, and errors from the form field.
  • Global attributes are accepted.

Slots

  • label - Accepts attributes:
    • class (:string)
  • error - Accepts attributes:
    • class (:string)

API

set_checked(switch_id, checked)

Sets the switch checked state from client-side. Returns a Phoenix.LiveView.JS command.

Examples

<button phx-click={Corex.Switch.set_checked("my-switch", true)}>
  Turn On
</button>

<button phx-click={Corex.Switch.set_checked("my-switch", false)}>
  Turn Off
</button>

set_checked(socket, switch_id, checked)

Sets the switch checked state from server-side. Pushes a LiveView event.

Examples

def handle_event("turn_on", _params, socket) do
  socket = Corex.Switch.set_checked(socket, "my-switch", true)
  {:noreply, socket}
end

toggle_checked(switch_id)

Toggles the switch checked state from client-side. Returns a Phoenix.LiveView.JS command.

Examples

<button phx-click={Corex.Switch.toggle_checked("my-switch")}>
  Toggle
</button>

toggle_checked(socket, switch_id)

Toggles the switch checked state from server-side. Pushes a LiveView event.

Examples

def handle_event("toggle", _params, socket) do
  socket = Corex.Switch.toggle_checked(socket, "my-switch")
  {:noreply, socket}
end