Creating dynamic checkboxes and radiobuttons in Phoenix

Creating dynamic checkboxes and radiobuttons in Phoenix

In most projects on the web there will be some occurences of the <input type="radio"> or <input type="checkbox"> control for forms.

While developing forms that require a dynamic set of radio buttons or checkboxes I’ve found that it’s not very well documented on how to get them to work together with labels in phoenix.

There are multiple ways to accomplish it so i’ll show you my two preferred ways.

Making use of input_id/3

Phoenix.HTML has a nifty little function used internally by the builder methods of radio buttons or check boxes to create the id attributes. However as of speaking it hasn’t been implemented into the builder for labels because there has been no idea on how to do this without working with temporary options. See This pull request for more info.

*Notice that the last value passed to input_id must be an atom or a string.

<% medals = [:gold, :silver, :bronze] %>
<% default_medal = :bronze %>

<%= form_for @changeset, options_path(@conn, :create), fn (f) -> %>
    <%= label f, :options, "Choose your options" %>
    
    <%= for option <- options do %>
        <%= label f, :medal, for: input_id(f, :medal, medal) %>
        <%= radio_button f, :medal, value, checked: medal == default_medal %>   
    <% end %>
<% end %>

Wrapping the radio button in a label

Something many people seem to miss is that labels doesn’t have the need to have a for attribute. By putting the target input inside the label it’ll automatically get focused upon clicking the label. Since e3f14d8 Phoenix.HTML supports label/1 which simply takes a block making it possible to it like this:

<% medals = [:gold, :silver, :bronze] %>
<% default_medal = :bronze %>

<%= form_for @changeset, options_path(@conn, :create), fn (f) -> %>
    <%= label f, :options, "Choose your options" %>
    
    <%= for option <- options do %>
        <%= label do %>
            <%= radio_button f, :medal, checked: medal == default_medal %>
        <% end %>
    <% end %>
<% end %>   

I hope this can help!