2

I've got a frontend user profile form that is successfully setting the values of custom fields in the backend except for some lightswitch fields I've added to my user profiles.

I have the following code which displays a checkbox on the frontend profile form and sets checked="checked" if that switch is "on" in the backend:

<div class="checkbox">
  <label>
    <input type="checkbox" id="memberShowEmailLink" name="fields[memberShowEmailLink]" value="1" {% if currentUser.memberShowEmailLink %}checked="checked"{% endif %}>
    Show a link to contact me via email in the member directory?
  </label>
</div>

If the lightswitch is set to "off" and I check the box on the frontend form and submit the form, the change is saved and the lightswitch flips to "on" in the backend.

However, if the lightswitch is already "on" and thus the box is already checked, if I uncheck it on the frontend form and submit the form, the change is not saved and there's no change in the backend.

What am I missing?

4

While both lightswitches and checkboxes represent an on/off state, they are quite different. Standard browser behavior is designed to only post checkbox data if the checkbox is checked, otherwise it is ignored. In PHP, when processing the form, you would want to check whether the post-data is present or not; if it's present then the value is checked; otherwise it's unchecked.

Although I haven't reviewed how craft processes checkbox form submissions I would assume that it also performs this check behind the scenes, and converts the value to a 1 or 0 to store the data. However, being a lightswitch, craft probably does not perform this check, so if the field is missing from the post-data (which it would be if unchecked), then craft simply ignores it, as not being part of the form to begin with.

There may be a simpler method built in that I'm not aware of, but one solution would be to create a hidden field with your lightswitch handle, and then set that field using javascript when the user checks or unchecks the checkbox, much the way that craft does.

Here is the standard lightswitch html for example so you can see how craft sets this up:

<div class="lightswitch" tabindex="0">
    <div class="lightswitch-container" style="margin-left: -11px;">
        <div class="label on"></div>
        <div class="handle"></div>
        <div class="label off"></div>
    </div>
    <input type="hidden" name="fields[switchHandle]" value="">
</div>

You would want something like this:

<div class="checkbox">
    <label>
        <input type="checkbox" class="js-checkbox" {% if currentUser.memberShowEmailLink %}checked="checked"{% endif %}>
        Show a link to contact me via email in the member directory?
    </label>
    <input type="hidden" class="js-lightbox" name="fields[memberShowEmailLink]" value="{% if currentUser.memberShowEmailLink %}1{% endif %}">
</div>

Then in javascript:

$('.js-checkbox').on('change', function(event) {
    if($(this).prop('checked')) {
        $('.js-lightbox').val(1);
    } else {
        $('.js-lightbox').val(0);
    }
});

Note: if you leave off the 'name' attribute the dummy checkbox should not get submitted.

1
  • This is fantastic Douglas. Thanks for all the well explained detail. I implemented and all is working. The only change I made was to add an "id" to each hidden input and a "data-target" attribute to each dummy checkbox, making an explicit link between the two. I was then hooking into those values in the js using $( $(this).attr('data-target') ).val(1) instead of $('.js-lightbox').val(1) (which was checking and unchecking all three boxes in unison). – Adam Snetman Jan 9 '15 at 15:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.