I am busy writing some helper functions for my fellow developers in-office who isn't too familiar with Bootstrap - which takes basic html and creates bootstrap layouts for them.
In this case, I am trying to make a justified horizontal list of radio buttons.
A example is:
<fieldset data-type="horizontal" data-bootstrap="radiogroup"> <label> <input type="radio" name="g1" value="default" data-bind="checked: true"/>Recent </label> <label> <input type="radio" name="g1" value="order" data-bind="checked: false"/>By Number </label> <label> <input type="radio" name="g1" value="advanced" data-bind="checked: false"/>Advanced </label> </fieldset>
I execute some JQuery inside the typescript file linked to this page - and the code reads:
function layoutUnwrappedBootstrapControls() { $("*[data-bootstrap='radiogroup']") .each((index, element) => { var listOfRadioButtons = $(element).find('label').clone(); $(element).children().remove(); $(element) .append("<div class='btn-group col-lg-12 col-md-12 col-sm-12 col-xs-12 clearfix' data-toggle='buttons'></div>"); $(element) .children(":first") .append(listOfRadioButtons) .find("label") .addClass("btn btn-primary") .css("width", (100 / listOfRadioButtons.length) + '%'); $(element).children(":first").button().button('refresh'); //< the issue }); }
Which produces:
<div class="btn-group col-lg-12 col-md-12 col-sm-12 col-xs-12 clearfix" data-toggle="buttons"> <label class="btn btn-primary" style="width: 33.3333%;"> <input type="radio" name="g1" value="default" data-bind="checked: true" data-mini="true" data-theme="h" id="tz15" checked="checked">Recent </label> <label class="btn btn-primary" style="width: 33.3333%;"> <input type="radio" name="g1" value="order" data-bind="checked: false" data-mini="true" data-theme="h" id="tz16">By Number </label> <label class="btn btn-primary" style="width: 33.3333%;"> <input type="radio" name="g1" value="advanced" data-bind="checked: false" data-mini="true" data-theme="h" id="tz17">Advanced </label> </div>
On the page, this seems fine. The issue I have however, is the data-toggle='buttons'
part - it tells me that bootstrap runs some code in order to initialise the list of radio buttons - and it doesn't seem to play nice with dynamically created button-groups.
My attempt to reinitialise the button group doesn't work. Radio Buttons still remain static - doesn't swap out 'active' on the label, and 'checked' on the input.
The spoopier part is: I cannot reproduce my issue on JSFiddle using identical code! it works as expected on JSFiddle: JSFiddle
How can I force a re-initialisation of a dynamically-created button-group?
4 Answers
Answers 1
The issue was the fact that, as @knetsi mentioned in the comments under the question has mentioned, when you do not have bootstrap.js loaded on your site, you will not get an error in the console to point you what the issue was. When, like on my site, you work with both JQuery UI / JQuery Mobile /JQuery and Bootstrap JS, Bootstrap needs to be loaded last - as it will cause a conflict with the other libraries when you attempt to refresh a button
Answers 2
If your code executes after bootstrap has already done it's business, it will not work...
You need to make your code execute before bootstrap...
So you need to either,
- Add your scripts before bootstrap if you are using document ready event.
- Move your scripts right after your html (in footer) without using document ready event.
Answers 3
If you call document ready again then previous events associated using bootstrap.js will be unbind, which is not a good idea so you can either change the sequence of execution of your script (means before bootstrap.js) or hold document ready event itself until you are done with your script. You can get reference of jquery.holdready here https://api.jquery.com/jquery.holdready/
Answers 4
The following worked for me (locally and in a fiddle).
In addition to incorporating document.ready
in a script tag inside the body (mentioned by previous answers) it looks like your knockout binding has a problem. I changed checked: true / checked: false
to checked: statusMsg
and added statusMsg: ko.observable("default")
. Knockout will check a radio box when the observables value is equal to some radio inputs nodeValue. From the documentation:
For radio buttons, KO will set the element to be checked if and only if the parameter value equals the radio button node’s value attribute or the value specified by the checkedValue parameter.
Knockout checked binding documentation
I logged the checked
values of the boxes after clicking and it worked.
My code and fiddle below:
<body> <fieldset data-type="horizontal" data-bootstrap="radiogroup"> <label> <input type="radio" name="g1" value="default" data-bind="checked: statusMsg"/>Recent </label> <label> <input type="radio" name="g1" value="order" data-bind="checked: statusMsg"/>By Number </label> <label> <input type="radio" name="g1" value="advanced" data-bind="checked: statusMsg"/>Advanced </label> </fieldset> <script> $(document).ready(function() { $("*[data-bootstrap='radiogroup']") .each((index, element) => { var listOfRadioButtons = $(element).find('label').clone(); $(element).children().remove(); $(element) .append("<div class='btn-group col-lg-12 col-md-12 col-sm-12 col-xs-12 clearfix' data-toggle='buttons'></div>"); $(element) .children(":first") .append(listOfRadioButtons) .find("label") .addClass("btn btn-primary") .css("width", (100 / listOfRadioButtons.length) + '%'); }); var viewModel = { statusMsg: ko.observable("default") } ko.applyBindings(viewModel); }); </script> </body>
0 comments:
Post a Comment