Corex.Editable (Corex v0.1.0)

View Source

Phoenix implementation of Zag.js Editable.

Anatomy

Basic

<.editable value="Click to edit" class="editable">
  <:label>Name</:label>
  <:edit_trigger><.heroicon name="hero-pencil-square" class="icon" /></:edit_trigger>
  <:submit_trigger><.heroicon name="hero-check" class="icon" /></:submit_trigger>
  <:cancel_trigger><.heroicon name="hero-x-mark" class="icon" /></:cancel_trigger>
</.editable>

Required slots: :label, :edit_trigger, :submit_trigger, :cancel_trigger. Preview value is managed by the component and the Editable TS hook.

API

Requires a stable id on <.editable>.

FunctionActionReturns
set_value/2Set preview value (client)%Phoenix.LiveView.JS{}
set_value/3Set preview value (server)socket

Events

Pick an event name and pass it to on_* on <.editable>.

Server events

EventWhenPayload
on_value_change="editable_changed"Value committed or cancelled%{"id" => id, "value" => string}

on_value_change

<.editable
  value="Click to edit"
  class="editable"
  on_value_change="editable_changed"
>
  <:label>Name</:label>
  <:edit_trigger><.heroicon name="hero-pencil-square" class="icon" /></:edit_trigger>
  <:submit_trigger><.heroicon name="hero-check" class="icon" /></:submit_trigger>
  <:cancel_trigger><.heroicon name="hero-x-mark" class="icon" /></:cancel_trigger>
</.editable>
def handle_event("editable_changed", %{"id" => _id, "value" => value}, socket) do
  {:noreply, assign(socket, :name, value)}
end

Client events

EventWhenevent.detail
on_value_change_client="editable-changed"Value changesid, value

Form

Use field={f[:name]} inside <.form> for changeset-backed forms.

For cross-cutting invalid styling and error presentation, see the Forms guide. Pass invalid={Corex.FormField.invalid?(@form[:name])} when you want alert borders after validation.

<.form for={@form} phx-change="validate">
  <.editable field={@form[:name]} class="editable">
    <:label>Name</:label>
    <:error :let={msg}>
      <.heroicon name="hero-exclamation-circle" class="icon" />
      {msg}
    </:error>
    <:edit_trigger><.heroicon name="hero-pencil-square" class="icon" /></:edit_trigger>
    <:submit_trigger><.heroicon name="hero-check" class="icon" /></:submit_trigger>
    <:cancel_trigger><.heroicon name="hero-x-mark" class="icon" /></:cancel_trigger>
  </.editable>
</.form>

Style

Use data attributes to target elements:

[data-scope="editable"][data-part="root"] {}
[data-scope="editable"][data-part="area"] {}
[data-scope="editable"][data-part="label"] {}
[data-scope="editable"][data-part="input"] {}
[data-scope="editable"][data-part="preview"] {}
[data-scope="editable"][data-part="edit-trigger"] {}
[data-scope="editable"][data-part="control"] {}
[data-scope="editable"][data-part="submit-trigger"] {}
[data-scope="editable"][data-part="cancel-trigger"] {}
[data-scope="editable"][data-part="error"] {}

If you wish to use the default Corex styling, you can use the class editable 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/editable.css";

You can then use modifiers

<.editable class="editable editable--accent editable--lg" value="">
  <:label>Label</:label>
  <:edit_trigger>Edit</:edit_trigger>
  <:submit_trigger>Save</:submit_trigger>
  <:cancel_trigger>Cancel</:cancel_trigger>
</.editable>

Summary

API

Set the visible text value from a control (phx-click).

Set the value from handle_event.

Components

editable(assigns)

Attributes

  • id (:string) - The id of the editable component.
  • value (:string) - Initial preview text (Zag defaultValue). Defaults to "".
  • disabled (:boolean) - Whether the editable is disabled. Defaults to false.
  • read_only (:boolean) - Whether the editable is read-only. Defaults to false.
  • required (:boolean) - Whether the input is required. Defaults to false.
  • invalid (:boolean) - Whether the editable is in invalid state. Defaults to false.
  • name (:string) - The name attribute for form submission. Defaults to nil.
  • form (:string) - The id of the form this input belongs to. Defaults to nil.
  • dir (:string) - Text direction. Defaults to nil. Must be one of nil, "ltr", or "rtl".
  • orientation (:string) - Defaults to "vertical". Must be one of "horizontal", or "vertical".
  • default_edit (:boolean) - Initial edit state. Defaults to false.
  • placeholder (:string) - Placeholder text when value is empty. Defaults to nil.
  • activation_mode (:string) - How to activate edit mode. Defaults to nil. Must be one of nil, "dblclick", or "focus".
  • select_on_focus (:boolean) - Whether to select all text on focus. Defaults to true.
  • on_value_change (:string) - Server event name when value changes. Defaults to nil.
  • on_value_change_client (:string) - Client event name when value changes. Defaults to nil.
  • translation (Corex.Editable.Translation) - Override translatable strings. Defaults to nil.
  • field (Phoenix.HTML.FormField) - A form field struct, e.g. f[:text] or @form[:text]. Defaults to nil.
  • errors (:list) - List of error messages to display. Defaults to [].
  • Global attributes are accepted.

Slots

  • label (required) - Accepts attributes:
    • class (:string)
  • edit_trigger (required) - Accepts attributes:
    • class (:string)
  • submit_trigger (required) - Accepts attributes:
    • class (:string)
  • cancel_trigger (required) - Accepts attributes:
    • class (:string)
  • error - Accepts attributes:
    • class (:string)

API

set_value(editable_id, value)

Set the visible text value from a control (phx-click).

<.action phx-click={Corex.Editable.set_value("my-editable", "Hello")}>Reset</.action>
<.editable id="my-editable" class="editable" name="title" value="Hi">
  <:label>Title</:label>
  <:edit_trigger>Edit</:edit_trigger>
  <:submit_trigger>Save</:submit_trigger>
  <:cancel_trigger>Cancel</:cancel_trigger>
</.editable>
document.getElementById("my-editable")?.dispatchEvent(
  new CustomEvent("corex:editable:set-value", {
    bubbles: false,
    detail: { value: "Hello" },
  })
);

set_value(socket, editable_id, value)

Set the value from handle_event.

<.action phx-click="reset_title" phx-value-value="Hello">Reset</.action>
<.editable id="my-editable" class="editable" name="title" value="Hi">
  <:label>Title</:label>
  <:edit_trigger>Edit</:edit_trigger>
  <:submit_trigger>Save</:submit_trigger>
  <:cancel_trigger>Cancel</:cancel_trigger>
</.editable>
def handle_event("reset_title", %{"value" => v}, socket) do
  {:noreply, Corex.Editable.set_value(socket, "my-editable", v)}
end