Corex. Editable
(Corex v0.1.1)
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>.
| Function | Action | Returns |
|---|---|---|
set_value/2 | Set preview value (client) | %Phoenix.LiveView.JS{} |
set_value/3 | Set preview value (server) | socket |
Events
Pick an event name and pass it to on_* on <.editable>.
Server events
| Event | When | Payload |
|---|---|---|
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)}
endClient events
| Event | When | event.detail |
|---|---|---|
on_value_change_client="editable-changed" | Value changes | id, 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
Components
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 tofalse.read_only(:boolean) - Whether the editable is read-only. Defaults tofalse.required(:boolean) - Whether the input is required. Defaults tofalse.invalid(:boolean) - Whether the editable is in invalid state. Defaults tofalse.name(:string) - The name attribute for form submission. Defaults tonil.form(:string) - The id of the form this input belongs to. Defaults tonil.dir(:string) - Text direction. Defaults tonil. Must be one ofnil,"ltr", or"rtl".orientation(:string) - Defaults to"vertical". Must be one of"horizontal", or"vertical".default_edit(:boolean) - Initial edit state. Defaults tofalse.placeholder(:string) - Placeholder text when value is empty. Defaults tonil.activation_mode(:string) - How to activate edit mode. Defaults tonil. Must be one ofnil,"dblclick", or"focus".select_on_focus(:boolean) - Whether to select all text on focus. Defaults totrue.on_value_change(:string) - Server event name when value changes. Defaults tonil.on_value_change_client(:string) - Client event name when value changes. Defaults tonil.translation(Corex.Editable.Translation) - Override translatable strings. Defaults tonil.field(Phoenix.HTML.FormField) - A form field struct, e.g. f[:text] or @form[:text]. Defaults tonil.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 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 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