Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout.js unique IDs for use in "for" label attribute in radio button groups

I've implemented a variant of the very cunning answer here for generating unique IDs for inputs and corresponding labels in my Knockout markup. My end goal is clickable labels, not unique IDs per se - I had previously been using a click binding on each label which navigated the DOM to select its input, but that seemed breaky and inefficient.

However the solution linked doesn't work for radio button groups where each radio in the group binds back to the same observable. In my case my radio groups are either true / false (binding back to a boolean observable) or represent an enum, in which case the observable holds an integer value. The solution as provided results in all of the radios in a group (and their corresponding label for attributes) getting the same ID.

To make matters more complex, these radio button sets themselves appear multiple times. For example, there might be 10 templated divs each with a set of 3 radio buttons: Red, Green, Blue - each radio having a label which I want to activate the corresponding radio on click.

I've been struggling to modify this solution to suit, but my brain has now locked up. Any ideas welcome!

like image 894
Tom W Hall Avatar asked Sep 15 '25 07:09

Tom W Hall


1 Answers

From my comment, a fiddle using RP's binding with a modification

ko.bindingHandlers.uniqueId = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        var value = valueAccessor();
        var idMod = 'id-' + (allBindingsAccessor().uniqueMod || 0);
        value[idMod] = value[idMod] || ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter);

        element.id= value[idMod];
    },
    counter: 0,
    prefix: "unique"
};

ko.bindingHandlers.uniqueFor = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        var value = valueAccessor();
        var idMod = 'id-' + (allBindingsAccessor().uniqueMod || 0);
        value[idMod] = value[idMod] || ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter);

        element.setAttribute("for", value[idMod]);
    } 
};

Example use:

<input type="radio" data-bind="checked: gender, attr: { name: 'gender-' + id() },
     uniqueId: gender, uniqueMod: 'male'" value="1" />
<label data-bind="uniqueFor: gender, uniqueMod: 'male' ">Male</label>

<input type="radio" data-bind="checked: gender, attr: { name: 'gender-' + id() },
    uniqueId: gender, uniqueMod: 'female'" value="2" />
<label data-bind="uniqueFor: gender, uniqueMod: 'female '">Female</label>
like image 158
Kyeotic Avatar answered Sep 17 '25 21:09

Kyeotic