October 16, 2016 | HTML5, CSS, web, development
The problem
In the current project, I made a custom checkbox. The custom implementation used native control and didn't rely on any JavaScript, but for some reason, it didn't work on Edge.
It is a common technique to give style for the native HTML checkbox by having a label that contains input (for functionality) and span (for styling). Let's see simplified implementation.
See the Pen Custom checkbox example by Tatu Tamminen (@ttamminen) on CodePen.
The HTML specification says that all "successful controls" are part of submission. What it means is that, for example, a checkbox that is unchecked will not be part of the form post. Form not sending checkbox state causes issues to MVC frameworks as it cannot determine between unchecked and non-existing control.
There is an easy solution, add a hidden field with unselected value, for example, 0 or False. The name of the field should be same as checkbox name.
<label class="custom-checkbox">
<input type="hidden" name="alarm" value="False" />
<input class="custom-checkbox-input" name="alarm" type="checkbox" value="True">
<span class="custom-checkbox-text">Alarm</span>
</label>
Here is a working example:
See the Pen Custom checkbox example with hidden field by Tatu Tamminen (@ttamminen) on CodePen.
Wait! Try with Edge, and you'll notice that checkbox state doesn't change.
The reason is that on Edge label is connected to the first input. Even if it is a hidden field.
To verify that this is the case, I added click event handler to the hidden field, and on Edge it did trigger.
Think about it, hidden field getting the click event!
The solution
There are two options: 1) move checkbox to be the first input element or 2) add for-attribute to the label.
Solution number one would look like this:
<label class="custom-checkbox">
<input class="custom-checkbox-input" name="alarm" type="checkbox" value="True">
<input type="hidden" name="alarm" value="False" />
<span class="custom-checkbox-text">Alarm</span>
</label>
Solution number two:
<label for="alarm-state" class="custom-checkbox">
<input type="hidden" name="alarm" value="False" />
<input id="alarm-state" class="custom-checkbox-input" name="alarm" type="checkbox" value="True">
<span class="custom-checkbox-text">Alarm</span>
</label>
I hope this will help you avoid same mistakes I made.