hubertlepicki / spike-liveview

LiveView bindings for Spike

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Readme

Spike.LiveView provides a wrapper around Phoenix.LiveView and Phoenix.LiveComponent, which simplifies working with memory-backed forms, including nested forms that require contextual validation.

Installation

Available in Hex, the package can be installed by adding spike_liveview to your list of dependencies in mix.exs:

def deps do
  [
    {:spike_liveview, "~> 0.2"}
  ]
end

Documentation can be found at https://hexdocs.pm/spike_liveview.

Quick start

Once installed in a Phoenix project, open up your *_web.ex file and add the following functions:

  def form_live_view do
    quote do
      use Phoenix.LiveView,
        layout: {MyAppWeb.LayoutView, "live.html"}

      unquote(view_helpers())

      use Spike.LiveView
    end
  end

  def form_live_component do
    quote do
      use Phoenix.LiveComponent

      unquote(view_helpers())

      use Spike.LiveView
    end
  end

This allows you to build LiveViews and LiveComponents that ship with form and form erors handling capabilities out of the box.

You will need a Spike form. For usage how to build these, refer to Spike docs.

For example, your simplest possible registration form may look like this:

defmodule MyApp.RegistrationForm do
  use Spike.Form do
    field(:username, :string)
    field(:password, :string)

    validates(:username, presence: true, by: &__MODULE__.validate_not_taken/2)
    validates(:password, presence: true)
  end

  def validate_not_taken(value, _context) do
    if MyApp.Repo.get_by(MyApp.User, username: value) do
      {:error, "username already taken"}
    else
      :ok
    end
  end
end

And a LiveView to handle registration process would be:

defmodule MyAppWeb.RegistrationLive do
  use MyAppWeb, :form_live_view
  import Spike.LiveView.Components

  def mount(_params, _, socket) do
    form = MyApp.RegistrationForm.new(%{})

    {:ok,
     socket
     |> assign(%{form: form, errors: Spike.errors(form)})}
  end

  def render(assigns) do
    ~H"""
    <h1>Register</h1>

    <div>
      <label for="username">Username:</label>

      <.form_field field={:username} form={@form}>
        <input id="username" name="value" type="text" value={@form.username} />
      </.form_field>

      <.errors let={field_errors} field={:username} form={@form} errors={@errors}>
        <span class="error">
          <%= field_errors |> Enum.map(fn {_k, v} -> v end) |> Enum.join(", ") %>
        </span>
      </.errors>
    </div>

    <div>
      <label for="password">Password:</label>

      <.form_field field={:password} form={@form}>
        <input id="password" name="value" type="text" value={@form.password} />
      </.form_field>

      <.errors let={field_errors} field={:password} form={@form} errors={@errors}>
        <span class="error">
          <%= field_errors |> Enum.map(fn {_k, v} -> v end) |> Enum.join(", ") %>
        </span>
      </.errors>
    </div>

    <a href="#" phx-click="register">Register!</a>
    """
  end

  def handle_event("register", _, socket) do
    if socket.assigns.errors == %{} do
      # perform registration logic here
      IO.puts("Registering user with #{socket.assigns.form.username} and #{socket.assigns.form.password}....")
      {:noreply, socket}   
    else
      {:noreply, socket |> assign(:form, Spike.make_dirty(socket.assigns.form))}
    end
  end
end

Remember to mount it at router and visit http://localhost:4000/register:

  scope "/", MyAppWeb do
    pipe_through :browser

    live "/register", RegistrationLive
  end

Usage of form components provided by this library is, however, pretty low-level, and we recommend you build your own form components instead.

For starting point to build your own form components, see our Components Library.

With the above components, we can shorten our render/1 function:

  def render(assigns) do
    ~H"""
    <h1>Register</h1>

    <Input type="text" form={@form} field={:username} errors={@errors} />
    <Input type="passwod" form={@form} field={:} errors={@errors} />
 
    <a href="#" phx-click="submit">Register!</a>
    """
  end

And that's pretty sweet!

See Components Library, Spike Example app for more examples.

About

LiveView bindings for Spike

License:Other


Languages

Language:Elixir 100.0%