feat: add col_click attribute to table component for checkbox column

- Add col_click slot attribute to table component that overrides row_click
- Clicking anywhere in the checkbox column now toggles the checkbox
- Clicking other columns still navigates to member details

Closes #223
This commit is contained in:
Moritz 2025-12-03 14:24:10 +01:00
parent 09c75212b2
commit 8e4f1ba674
6 changed files with 71 additions and 60 deletions

View file

@ -357,6 +357,7 @@ defmodule MvWeb.CoreComponents do
slot :col, required: true do
attr :label, :string
attr :col_click, :any, doc: "optional column-specific click handler that overrides row_click"
end
slot :action, doc: "the slot for showing user actions in the last table column"
@ -391,8 +392,11 @@ defmodule MvWeb.CoreComponents do
<tr :for={row <- @rows} id={@row_id && @row_id.(row)}>
<td
:for={col <- @col}
phx-click={@row_click && @row_click.(row)}
class={@row_click && "hover:cursor-pointer"}
phx-click={
(col[:col_click] && col[:col_click].(@row_item.(row))) ||
(@row_click && @row_click.(row))
}
class={(col[:col_click] || @row_click) && "hover:cursor-pointer"}
>
{render_slot(col, @row_item.(row))}
</td>

View file

@ -892,6 +892,16 @@ defmodule MvWeb.MemberLive.Index do
|> Enum.map(&format_member_email/1)
end
@doc """
Returns a JS command to toggle member selection when clicking the checkbox column.
Used as `col_click` handler to ensure clicking anywhere in the checkbox column
toggles the checkbox instead of navigating to the member details.
"""
def checkbox_column_click(member) do
JS.push("select_member", value: %{id: member.id})
end
# Formats a member's email in the format "First Last <email>"
# Used for copy_emails feature and mailto links to create email-client-friendly format.
def format_member_email(member) do

View file

