Logo

dev-resources.site

for different kinds of informations.

SaladUI - Implement avatar component for Phoenix LiveView

Published at
5/27/2024
Categories
elixir
phoenix
liveview
Author
bluzky
Categories
3 categories in total
elixir
open
phoenix
open
liveview
open
Author
6 person written this
bluzky
open
SaladUI - Implement avatar component for Phoenix LiveView

This post is written after I implement Avatar component for SaladUI component library for Phoenix Liveview.

An avatar component is quite simple, but I want to enhance it with fallback avatar text. The template structure is as following:



<.avatar>
  <.avatar_image src="./my-profile-img.jpg"></.avatar_image>
  <.avatar_fallback class="bg-primary text-white">CN</.avatar_fallback>
<.avatar>


Enter fullscreen mode Exit fullscreen mode

Here is an implementation of avatar component in html



<span class="relative rounded-full overflow-hidden w-10 h-10">
    <img class="aspect-square w-full h-full" src="https://github.com/shadcn.png">
    <span class="flex rounded-full bg-primary text-white items-center justify-center w-full h-full">CN</span>
</span>


Enter fullscreen mode Exit fullscreen mode

Image description

It's the happy case, the image exist, and the fallback element is push down and hidden due to class overflow-hidden.

But when the image doesn't exist, the broken image is displayed.

Image description

Hmm, the image should be hidden if it does not exist or got error while loading. Fortunately, img provide onerror event.



<span class="relative rounded-full overflow-hidden w-10 h-10">
    <img class="aspect-square w-full h-full" src="badimage.png" onerror="this.style.display='none'">
    <span class="flex rounded-full bg-primary text-white items-center justify-center w-full h-full">CN</span>
</span>


Enter fullscreen mode Exit fullscreen mode

Guest what. Nothing changed, the broken image is still visible.
It took me a while to discover the reason. onerror="this.style.display='none'" change attribute on client side, when Phoenix LiveView update, it patch the html and remove the display style value. So just add phx-update="ignore" and you got the error image hidden.



<span class="relative rounded-full overflow-hidden w-10 h-10">
    <img class="aspect-square w-full h-full" src="https://github.com/shadcn.png" onerror="this.style.display='none'" phx-update="ignore">
    <span class="flex rounded-full bg-primary text-white items-center justify-center w-full h-full">CN</span>
</span>


Enter fullscreen mode Exit fullscreen mode

And it works as expected

Image description

Now wrap up the component



defmodule SaladUI.Avatar do
  @moduledoc false
  use Phoenix.Component

  attr(:class, :string, default: nil)
  attr(:rest, :global)

  def avatar(assigns) do
    ~H"""
    <span class={classes(["relative h-10 w-10 overflow-hidden rounded-full", @class])} {@rest}>
      <%= render_slot(@inner_block) %>
    </span>
    """
  end

  attr(:class, :string, default: nil)
  attr(:rest, :global)

  def avatar_image(assigns) do
    ~H"""
    <img
      class={classes(["aspect-square h-full w-full", @class])}
      {@rest}
      phx-update="ignore"
      style="display:none"
      onload="this.style.display=''"
    />
    """
  end

  attr(:class, :string, default: nil)
  attr(:rest, :global)
  slot(:inner_block, required: false)

  def avatar_fallback(assigns) do
    ~H"""
    <span
      class={
        classes(["flex h-full w-full items-center justify-center rounded-full bg-muted", @class])
      }
      {@rest}
    >
      <%= render_slot(@inner_block) %>
    </span>
    """
  end
end


Enter fullscreen mode Exit fullscreen mode

You may notice that I use onload event instead of onerror:



style="display:none"
onload="this.style.display=''"


Enter fullscreen mode Exit fullscreen mode

Using onerror browser waits until the image loading complete to decide if there is any error then trigger the event. This cause the white avatar while loading image. Using onload event to show image when the loading process complete, so by default if the image loading is slow, the fallback avatar still displays.

If you want to learn more, then visit my github repo https://github.com/bluzky/salad_ui.

Thanks for reading.

liveview Article's
30 articles in total
Favicon
Phoenix LiveView, hooks and push_event: json_view
Favicon
Phoenix LiveView is slot empty?
Favicon
Bridging the Gap: Simplifying Live Component Invocation in Phoenix LiveView
Favicon
Optimize LiveView Performance with Temporary Assigns
Favicon
Phoenix LiveView Optimization Guide
Favicon
Better LiveView Hooks with Typescript
Favicon
Automatically clearing flash messages in Phoenix LiveView
Favicon
Debug and visualise TailwindCSS document structure
Favicon
Build a small chat service using Elixir and deploy it on Amazon ec2 using AWS (Part 1)
Favicon
Build a small chat service using Elixir and deploy it on Amazon ec2 using AWS (Part 2)
Favicon
Weather API: A GenServer and LiveView Implementation Part I
Favicon
Build a small chat service using Elixir and deploy it on Amazon ec2 using AWS (Last part)
Favicon
Backpex - a highly customizable admin panel for Phoenix LiveView applications
Favicon
AI powered app (with open-source LLMs like Llama) with Elixir, Phoenix, LiveView, and TogetherAI
Favicon
Using Ecto (without Db) for validating Phoenix form
Favicon
Adding stream_async() to Phoenix LiveView
Favicon
SaladUI - Implement avatar component for Phoenix LiveView
Favicon
Connectivity status with Phoenix LiveView
Favicon
Phoenix Liveview components for Shadcn UI
Favicon
Ash - Create with relationship
Favicon
My Failed Student Housing App
Favicon
Beter data-confirm modals in Phoenix LiveView
Favicon
Free Beginner Friendly LiveView Course in English and Portuguese
Favicon
LiveView + WebComponents = 🚀
Favicon
Ash AshSqlite - Aggregates not supported
Favicon
Phoenix Liveview - open editor for element
Favicon
Ash Calculations - Cond
Favicon
How does Ecto.Schema's `has_one/3` works?
Favicon
Creating a Date Range Picker with Phoenix LiveView
Favicon
Listing matches for users

Featured ones: