Johnsonium
Johnsonium

Reputation: 2005

How to Attach Events to Table Checkboxes in Material Design Lite

When you create a MDL table, one of the options is to apply the class 'mdl-data-table--selectable'. When MDL renders the table an extra column is inserted to the left of your specified columns which contains checkboxes which allow you to select specific rows for actions. For my application, I need to be able to process some JavaScript when a person checks or unchecks a box. So far I have been unable to do this.

The problem is that you don't directly specify the checkbox controls, they are inserted when MDL upgrades the entire table. With other MDL components, for instance a button, I can put an onclick event on the button itself as I'm specifying it with an HTML button tag.

Attempts to put the onclick on the various container objects and spans created to render the checkboxes has been unsuccessful. The events I attach don't seem to fire. The closest I've come is attaching events to the TR and then iterating through the checkboxes to assess their state.

Here's the markup generated by MDL for a single checkbox cell:

<td>
    <label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect mdl-data-table__select mdl-js-ripple-effect--ignore-events is-upgraded" data-upgraded=",MaterialCheckbox">
        <input type="checkbox" class="mdl-checkbox__input">
            <span class="mdl-checkbox__focus-helper"></span>
            <span class="mdl-checkbox__box-outline">
                <span class="mdl-checkbox__tick-outline"></span>
            </span>
            <span class="mdl-checkbox__ripple-container mdl-js-ripple-effect mdl-ripple--center">
                <span class="mdl-ripple"></span>
            </span>
    </label>
</td>

None of this markup was specified by me, thus I can't simply add an onclick attribute to a tag.

If there an event chain I can hook into? I want to do it the way the coders intended.

Upvotes: 4

Views: 4134

Answers (3)

Nicu Surdu
Nicu Surdu

Reputation: 8301

It's not the nicest piece of code, but then again, MDL is not the nicest library out there. Actually, it's pretty ugly.

That aside, about my code now: the code will bind on a click event on document root that originated from an element with class mdl-checkbox.

The first problem: the event triggers twice. For that I used a piece of code from Underscore.js / David Walsh that will debounce the function call on click (if the function executes more than once in a 250ms interval, it will only be called once).

The second problem: the click events happens before the MDL updates the is-checked class of the select box, but we can asume the click changed the state of the checkbox since last time, so negating the hasClass on click is a pretty safe bet in determining the checked state in most cases.

function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
}

$(document).on("click", ".mdl-checkbox", debounce(function (e) {
    var isChecked = !$(this).hasClass("is-checked");
    console.log(isChecked);
}, 250, true));

Hope it helps ;)

Upvotes: 4

Gopherkhan
Gopherkhan

Reputation: 4342

You could delegate the change event from the containing form.

For example

var form = document.querySelector('form');
form.addEventListener('change', function(e) { 
    if (!e.target.tagName === 'input' || 
         e.target.getAttribute('type') !== 'checkbox') { 
       return;
    }
    console.log("checked?" + e.target.checked);
});

Upvotes: 1

Garbee
Garbee

Reputation: 10981

We currently don't have a way directly to figure this out. We are looking into adding events with V1.1 which can be subscribed to at Issue 1210. Remember, just subscribe to the issue using the button on the right hand column. We don't need a bunch of +1's and other unproductive comments flying around.

One way to hack it is to bind an event to the table itself listening to any "change" events. Then you can go up the chain from the event's target to get the table row and then grab the data you need from there.

Upvotes: 1

Related Questions