PhoenixImageTools.Components (phoenix_image_tools v0.3.0)
View SourceProvides Phoenix LiveView components for displaying responsive images.
Usage
<.picture
versions={[:xs, :sm, :md, :lg, :xl]}
base={:original}
url_fun={&MyApp.Uploaders.ProfileImageUploader.url({@user.profile_image, @user}, &1)}
alt="User profile image"
lazy_loading={true}
rounded={true}
class="object-cover"
/>
Summary
Functions
Processes a single uploaded file and prepares it for insertion into database records.
Processes uploaded files and prepares them for insertion into database records.
Renders a file upload field component for handling image uploads with preview.
Determines if a file is an image based on its extension.
Attributes
title
(:string
) - Defaults tonil
.
Slots
inner_block
(required)
Renders a responsive picture element with proper srcset attributes.
Functions
@spec consume_upload(Phoenix.LiveView.Socket.t(), map(), atom(), keyword()) :: map()
Processes a single uploaded file and prepares it for insertion into database records.
Similar to consume_uploads/4
but designed for single file uploads. It expects only
one file to be uploaded at a time.
Parameters
socket
- The LiveView socket with uploadsparams
- The params map (usually from the form submission)field_key
- The atom key of the upload fieldoptions
- A keyword list of options:generate_name
- When true, generates a unique UUID for the filename (default: false):merge_fun
- A function that merges the uploaded file path into params (default: simple Map.put)
Returns
The updated params map with the uploaded file merged in.
Examples
# In a LiveView handle_event function
def handle_event("save", %{"user" => user_params}, socket) do
user_params =
PhoenixImageTools.Components.consume_upload(
socket,
user_params,
:avatar,
generate_name: true
)
case Accounts.update_user(socket.assigns.user, user_params) do
{:ok, user} ->
{:noreply, socket |> put_flash(:info, "Profile updated") |> assign(:user, user)}
{:error, changeset} ->
{:noreply, assign_form(socket, changeset)}
end
end
With custom merge function:
# Custom merge that handles nested params
merge_fun = fn params, key, uploaded_file ->
put_in(params, ["profile", "{key}"], uploaded_file)
end
PhoenixImageTools.Components.consume_upload(
socket,
user_params,
:avatar,
generate_name: true,
merge_fun: merge_fun
)
@spec consume_uploads(Phoenix.LiveView.Socket.t(), map(), atom(), keyword()) :: map()
Processes uploaded files and prepares them for insertion into database records.
This function helps consume LiveView uploads and merge the results into the
params map, making it ready for changesets. It's designed to work with the
form_upload_field
component and handles both single and multiple file uploads.
Parameters
socket
- The LiveView socket with uploadsparams
- The params map (usually from the form submission)field_key
- The atom key of the upload fieldoptions
- A keyword list of options:generate_names
- When true, generates unique UUIDs for filenames (default: false)
Returns
The updated params map with the uploaded files merged in.
Examples
# In a LiveView handle_event function
def handle_event("save", %{"product" => product_params}, socket) do
product_params =
PhoenixImageTools.Components.consume_uploads(
socket,
product_params,
:images,
generate_names: true
)
case Products.create_product(product_params) do
{:ok, product} ->
{:noreply, socket |> put_flash(:info, "Product created") |> push_navigate(to: ~p"/products")}
{:error, changeset} ->
{:noreply, assign_form(socket, changeset)}
end
end
The files will be available in your changeset as a list of maps in the format:
%{
"0" => %{"delete" => "false", "file" => "/path/to/file.jpg"},
"1" => %{"delete" => "false", "file" => "/path/to/another_file.png"}
}
This format is compatible with cast_attachments/4
from PhoenixImageTools.Schema
.
Renders a file upload field component for handling image uploads with preview.
This component simplifies the creation of LiveView file upload experiences, supporting both new uploads and displaying previously uploaded images.
Examples
<.form_upload_field
upload={@uploads}
name={:images}
label="Product Images"
/>
With previous uploads and custom cancel action:
<.form_upload_field
upload={@uploads}
name={:profile_image}
label="Profile Picture"
target={@myself}
accept={~w(.jpg .jpeg .png)}
max_entries={1}
>
<:previous_uploads>
<.inputs_for :let={image_form} field={@form[:images]}>
<.hidden_input form={image_form} field={:delete} />
<.hidden_input form={image_form} field={:id} />
<div id={"image-{image_form.index}"} class={image_form[:delete].value == "true" && "hidden"}>
<figure class="mb-2">
<img
src={MyApp.MediaUploader.url(Ecto.Changeset.get_field(image_form.source, :file), :thumbnail)}
class="rounded-lg max-w-[200px]"
alt="Uploaded image"
/>
</figure>
<div>
<button
type="button"
phx-click="mark-image-for-deletion"
phx-value-index={image_form.index}
class="text-red-600 text-sm"
>
Remove
</button>
</div>
</div>
</.inputs_for>
</:previous_uploads>
</.form_upload_field>
In the LiveView module, you'll need to set up uploads:
def mount(_params, _session, socket) do
socket =
socket
|> assign_form(...)
|> allow_upload(:images,
accept: ~w(.jpg .jpeg .png .webp),
max_entries: 5,
max_file_size: 10_000_000
)
{:ok, socket}
end
def handle_event("save", %{"entity" => entity_params}, socket) do
entity_params =
PhoenixImageTools.Components.consume_uploads(
socket,
entity_params,
:images,
generate_names: true
)
# Continue with saving logic
end
def handle_event("cancel-upload", %{"ref" => ref}, socket) do
{:noreply, cancel_upload(socket, :images, ref)}
end
Attributes
upload
- The LiveView uploads map.name
- The upload field name (must match the field name in allow_upload).label
- Optional label text for the upload field (defaults to capitalized name).target
- Optional target for phx events (useful in LiveComponents).class
- Optional CSS classes to apply to the container.drop_prompt
- Optional custom prompt for drag and drop area.accept
- Optional list of allowed file extensions (for information only).max_entries
- Optional maximum number of files (for information only).max_file_size_mb
- Optional max file size in MB (for information only).
Slots
previous_uploads
- Slot for rendering previously uploaded files.upload_entry
- Slot for customizing the display of upload entries.
Usage with consume_uploads
The companion function consume_uploads/4
helps process uploaded files and prepare
them for insertion into database records. See its documentation for details.
Attributes
upload
(:map
) (required) - The LiveView uploads map.name
(:atom
) (required) - The upload field name (must match the field name in allow_upload).label
(:string
) - Optional label text for the upload field. Defaults tonil
.target
(:any
) - Optional target for phx events (useful in LiveComponents). Defaults tonil
.class
(:string
) - Optional CSS classes to apply to the container. Defaults to""
.drop_prompt
(:string
) - Custom prompt for drag and drop area. Defaults to"Drag and drop files or click to browse"
.accept
(:list
) - Optional list of allowed file extensions (for information only). Defaults tonil
.max_entries
(:integer
) - Optional maximum number of files (for information only). Defaults tonil
.max_file_size_mb
(:integer
) - Optional max file size in MB (for information only). Defaults tonil
.
Slots
previous_uploads
- Slot for rendering previously uploaded files.upload_entry
- Slot for customizing the display of upload entries. Accepts attributes:entry
(:map
)
Determines if a file is an image based on its extension.
Checks if a given filename has a supported image extension.
Parameters
file_name
- The filename or path to check
Returns
Boolean indicating if the file has a supported image extension
Examples
iex> PhoenixImageTools.Components.is_image?("photo.jpg")
true
iex> PhoenixImageTools.Components.is_image?("document.pdf")
false
Attributes
title
(:string
) - Defaults tonil
.
Slots
inner_block
(required)
Renders a responsive picture element with proper srcset attributes.
Attributes
class
- CSS classes to apply to the picture element.url_fun
- Function to generate URLs for different image versions.versions
- List of image versions to include in the srcset.base
- Base version to use as the default image src.zoom_version
- Version to use for the zoomable view (defaults to base if not provided).lazy_loading
- Whether to enable lazy loading for the image.rounded
- Whether to apply rounded corners to the image.zoomable
- Whether the image should be zoomable.alt
- Alternative text for the image.height
- Height attribute for the image (defaults to 500).width
- Width attribute for the image (defaults to 500).
Attributes
class
(:any
) - CSS classes to apply to the picture element. Defaults tonil
.url_fun
(:any
) - Function to generate URLs for different image versions.versions
(:list
) - List of image versions to include in the srcset.base
(:atom
) - Base version to use as the default image src.zoom_version
(:atom
) - Version to use for the zoomable view (defaults to base if not provided). Defaults tonil
.lazy_loading
(:boolean
) - Whether to enable lazy loading for the image. Defaults tofalse
.rounded
(:boolean
) - Whether to apply rounded corners to the image. Defaults tofalse
.zoomable
(:boolean
) - Whether the image should be zoomable. Defaults tofalse
.alt
(:string
) - Alternative text for the image. Defaults to""
.height
(:integer
) - Height attribute for the image. Defaults to500
.width
(:integer
) - Width attribute for the image. Defaults to500
.- Global attributes are accepted.