@ -58,6 +58,7 @@
<!-- <:col :let={member} label="Id">{member.id}</:col> -->
<:col
:let={member}
col_click={&MvWeb.MemberLive.Index.checkbox_column_click/1}
label={
~H"""
<.input
@ -74,11 +75,7 @@
<.input
type="checkbox"
name={member.id}
phx-click="select_member"
phx-value-id={member.id}
checked={MapSet.member?(@selected_members, member.id)}
phx-capture-click
phx-stop-propagation
aria-label={gettext("Select member")}
role="checkbox"
/>

View file

@ -10,12 +10,12 @@ msgid ""
msgstr ""
"Language: en\n"
#: lib/mv_web/components/core_components.ex:386
#: lib/mv_web/components/core_components.ex:387
#, elixir-autogen, elixir-format
msgid "Actions"
msgstr "Aktionen"
#: lib/mv_web/live/member_live/index.html.heex:248
#: lib/mv_web/live/member_live/index.html.heex:245
#: lib/mv_web/live/user_live/index.html.heex:72
#, elixir-autogen, elixir-format
msgid "Are you sure?"
@ -28,19 +28,19 @@ msgid "Attempting to reconnect"
msgstr "Verbindung wird wiederhergestellt"
#: lib/mv_web/live/member_live/form.ex:53
#: lib/mv_web/live/member_live/index.html.heex:184
#: lib/mv_web/live/member_live/index.html.heex:181
#: lib/mv_web/live/member_live/show.ex:58
#, elixir-autogen, elixir-format
msgid "City"
msgstr "Stadt"
#: lib/mv_web/live/member_live/index.html.heex:250
#: lib/mv_web/live/member_live/index.html.heex:247
#: lib/mv_web/live/user_live/index.html.heex:74
#, elixir-autogen, elixir-format
msgid "Delete"
msgstr "Löschen"
#: lib/mv_web/live/member_live/index.html.heex:242
#: lib/mv_web/live/member_live/index.html.heex:239
#: lib/mv_web/live/user_live/form.ex:265
#: lib/mv_web/live/user_live/index.html.heex:66
#, elixir-autogen, elixir-format
@ -54,7 +54,7 @@ msgid "Edit Member"
msgstr "Mitglied bearbeiten"
#: lib/mv_web/live/member_live/form.ex:47
#: lib/mv_web/live/member_live/index.html.heex:112
#: lib/mv_web/live/member_live/index.html.heex:109
#: lib/mv_web/live/member_live/show.ex:50
#: lib/mv_web/live/user_live/form.ex:46
#: lib/mv_web/live/user_live/index.html.heex:44
@ -70,7 +70,7 @@ msgid "First Name"
msgstr "Vorname"
#: lib/mv_web/live/member_live/form.ex:50
#: lib/mv_web/live/member_live/index.html.heex:220
#: lib/mv_web/live/member_live/index.html.heex:217
#: lib/mv_web/live/member_live/show.ex:55
#, elixir-autogen, elixir-format
msgid "Join Date"
@ -87,7 +87,7 @@ msgstr "Nachname"
msgid "New Member"
msgstr "Neues Mitglied"
#: lib/mv_web/live/member_live/index.html.heex:239
#: lib/mv_web/live/member_live/index.html.heex:236
#: lib/mv_web/live/user_live/index.html.heex:63
#, elixir-autogen, elixir-format
msgid "Show"
@ -115,7 +115,7 @@ msgid "Exit Date"
msgstr "Austrittsdatum"
#: lib/mv_web/live/member_live/form.ex:55
#: lib/mv_web/live/member_live/index.html.heex:148
#: lib/mv_web/live/member_live/index.html.heex:145
#: lib/mv_web/live/member_live/show.ex:60
#, elixir-autogen, elixir-format
msgid "House Number"
@ -130,21 +130,21 @@ msgstr "Notizen"
#: lib/mv_web/live/components/payment_filter_component.ex:94
#: lib/mv_web/live/components/payment_filter_component.ex:144
#: lib/mv_web/live/member_live/form.ex:48
#: lib/mv_web/live/member_live/index.html.heex:229
#: lib/mv_web/live/member_live/index.html.heex:226
#: lib/mv_web/live/member_live/show.ex:51
#, elixir-autogen, elixir-format
msgid "Paid"
msgstr "Bezahlt"
#: lib/mv_web/live/member_live/form.ex:49
#: lib/mv_web/live/member_live/index.html.heex:202
#: lib/mv_web/live/member_live/index.html.heex:199
#: lib/mv_web/live/member_live/show.ex:54
#, elixir-autogen, elixir-format
msgid "Phone Number"
msgstr "Telefonnummer"
#: lib/mv_web/live/member_live/form.ex:56
#: lib/mv_web/live/member_live/index.html.heex:166
#: lib/mv_web/live/member_live/index.html.heex:163
#: lib/mv_web/live/member_live/show.ex:61
#, elixir-autogen, elixir-format
msgid "Postal Code"
@ -165,7 +165,7 @@ msgid "Saving..."
msgstr "Speichern..."
#: lib/mv_web/live/member_live/form.ex:54
#: lib/mv_web/live/member_live/index.html.heex:130
#: lib/mv_web/live/member_live/index.html.heex:127
#: lib/mv_web/live/member_live/show.ex:59
#, elixir-autogen, elixir-format
msgid "Street"
@ -176,7 +176,7 @@ msgstr "Straße"
msgid "Id"
msgstr "ID"
#: lib/mv_web/live/member_live/index.html.heex:234
#: lib/mv_web/live/member_live/index.html.heex:231
#: lib/mv_web/live/member_live/index/formatter.ex:61
#: lib/mv_web/live/member_live/show.ex:52
#, elixir-autogen, elixir-format
@ -193,7 +193,7 @@ msgstr "Mitglied anzeigen"
msgid "This is a member record from your database."
msgstr "Dies ist ein Mitglied aus deiner Datenbank."
#: lib/mv_web/live/member_live/index.html.heex:234
#: lib/mv_web/live/member_live/index.html.heex:231
#: lib/mv_web/live/member_live/index/formatter.ex:60
#: lib/mv_web/live/member_live/show.ex:52
#, elixir-autogen, elixir-format
@ -359,12 +359,12 @@ msgstr "Profil"
msgid "Required"
msgstr "Erforderlich"
#: lib/mv_web/live/member_live/index.html.heex:68
#: lib/mv_web/live/member_live/index.html.heex:69
#, elixir-autogen, elixir-format
msgid "Select all members"
msgstr "Alle Mitglieder auswählen"
#: lib/mv_web/live/member_live/index.html.heex:82
#: lib/mv_web/live/member_live/index.html.heex:79
#, elixir-autogen, elixir-format
msgid "Select member"
msgstr "Mitglied auswählen"
@ -566,7 +566,7 @@ msgstr "Benutzer*innen"
msgid "Click to sort"
msgstr "Klicke um zu sortieren"
#: lib/mv_web/live/member_live/index.html.heex:94
#: lib/mv_web/live/member_live/index.html.heex:91
#, elixir-autogen, elixir-format
msgid "First name"
msgstr "Vorname"

View file

@ -11,12 +11,12 @@
msgid ""
msgstr ""
#: lib/mv_web/components/core_components.ex:386
#: lib/mv_web/components/core_components.ex:387
#, elixir-autogen, elixir-format
msgid "Actions"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:248
#: lib/mv_web/live/member_live/index.html.heex:245
#: lib/mv_web/live/user_live/index.html.heex:72
#, elixir-autogen, elixir-format
msgid "Are you sure?"
@ -29,19 +29,19 @@ msgid "Attempting to reconnect"
msgstr ""
#: lib/mv_web/live/member_live/form.ex:53
#: lib/mv_web/live/member_live/index.html.heex:184
#: lib/mv_web/live/member_live/index.html.heex:181
#: lib/mv_web/live/member_live/show.ex:58
#, elixir-autogen, elixir-format
msgid "City"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:250
#: lib/mv_web/live/member_live/index.html.heex:247
#: lib/mv_web/live/user_live/index.html.heex:74
#, elixir-autogen, elixir-format
msgid "Delete"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:242
#: lib/mv_web/live/member_live/index.html.heex:239
#: lib/mv_web/live/user_live/form.ex:265
#: lib/mv_web/live/user_live/index.html.heex:66
#, elixir-autogen, elixir-format
@ -55,7 +55,7 @@ msgid "Edit Member"
msgstr ""
#: lib/mv_web/live/member_live/form.ex:47
#: lib/mv_web/live/member_live/index.html.heex:112
#: lib/mv_web/live/member_live/index.html.heex:109
#: lib/mv_web/live/member_live/show.ex:50
#: lib/mv_web/live/user_live/form.ex:46
#: lib/mv_web/live/user_live/index.html.heex:44
@ -71,7 +71,7 @@ msgid "First Name"
msgstr ""
#: lib/mv_web/live/member_live/form.ex:50
#: lib/mv_web/live/member_live/index.html.heex:220
#: lib/mv_web/live/member_live/index.html.heex:217
#: lib/mv_web/live/member_live/show.ex:55
#, elixir-autogen, elixir-format
msgid "Join Date"
@ -88,7 +88,7 @@ msgstr ""
msgid "New Member"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:239
#: lib/mv_web/live/member_live/index.html.heex:236
#: lib/mv_web/live/user_live/index.html.heex:63
#, elixir-autogen, elixir-format
msgid "Show"
@ -116,7 +116,7 @@ msgid "Exit Date"
msgstr ""
#: lib/mv_web/live/member_live/form.ex:55
#: lib/mv_web/live/member_live/index.html.heex:148
#: lib/mv_web/live/member_live/index.html.heex:145
#: lib/mv_web/live/member_live/show.ex:60
#, elixir-autogen, elixir-format
msgid "House Number"
@ -131,21 +131,21 @@ msgstr ""
#: lib/mv_web/live/components/payment_filter_component.ex:94
#: lib/mv_web/live/components/payment_filter_component.ex:144
#: lib/mv_web/live/member_live/form.ex:48
#: lib/mv_web/live/member_live/index.html.heex:229
#: lib/mv_web/live/member_live/index.html.heex:226
#: lib/mv_web/live/member_live/show.ex:51
#, elixir-autogen, elixir-format
msgid "Paid"
msgstr ""
#: lib/mv_web/live/member_live/form.ex:49
#: lib/mv_web/live/member_live/index.html.heex:202
#: lib/mv_web/live/member_live/index.html.heex:199
#: lib/mv_web/live/member_live/show.ex:54
#, elixir-autogen, elixir-format
msgid "Phone Number"
msgstr ""
#: lib/mv_web/live/member_live/form.ex:56
#: lib/mv_web/live/member_live/index.html.heex:166
#: lib/mv_web/live/member_live/index.html.heex:163
#: lib/mv_web/live/member_live/show.ex:61
#, elixir-autogen, elixir-format
msgid "Postal Code"
@ -166,7 +166,7 @@ msgid "Saving..."
msgstr ""
#: lib/mv_web/live/member_live/form.ex:54
#: lib/mv_web/live/member_live/index.html.heex:130
#: lib/mv_web/live/member_live/index.html.heex:127
#: lib/mv_web/live/member_live/show.ex:59
#, elixir-autogen, elixir-format
msgid "Street"
@ -177,7 +177,7 @@ msgstr ""
msgid "Id"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:234
#: lib/mv_web/live/member_live/index.html.heex:231
#: lib/mv_web/live/member_live/index/formatter.ex:61
#: lib/mv_web/live/member_live/show.ex:52
#, elixir-autogen, elixir-format
@ -194,7 +194,7 @@ msgstr ""
msgid "This is a member record from your database."
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:234
#: lib/mv_web/live/member_live/index.html.heex:231
#: lib/mv_web/live/member_live/index/formatter.ex:60
#: lib/mv_web/live/member_live/show.ex:52
#, elixir-autogen, elixir-format
@ -360,12 +360,12 @@ msgstr ""
msgid "Required"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:68
#: lib/mv_web/live/member_live/index.html.heex:69
#, elixir-autogen, elixir-format
msgid "Select all members"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:82
#: lib/mv_web/live/member_live/index.html.heex:79
#, elixir-autogen, elixir-format
msgid "Select member"
msgstr ""
@ -567,7 +567,7 @@ msgstr ""
msgid "Click to sort"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:94
#: lib/mv_web/live/member_live/index.html.heex:91
#, elixir-autogen, elixir-format
msgid "First name"
msgstr ""

View file

@ -11,12 +11,12 @@ msgstr ""
"Language: en\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: lib/mv_web/components/core_components.ex:386
#: lib/mv_web/components/core_components.ex:387
#, elixir-autogen, elixir-format
msgid "Actions"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:248
#: lib/mv_web/live/member_live/index.html.heex:245
#: lib/mv_web/live/user_live/index.html.heex:72
#, elixir-autogen, elixir-format
msgid "Are you sure?"
@ -29,19 +29,19 @@ msgid "Attempting to reconnect"
msgstr ""
#: lib/mv_web/live/member_live/form.ex:53
#: lib/mv_web/live/member_live/index.html.heex:184
#: lib/mv_web/live/member_live/index.html.heex:181
#: lib/mv_web/live/member_live/show.ex:58
#, elixir-autogen, elixir-format
msgid "City"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:250
#: lib/mv_web/live/member_live/index.html.heex:247
#: lib/mv_web/live/user_live/index.html.heex:74
#, elixir-autogen, elixir-format
msgid "Delete"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:242
#: lib/mv_web/live/member_live/index.html.heex:239
#: lib/mv_web/live/user_live/form.ex:265
#: lib/mv_web/live/user_live/index.html.heex:66
#, elixir-autogen, elixir-format
@ -55,7 +55,7 @@ msgid "Edit Member"
msgstr ""
#: lib/mv_web/live/member_live/form.ex:47
#: lib/mv_web/live/member_live/index.html.heex:112
#: lib/mv_web/live/member_live/index.html.heex:109
#: lib/mv_web/live/member_live/show.ex:50
#: lib/mv_web/live/user_live/form.ex:46
#: lib/mv_web/live/user_live/index.html.heex:44
@ -71,7 +71,7 @@ msgid "First Name"
msgstr ""
#: lib/mv_web/live/member_live/form.ex:50
#: lib/mv_web/live/member_live/index.html.heex:220
#: lib/mv_web/live/member_live/index.html.heex:217
#: lib/mv_web/live/member_live/show.ex:55
#, elixir-autogen, elixir-format
msgid "Join Date"
@ -88,7 +88,7 @@ msgstr ""
msgid "New Member"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:239
#: lib/mv_web/live/member_live/index.html.heex:236
#: lib/mv_web/live/user_live/index.html.heex:63
#, elixir-autogen, elixir-format
msgid "Show"
@ -116,7 +116,7 @@ msgid "Exit Date"
msgstr ""
#: lib/mv_web/live/member_live/form.ex:55
#: lib/mv_web/live/member_live/index.html.heex:148
#: lib/mv_web/live/member_live/index.html.heex:145
#: lib/mv_web/live/member_live/show.ex:60
#, elixir-autogen, elixir-format
msgid "House Number"
@ -131,21 +131,21 @@ msgstr ""
#: lib/mv_web/live/components/payment_filter_component.ex:94
#: lib/mv_web/live/components/payment_filter_component.ex:144
#: lib/mv_web/live/member_live/form.ex:48
#: lib/mv_web/live/member_live/index.html.heex:229
#: lib/mv_web/live/member_live/index.html.heex:226
#: lib/mv_web/live/member_live/show.ex:51
#, elixir-autogen, elixir-format
msgid "Paid"
msgstr ""
#: lib/mv_web/live/member_live/form.ex:49
#: lib/mv_web/live/member_live/index.html.heex:202
#: lib/mv_web/live/member_live/index.html.heex:199
#: lib/mv_web/live/member_live/show.ex:54
#, elixir-autogen, elixir-format
msgid "Phone Number"
msgstr ""
#: lib/mv_web/live/member_live/form.ex:56
#: lib/mv_web/live/member_live/index.html.heex:166
#: lib/mv_web/live/member_live/index.html.heex:163
#: lib/mv_web/live/member_live/show.ex:61
#, elixir-autogen, elixir-format
msgid "Postal Code"
@ -166,7 +166,7 @@ msgid "Saving..."
msgstr ""
#: lib/mv_web/live/member_live/form.ex:54
#: lib/mv_web/live/member_live/index.html.heex:130
#: lib/mv_web/live/member_live/index.html.heex:127
#: lib/mv_web/live/member_live/show.ex:59
#, elixir-autogen, elixir-format
msgid "Street"
@ -177,7 +177,7 @@ msgstr ""
msgid "Id"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:234
#: lib/mv_web/live/member_live/index.html.heex:231
#: lib/mv_web/live/member_live/index/formatter.ex:61
#: lib/mv_web/live/member_live/show.ex:52
#, elixir-autogen, elixir-format
@ -194,7 +194,7 @@ msgstr ""
msgid "This is a member record from your database."
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:234
#: lib/mv_web/live/member_live/index.html.heex:231
#: lib/mv_web/live/member_live/index/formatter.ex:60
#: lib/mv_web/live/member_live/show.ex:52
#, elixir-autogen, elixir-format
@ -360,12 +360,12 @@ msgstr ""
msgid "Required"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:68
#: lib/mv_web/live/member_live/index.html.heex:69
#, elixir-autogen, elixir-format
msgid "Select all members"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:82
#: lib/mv_web/live/member_live/index.html.heex:79
#, elixir-autogen, elixir-format
msgid "Select member"
msgstr ""
@ -567,7 +567,7 @@ msgstr ""
msgid "Click to sort"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex:94
#: lib/mv_web/live/member_live/index.html.heex:91
#, elixir-autogen, elixir-format, fuzzy
msgid "First name"
msgstr ""