Trigger show action on clicking table row

Hello all, just started learning Elixir & Phoenix. Had a quick question about the table view that is generated by Phoenix to show lists of things. In this view, every row has a “Show”, “Edit” and “Delete” button. What is the best way to replace the “Show” button functionality with a click on the table row?

In other words, “Show” is currently a link <%= link "Show", to: Routes.contact_path(@conn, :show, contact) %> . I want to do the same action when user clicks on the row instead.

You can wrap other elements in the a tag by using a do block.

<%= link to: Routes.contact_path(@conn, :show, contact), class: "h-full w-full ..." do %> 

... inner content ...

<% end %>

Thanks @cmo, but that would mean wrapping a <tr> in an <a> tag. That seems very unusual markup, I would like to avoid that.

You haven’t shown the code you’re looking at so I don’t know what your markup looks like.

I’m suggesting you put a link inside a <td>.

Hi @cmo, here’s my markup. If I add a link in a , then only the link will trigger the navigation. I would like to trigger the navigation on click anywhere in the row:

<%= for contact <- @contacts do %>
    <tr
      id={Integer.to_string(contact.id)}
      onclick="showContact"
    >
      <td><%= contact.firstName %></td>
      <td><%= contact.lastName %></td>
    </tr>
<% end %>

This is now almost working, except that onclick is not triggering my showContact function. I think I have to use addEventListener.

If you put the a inside all the tds and have the a fill the entire space it will give you that behaviour. Otherwise you can do it on the tr with javascript. I imagine you’ll want to pass the contact’s id or something to the showContact though.

<%= for contact <- @contacts do %>
    <tr id={"contact-#{contact.id}"}>
      <td><%= link contact.first_name, to: Routes.contact_path(@conn, :show, contact) class: "css to make it full height & width... display: block?" %></td>
      <td><%= link contact.last_name, to: Routes.contact_path(@conn, :show, contact) class: "css to make it full height & width... display: block?" tabindex: "-1" %></td>
    </tr>
<% end %>

Yep, that’s the approach I took. Got it to work by adding the script right inside my .heex file instead of app.js. Also onclick never worked. Had to use addEventListener - which makes it more lines of code, but it works!

<script>
var tbody = document.getElementById("contacts-body");
var rows = tbody.getElementsByTagName("tr");
for (i = 0; i < rows.length; i++) {
  const row = rows[i];
  row.addEventListener('click', showContact);
}

function showContact(e) {
  let id = e.currentTarget.id;
  if (id) {
    window.location.href = '/contacts/' + id;
  }
}
</script>