No idea why the live title is not updating to the correct value, have you?

I’m trying to use this code to update the title on a page. I can’t use the suffix in .live_title, because the presentation is awkward when there is no page_title in assigns. It would display as " - App Name".

I tried to fix this using a bit of code, and am not sure what’s happening. If there is a page title in assigns, it shows only the page title and not the suffix. This is in the root layout:

<% app_name = "App Name" %>
  <%= if title = assigns[:page_title], do: "#{title} - #{app_name}", else: app_name %>

I’ve tried even removing the live_title and just using the title tag, but it’s still very strange behavior. Where exactly does the peculiarity live?

So live_title is a special case. The root template isn’t rendered within the context of LiveView and doesn’t react to normal assigns. This is why you reference assigns[:page_title] and not @page_title. So live_title is the sort of exception. Once the socket connects, its inner block is fully replaced with whatever is in socket.assigns[:live_title], that is if there is anything in it. If you look quickly, you can see that you actually get what you’re expecting on the dead render and then it’s quickly replaced when the socket connects. If you liveSocket.enableLatencySim(5000) in the JS console and refresh, this will be much clearer. So basically, if you don’t want to use suffix you have to put everything you want in the title in the :live_title assign. You could make a helper to manage this.

Off the top of my head, I would still use suffix but like this:

# Put this somewhere that you can include in your MyAppWeb.live_view:
def assign_page_title(socket, title) do
  assign(socket, :page_title, title <> " | ")

and then just do:

<.live_title suffix="App Name">
  <%= assigns[:page_title] %>

Personally, I do this (and don’t use a helper):

<.live_title suffix=" | App Name">
  <%= assigns[:page_title] || "Home" %>

Of course I have to be sure to assign live_title on every page but the home page.

1 Like

Thanks for the explanation, that solution works for me. I get what you’re saying about the default behavior, but I think that it is prone to errors and potential misunderstanding. IMO the default behavior is wonky and should probably be changed. Will think about whether opening an issue makes sense.

It’s described right off the bat in the Live Layouts section of the docs. It’s not clear what it is you would want changed, but keeping <head> out of live updates was a very intentional decision that won’t get changed. There’s usually no need to manipulate the <head> other than the title <title>. For cases like updating the favicon there is Phx.Live.Head. Perhaps that’s not what you’re suggesting and if not I apologize.

I do, however, think it would be nice if the live_layout component took a delimiter attribute:

<.live_layout suffix="My App" delimiter="|">
  <%= assigns[:live_title] %>

Especially if the :live_title assign could then optionally be a list:

|> assign(:live_title, ["Products", "Dog Food"])

which would update the title as: “Products | Dog Food | My App”.

You can always copy live_title code and add the functionality locally in your project.

I’ve done this once before with live_component, as the business logic required some things to be present there and I didn’t want to pollute the entire codebase with implementation details, pretty easy to understand and results in clean and readable code, at least as long as you are writing documentation :smile: .

1 Like