root

root

Setting dynamic layouts in LiveViews that correspond with the hostname

Hello everyone.

I have an app that’s going to be setting the layout dynamically according to the current domain name. I’m trying to figure out a way to do it in LiveView.

I’ve gotten to the point where I have an on_mount helper that gets the current hostname and makes it available in assigns, but I’m not able to use that from within the LiveView mount calls, because the helper depends on hooking handle_params. The only other place to set the layout (as far as I know) is in the router or in the myapp_web file where the :live_view helpers are defined, and I’m not seeing how to get access to the hostname from either of those locations.

Is there a recommended way to do this that I’ve missed?

Marked As Solved

root

root

Okay…

router.ex

...

  # put host and configuration data into session for retrieval from liveview
  defp sessionify_configuration(conn, _opts) do
    import Plug.Conn

    case MyApp.Sites.Domain.get_by_name(conn.host) do
      {:ok, domain} ->
        configuration =
          domain.site_id
          |> MyApp.Sites.Site.get_by_id!()
          |> MyApp.Sites.load!(:configuration)
          |> Map.get(:configuration)

        conn
        |> put_session(:configuration, configuration)
        |> put_session(:current_host, conn.host)
        |> put_session(:current_path, conn.request_path)

      {:error, error} ->
        IO.inspect(error)
        raise "No Domain found with the name " <> conn.host
        conn
    end
  end

  pipeline :do_config do
    plug :sessionify_configuration
  end

  scope "/", MyAppWeb do
    pipe_through [:browser, :do_config]

    # login not required
    ash_authentication_live_session :authenticated_optional,
      on_mount: [
        {MyAppWeb.LiveUserAuth, :live_user_optional},
        {MyAppWeb.AssignConfiguration, :assign_configuration}
      ] do

      live "/", PublicLive.Index, :index
    end

...

assign_configuration.ex

def on_mount(:assign_configuration, _params, session, socket) do
  socket =
    socket
    |> Phoenix.Component.assign(:configuration, Map.get(session, "configuration"))
    |> Phoenix.Component.assign(:current_host, Map.get(session, "current_host"))
    |> Phoenix.Component.assign(:current_path, Map.get(session, "current_path"))

  {:cont, socket}
end

index.ex

  def mount(_params, _session, socket) do
    socket =
      socket
      |> assign(:page_title, "public")
      |> assign(:testificate, "testificatey")

    layout = {MyAppWeb.Layouts, socket.assigns.configuration.theme}

    {:ok, socket, layout: layout}
  end

This is the flow I have right now that’s working! I was able to remove extraneous hooks and consolidate some functionality into the on_mount. And it looks like Phoenix actually is letting me pass the layout template as a string, too, although it does complain that this is deprecated. So no String.to_atom for now (and if I do have to do that later I think I can just whitelist it based on existing themes).

So the only thing I have to append to every liveview is

layout = {MyAppWeb.Layouts, socket.assigns.configuration.theme}
{:ok, socket, layout: layout}

Not too bad.

And to be clear I meant like they could potentially manipulate the session based on the hostname. If you are whitelisting hostnames then it’s no problem.

This area is all public stuff you can view by simply going to that site, so that should be fine as I understand it. Unless there’s anything drastic I’m missing.

Also Liked

olivermt

olivermt

Can you not set up a plug that puts the host in the session?

sodapopcan

sodapopcan

Wellllllll ****. Could you add it to the session from a plug so it’s available in mount? Maybe not ideal. I don’t think I can be much help here as I’ve never actually done this myself. I’m interested, though, so hopefully someone else can help!

(and yes, I also read that same thread and how I set the current URL too :slight_smile: )

EDIT: Ha, re: post that beat me to the punch

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

The session is signed by default, so it is not editable by the user. You can also encrypt it to make it impossible for the user to view.

Where Next?

Popular in Questions Top

_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
vac
Hi, I’m quite new in Elixir and I’m trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and I...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New

Other popular topics Top

New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31307 143
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

We're in Beta

About us Mission Statement