|

How to build a toggle switch menu with jQuery

In the Saber Commerce settings page we have a number of toggle on/off settings. These could be displayed as checkboxes, but we decided we wanted toggle switches. This may be mainly a UX design choice, but it also has a practical application as well. Which good UX design choices often do, especially when it comes to features that we want users to find intuitive and comfortable. So checkboxes serve the function of choosing to turn something on or off, but toggle switches tend to make it more clear what the options are. Visually their also larger, making them more prominent.

There are a lot of toggle switch code examples out there many of them use CSS. Many of them are enhancements for checkboxes so they use CSS to show the labels for a checkbox as clickable options and then add some toggle effects. The code for many of these seems quite bulky. So our solution is more jQuery/JS oriented. We’re already building the SACOM UX entirely from JS anyway, and we’re parsing our settings forms with jQuery, so there is no reason to shy away from using JS in our project. In fact we prefer it, we’d rather keep the CSS light so that it’s easier to make style changes.

Our goal with a toggle switch is to store the setting. We use a hidden text element to store the value of the selection. So here is what the definition of a single toggle switch looks like:

h += SettingsEditor.toggleFieldHtml({
  id: 'invoices_show_in_menu',
  choices: [
    {
      label: 'YES',
      value: 1
    },
    {
      label: 'NO',
      value: 0
     },
  ]
});

In the example above “h” is the variable we’re storing the HTML in before it’s rendered into the DOM (using jQuery append). SettingsEditor.toggleFieldHtml() is the function that builds the HTML for our toggle. We are passing it an ID for the setting first, then an array of options. In this example we pass 2 options, but this toggler will work with 3 or more options as well.

You might be surprised at how lightweight the code is for the toggleFieldHtml() function. It simply loops over the choices passed to, and builds up a very simple markup structure that includes the hidden text field with the ID for the setting:

toggleFieldHtml: function( options ) {

		var h = '';
		h += '<div class="sacom-settings-toggle">';

		// Loop over choices.
		jQuery.each( options.choices, function( index, choice ) {

			h += '<div data-value="' + choice.value + '" class="toggle-option">';
			h += choice.label;
			h += '</div>';

		});

		// Value storage hidden input.
		h += '<input type="hidden" id="' + options.id + '" />';
		h += '</div>';
		return h;

	},

The markup it returns looks like this:

<div class="sacom-settings-toggle">
  <div data-value="1" class="toggle-option">YES</div>
  <div data-value="0" class="toggle-option">NO</div>
  <input type="hidden" id="stripe_enabled">
</div>

It’s quite minimal, and it’s simple to style. You can certainly adapt the markup if you needed more elements to create a different style. You might wonder why we didn’t use an unordered list (<ul> and <li> tags) here. There isn’t really any reason, but divs work fine… and perhaps on some level styling the divs is a bit simpler (don’t have to worry about overriding any default list styles).

Notice the use of a data element (data-value) which holds the value for each option. The processing of selection is going to take that value and stash it into the hidden input on a click event. The click event is shown below, note that it’s wrapped inside a function because this entire solution sits in a class (SettingsEditor).

toggleFieldEvents: function() {

    jQuery( document ).on( 'click', '.sacom-settings-toggle > div.toggle-option', function() {

        let toggleOptionEl = jQuery( this );
        let toggleEl = toggleOptionEl.parents( '.sacom-settings-toggle' );
        let currentValue = toggleOptionEl.attr( 'data-value' );
        toggleEl.find( '.selected' ).removeClass( 'selected' );
        toggleOptionEl.addClass( 'selected' );
        toggleEl.find('input').val( currentValue );

    });

},

The click event is attached globally by using document as the selector, this is because in our application the DOM is often being refreshed without a page refresh. So much like in React, the DOM is updated, except here we use jQuery. We start off here by parsing the current option element, and then we get the parent which is the entire toggle. We only need to achieve 2 goals in the click handler, the first is to update the selection by removing the “selected” class from the existing option and applying it to the current option selected. Next we need to take the value from the attribute data-value and stash this into the hidden input.

We do need some CSS for our toggles, but it’s very minimal just 4 declarations in our styling:

.sacom-settings-toggle {
	display: flex;
}

.sacom-settings-toggle > div {
	cursor: pointer;
	padding: 15px 25px;
	background: #AEAEAE;
	color: #FFF;
	min-width: 120px;
	text-align: center;
}

.sacom-settings-toggle > div:hover {
	background: #DDD;
}

.sacom-settings-toggle > div.selected {
	background: #2271B1;
}

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *