Hi guys, I’m working with liveview and I was validating with an if inside my template if an specific assign value was nil then I render a 404 error template I created. Yesterday I got some feedback saying that there was a better way to do this since phoenix had a way to handle this.
https://hexdocs.pm/phoenix/controllers.html
I leaned on this docs, and I just remove the validation logic from the liveview module and I create a plug to validate that so if it find that attribute nil it uses send_resp to send the conn with the error code so I don’t need to manually redirect to a error page.
Now the problem I’m facing is that is a pure plane template just with text displaying the message I send in the response, and I need to customize that response to be styled and with some html tags.
I was wondering if anyone could suggest me what is the correct way to deal with this.
this was the first way I tried with the conditional in the template, before refactoring it with the plug :
<%= unless @current_group do %>
<%= live_component @socket, UIWeb.Error404Component, id: :error_404, message: "The Page you are looking doesn't exist, please verify if there is a group for the given subdomain" %>
<% else %>
<section class="container">
<div class="row min-vh-100 justify-content-center">
<div class="col-12 col-sm-7 align-self-center">
<div class="row justify-content-center no-gutters">
<div class="col-6 py-5 col-sm-4 align-self-center">
<img src="<%= @group_avatar_url %>" class="group-avatar" />
</div>
<div class="col-12 col-sm-8 align-self-center pl-sm-2">
<%= unless @listener_token do %>
<a class="btn btn-danger" href="/auth/signout" role="button"><%= gettext("Sign out") %></a>
<% else %>
<h1 class="xl text-center">
<%= @current_group.name %>
</h1>
<p class="text-justify" style="white-space: pre-line"><%= @current_group.description %></p>
<%= if @login_with_password do %>
<div class="mt-4">
<%= live_component @socket, UIWeb.UserSignInPasswordComponent, id: :form_sign_in_password %>
</div>
<% end %>
<%= if @login_with_google do %>
<div class="text-center mt-4">
<a class="btn btn-group-login btn-primary" href="/auth/google?state=<%= @current_group.domain_url %>" role="button">
<%= gettext("Login with Google") %>
</a>
</div>
<% end %>
<% end %>
And this is what I have right now:
PLUG:
defmodule UIWeb.Plugs.Listeners.SubdomainGroupExist do
@moduledoc """
This plug helps doing all the logic and validations
required to authenticate a listener by SSO mode.
"""
@behaviour Plug
import Plug.Conn
alias Core.Groups
@spec init(default :: map()) :: map()
def init(default), do: default
@spec call(conn :: Plug.Conn.t(), default :: map()) :: Plug.Conn.t()
def call(
%{host: host} = conn,
_default
) do
{:ok, group} = Groups.get_group_by_domain_url(host)
validate_group(group, conn)
end
defp validate_group(nil, conn) do
conn
|> put_resp_content_type("text/html")
|> send_resp(404, "The group you are searching for doesn't exist")
end
defp validate_group(group, conn), do: Map.put(conn, :params, %{group: group})
end
CONTROLLER:
defmodule UIWeb.ListenerController do
@moduledoc """
this module is use as a controller to group common functionality
and achieve the manage the main view for listeners
"""
use UIWeb, :controller
import Phoenix.LiveView.Controller
plug UIWeb.Plugs.Listeners.SubdomainGroupExist when action in [:index]
@spec index(conn :: Plug.Conn.t(), params :: map()) :: Plug.Conn.t()
def index(conn, %{group: group}) do
live_render(conn, UIWeb.Listeners.ListenersLive, session: %{"group" => group})
end
end
AND HERE IS THE LIVE MOUNT, THAT GETS HERE WHEN NO ERROR ADDED TO THE CONN IN THE PLUG:
@spec render(map()) :: Rendered.t()
def render(assigns), do: Phoenix.View.render(UIWeb.PageView, "listener.html", assigns)
@spec mount(params :: map(), session :: map(), socket :: Socket.t()) :: {atom(), Socket.t()}
def mount(
_params,
%{"group" => %{avatar_url: avatar_url, name: name} = group} = session,
socket
) do
token = define_status(session)
full_avatar_url = CDN.get_cdn_url(avatar_url, :image)
new_socket = group_validations(group, session["host"], socket)
{:ok,
assign(new_socket,
listener_token: token,
current_group: group,
group_avatar_url: full_avatar_url,
page_title: "#{name} - Podcasts"
)}
end
and this is how I’m getting the erro using the send_resp function:
I hope someone can help me!
Thank in advice!