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 plex, 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 wele!
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 plex, 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 wele!
Share Improve this question edited May 23, 2017 at 11:59 CommunityBot 11 silver badge asked Jul 18, 2012 at 3:08 Tom W HallTom W Hall 5,2834 gold badges31 silver badges35 bronze badges 9- My interim solution is to just rely on implicit association by putting the radio inputs inside the labels - but I don't like that approach because this site is going to be adapted by a graphic designer who may change the structure (yes, I'm scared too) and I don't like that use of labels anyway because of CSS styling issues. – Tom W Hall Commented Jul 18, 2012 at 3:41
- Can you post a fiddle with an example of your viewmodel. Its not clear how you are reusing the radios. – Kyeotic Commented Jul 18, 2012 at 4:26
- Yep, here's a simplified example: jsfiddle/qeQTd/17 Cheers. – Tom W Hall Commented Jul 18, 2012 at 5:07
- I'm thinking now that I could generate the ID with a binding in a similar fashion to the name, and reuse that on the label for - but the markup is going to get pretty heinous. – Tom W Hall Commented Jul 18, 2012 at 5:20
-
Works fine for me: jsfiddle/tyrsius/52xDw/1. Also, the mapping plugin actually makes your example longer and more plicated than it would be if you just used
arrayMap
. – Kyeotic Commented Jul 18, 2012 at 5:34
1 Answer
Reset to default 8From my ment, 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>