First of all I have an Intercooler.ex file with this:
defmodule Intercooler do
def get_params(%Plug.Conn{params: params}) do
get_params(params)
end
def get_params(%{"ic-request" => "true"} = params) do
params
end
def get_params(_) do
nil
end
def get_param(data, id, default \\ nil) when is_binary(id) do
case get_params(data) do
nil -> nil
params -> Map.get(params, id, default)
end
end
def active?(data), do: get_params(data) !== nil
def get_target_id(data), do: get_param(data, "ic-target-id")
end
Just a simple set of helpers (that I keep intending to grow but have not yet, I should make a public repo…).
And I have an Intercooler/Plug.ex file with:
defmodule Intercooler.Plug do
defmodule Format do
import Plug.Conn
import Phoenix.Controller
def init(options), do: options
def call(conn, options) do
case conn.params["ic-request"] do
"true" ->
conn
|> put_layout_formats(["ic.html" | layout_formats(conn)])
|> put_format("ic.html")
_ ->
conn
end
end
end
end
What that does is change the layout templates to be “.ic.html.eex” instead of “.html.eex”. This made it trivial to make special intercooler-only templates.
Next I have in my router’s browser pipeline I added this plug right after the :accepts
plug:
plug Intercooler.Plug.Format
Next in my web/templates/layout I made an “app.ic.html.eex”, with just this:
<%= render_sublayout @view_module, @view_template, @view_module, "sublayout.ic.html", assigns %>
And that was only because I was too lazy to clear the required layout name on the plug. ^.^
Do note, *you* will probably not be able to use the above file, the framework I’ve built up has a render_sublayout function that does arbitrary recursing through the page module system, your “app.ic.html.eex” will probably just be:
<%= render @view_module, @view_template, assigns %>
Say you have an index.html.eex template, if your intercooler calls back in to the same page (to the index.ic.html.eex template) to get information then you can query what it is asking for by using the above Intercooler
module in your template, one of mine is like:
<%=
case Intercooler.get_target_id(@conn) do
"tab-check_in_out-checked_out" ->
section_ids = @section.values
|> Enum.map(fn out -> out.id end)
|> Enum.sort
|> Enum.uniq
ids = Intercooler.get_param(@conn, "checked_out", %{"id"=>["-1"]})["id"]
|> List.wrap
|> Enum.map(&String.to_integer/1)
|> Enum.sort
|> Enum.uniq
if section_ids !== ids do
render "index_section_tab_out.html", conn: @conn, changeset: @changeset, section: @section
end
_ -> nil # TODO: Need to add support for the polling tab better, check in button is not updating it there. Not needed quite yet though...
end
%>
In that I just check what it is asking for (“tab-check_in_out-checked_out” in this case), so I gather up the information it wants and call back to the real template to render that snippet back out to it (I have more case statements too for different parts).
Alternatively in intercooler you can have it request from different url’s instead of the same url with different ID names, then you just render the template straight out (though that style involves making more controller endpoints that might be duplicates of existing ones, I prefer the view dispatcher method, but either works and I use both in various cases).
Learn intercooler first, it works its magic via tags and such, then build your server around that.