BartOtten

BartOtten

Feature Request: LiveView Dynamic Favicon

Proposal

  • Support DOM patching of the HTML link element for a favicon.
  • Add the special @page_favicon assign mimicking the @page_title assign so each page can have it’s own dynamic favicon; supporting multiple tabs for an application with different ‘statuses’.

Reason
Many modern web applications have dynamic favicons. These dynamic favicons are used to notify browser users of events or statuses. For example: unread messages or a CI build status. As those use cases are quite common, providing such functionality seems to fit the ‘no Javascript’-philosophy. Additionaly it seems to align with the automagic @page_title.

Because the root layout from the Plug pipeline is rendered outside of LiveView, the contents cannot be dynamically changed. The one exception is the <title> of the HTML document. Phoenix LiveView special cases the @page_title assign to allow dynamically updating the title of the page, which is useful when using live navigation, or annotating the browser tab with a notification. For example, to update the user’s notification count in the browser’s title bar, first set the page_title assign on mount
Live layouts — Phoenix LiveView v1.2.5

Current State

  • The HTML link element for favicons is placed in layout/root_live.html.heex. No native logic is in place to update it in the DOM and there is no @page_favicon.
  • The HTML title element is placed in `layout/root_live.html.heex. Native logic is in place to update the element in the DOM when the @page_title assignment is changed.

Todo

  • get approval for feature
  • research possibilities
  • draft design
  • get approval for design
  • implement

I am willing to work on this as contribution to the community.

Links
[LiveView Dynamic Favicon?]
[https://medium.com/@alperen.talaslioglu/building-dynamic-favicon-with-javascript-223ad7999661]

Most Liked

AndyL

AndyL

Here’s some rough design ideas:

Let there be a special assign @favicon_href

The live_favicon_tag would go into layout/root_live.html.heex

<%= live_favicon_tag assigns[:favicon_href] || "/images/favicon.ico" %>

The live_favicon_tag function would emit the following HTML

<link id="phx-favicon" rel="icon" type="image/x-icon" href="/images/favicon.ico"/>

Add an event listener to the client javascript

window.addEventListener("phx:change-favicon", (e) => {
  var href = e.detail.href 
  var fabtag = document.getElementById('phx-favicon') 
  fabtag.href = href
})

On the server, when the LiveView process detects that @favicon_href has changed, push an event to the client:

push_event(socket, "change-favicon", %{href: @favicon_href})}

With this approach, add-on packages (like live_dashboard) could add their own favicon images to priv/images, and then use their own favicons in their particular LiveViews.

10
Post #3
BartOtten

BartOtten

It’s gonna be 3 I guess.

Took some time to explore the problem domain a little further. As a result, I will create multiple libs all targeted at manipulating the static head.

Phoenix Live Head
Low level lib which includes functions to manipulate the head of the page incl. generic Javascript. It also takes care of minimizing data over the wire. The other libs depend on it, direct usage will be discouraged.

Phoenix Live Favicon
Lib which supports dynamic favicons! It will include a helper function to cover some exotic use cases, but will mainly be used with the HTML link element(s).

Phoenix Live Metadata
This one is a convenience lib which can be used pre-production (on production it is harmful!). It updates the metadata in the head for easy inspection.

Phoenix Live -other head element-

—-

This way devs can pick the parts they need for each environment.

BartOtten

BartOtten

Just to keep everyone informed

To be super clear
I fully understand and respect Chris’ rejection. He just doesn’t want anyone spilling time so he was quick to respond.

The rejection
The rejection was based on the commit and example code published.

The PR did not yet include support for multi favicon links nor some other features, as it was not final code yet. I used a ‘draft PR’ which GitHub says “is meant for discussion, not review” just to make sure the ‘we are working on this idea already’ would be represented at GitHub too and discussion about code could take place there.

So Chris was right the published code at that time could be done with 10 lines of primitives and -based on that- changing Phoenix codebase should not happen.

Future
Currently I see 4 options.

  1. Write a blog post how it’s done with primitives
  2. Write a helper lib/files requiring manual changes in Javascript files.
  3. Write a lib which solely relies on Phoenix so it’s a ‘add to mix dep’ and go.
  4. Challenge the rejection with the improved ‘include in Phoenix Liveview’ code and description why Chris’ solution won’t work (enough)

When option 3 is viable, it’s probably gonna be 3.

While the code for 4 is ready for a challenge, the challenge won’t happen until the pro’s and cons of all the options are clear and comparable.

So far
So far I have the code for 2 and 4 (they share most lines). Will make an attempt at 3 this weekend, should be quite straight forward.

One way or another we will have dynamic multi-link favicons in our Phoenix Live View apps; so just subscribe to this topic, wait and relax :slight_smile:

Where Next?

Popular in Questions Top

New
nobody
How to bind a phoenix app to a specific ip address? could not find anything about that, nowhere, unfortunately, but for me this is quite...
New
Lily
In templates/appointment/index.html.eex: &lt;%= for appointment &lt;- @appointments do %&gt; &lt;tr&gt; &lt;td&gt;&lt;%= appoi...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; somethi...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call t...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New

Other popular topics Top

malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 126479 1222
New

We're in Beta

About us Mission Statement