Debugging Complex Data in LiveView

A Mac desktop and MacBook with indeterminate code on the screens
Mike Binns

Engineer

Mike Binns

You need a solid, scalable foundation for your digital product. That’s Elixir. Book a free consult today to learn how we can put Elixir to work for you.

LiveView Quick Debugging Tip

Being a productive Software Engineer means having plenty of tools in your toolbelt to help you quickly navigate the day-to-day needs of the job, and knowing how to combine them in ways that are useful. Here’s one combination I find myself using pretty regularly on my LiveView projects to get a look at what is actually going on with assigns or other data that doesn’t seem to be matching what I expect it to, especially when logging it to the console via IO.inspect isn’t a great option (e.g. when rendering many components in a list), and when the data I need to see is more complex or multi-layered, such as the LiveView assigns map.

TL;DR:

<pre><%= inspect(@my_map, pretty: true) %></pre>

Breaking it Down

There are two tools here, the pretty: true flag on the inspect function, and the HTML <pre> tag.

pretty: true

By default, the inspect function returns the string version of the term in a single line. For example, the Repo config returned is all one line:

iex(7)> Application.get_env(:liveview_inspect_pre, LiveviewInspectPre.Repo) |> inspect()
"[username: \"postgres\", password: \"postgres\", hostname: \"localhost\", database: \"liveview_inspect_pre_dev\", stacktrace: true, show_sensitive_data_on_connection_error: true, pool_size: 10]"

If we add the pretty: true option, we get newlines and indentation spaces embedded in the string:

iex(8)> Application.get_env(:liveview_inspect_pre, LiveviewInspectPre.Repo) |> inspect(pretty: true)
"[\n  username: \"postgres\",\n  password: \"postgres\",\n  hostname: \"localhost\",\n  database: \"liveview_inspect_pre_dev\",\n  stacktrace: true,\n  show_sensitive_data_on_connection_error: true,\n  pool_size: 10\n]"

When we pass that into IO.puts, we see that the string is formatted nicely, with newlines and two space indents.

iex(9)> Application.get_env(:liveview_inspect_pre, LiveviewInspectPre.Repo) |> inspect(pretty: true) |> IO.puts()
[
  username: "postgres",
  password: "postgres",
  hostname: "localhost",
  database: "liveview_inspect_pre_dev",
  stacktrace: true,
  show_sensitive_data_on_connection_error: true,
  pool_size: 10
]

This formatting can be invaluable when you are dealing with more complex terms, such as the LiveView assigns map.

PRE Tag

By default, HTML ignores whitespace in text: it completely ignores newlines, and it collapses any number of spaces into a single space. If we were to simply <%= inspect(@my_var, pretty: true) %>, the browser would eat up the nice whitespace returned by pretty: true and render it all in one line:

The HTML <pre> tag defines preformatted text, meaning that the browser will honor both the newlines and multiple spaces that exist in the text between the opening and closing tags. By combining this with the pretty: true inspect option (resulting in <pre><%= inspect(@my_map, pretty: true) %></pre>) we get to see the nicely formatted version in the browser:

Wrap Up

While a regular IO.inspect logging to the console is often the simplest way to see what the state of data is for a piece of code, we sometimes find ourselves needing to see the data on the page for one reason or another. Hopefully, this small tool combination can be helpful to you the next time you run into this scenario.

Newsletter

Stay in the Know

Get the latest news and insights on Elixir, Phoenix, machine learning, product strategy, and more—delivered straight to your inbox.

Narwin holding a press release sheet while opening the DockYard brand kit box