Shared LiveView module for extensions.
Use this instead of MishkaCmsWeb, :live_view in extension LiveViews.
Automatically embeds templates from the same directory.
Features
- Phoenix.LiveView
- Phoenix.HTML
- Phoenix.Component
- Phoenix.LiveView.JS
- Gettext (translations)
- CoreComponents (UI components: button, input, table, modal, etc.)
- Runtime path helpers (path/2, url/2)
- embed_templates (auto-loads .html.heex files from same directory)
Usage
# index.ex
defmodule MishkaBlogWeb.Live.Admin.Dashboard.Blogger.Index do
use MishkaCmsCore.ExtensionLiveView
@impl true
def mount(_params, _session, socket) do
{:ok, assign(socket, count: 10)}
end
end
# index.html.heex (same directory)
<div class="container mx-auto px-4 py-8">
<.header>
Bloggers {@count}
<:subtitle>Manage all bloggers</:subtitle>
<:actions>
<.button navigate={path(@socket, "/admin/dashboard/blog/bloggers/new")}>
New Blogger
</.button>
</:actions>
</.header>
<.table id="bloggers" rows={@bloggers}>
<:col :let={blogger} label="Name">{blogger.name}</:col>
<:col :let={blogger} label="Email">{blogger.email}</:col>
</.table>
</div>Available Components
From MishkaCmsCore.CoreComponents:
<.button>- Buttons with navigation support<.input>- Form inputs with labels and error handling<.table>- Tables with streams support<.flash>- Flash messages<.header>- Page headers with actions<.icon>- Heroicons<.list>- Data lists
Path Helpers
Since extensions compile before the main CMS, they cannot use ~p sigils.
Instead, use the runtime path helpers:
# In templates - use path/2 with @socket:
<.link navigate={path(@socket, "/admin/dashboard")}>Dashboard</.link>
# With dynamic segments:
<.link navigate={path(@socket, "/posts/#{@post.id}")}>View</.link>
# For full URLs:
url(@socket, "/posts/#{@post.id}")Translations
Use gettext/1 for translations:
<h1>{gettext("Welcome")}</h1>
<p>{ngettext("1 item", "%{count} items", @count)}</p>