How can I disable Bootstrap 3 radio buttons? If I start with the BS3 example and add disabled="disabled" to each input element, there are no changes in appearance or behavior:
<div class="container">
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-primary active">
<input type="radio" name="options" id="option1" autocomplete="off" checked disabled="disabled">Radio 1 (preselected)</label>
<label class="btn btn-primary">
<input type="radio" name="options" id="option2" autocomplete="off" disabled="disabled">Radio 2</label>
<label class="btn btn-primary">
<input type="radio" name="options" id="option3" autocomplete="off" disabled="disabled">Radio 3</label>
</div>
Demo: JSFiddle.
I guess this is because the disabled attribute is only applied to the now-invisible button and not the clickable text label, but I don't see anything in the BS3 docs about this.
Add disabled class to the label like this
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-primary disabled">
<input type="checkbox" autocomplete="off"> Checkbox 1 (pre-checked)
</label>
<label class="btn btn-primary active disabled">
<input type="checkbox" autocomplete="off"> Checkbox 2
</label>
<label class="btn btn-primary disabled">
<input type="checkbox" autocomplete="off"> Checkbox 3
</label>
</div>
Here is a demo
As mentioned by #giammin in the comments to the accepted answer, setting 'disabled' on the input elements doesn't work in 3.3.6 of bootstrap. (Current version at time of publication of this answer).
I was having exactly the same issue, and my solution was to use the CSS property "pointer events". This makes sure the element and children are never a target of click events. However this is not a foolproof solution - users can still tab in and use space to click the hidden elements on a desktop browser.
.disabled-group
{
pointer-events: none;
}
If you set this on your '.btn-group' element, you'll completely disable
<div class="btn-group disabled-group" data-toggle="buttons">
<label class="btn btn-primary disabled">
<input type="checkbox" autocomplete="off"> Checkbox 1 (pre-checked)
</label>
<label class="btn btn-primary disabled">
<input type="checkbox" autocomplete="off"> Checkbox 2
</label>
<label class="btn btn-primary disabled">
<input type="checkbox" autocomplete="off"> Checkbox 3
</label>
</div>
The '.disabled' class is then optional - use it for graying out and 'cursor: not-allowed;' property.
The discussion of the fix solution is at this source:
https://github.com/twbs/bootstrap/issues/16703
For radio button groups, add class disabled to the one you wish disabled.
Make sure you have something like this code:
$('.btn-group').on("click", ".disabled", function(event) {
event.preventDefault();
return false;
});
This will get all your .disabled classed buttons inside the button groups also disabled. This works also for radio type button groups.
You can use the above to disable an input[type='radio'] that is inside a label (bootstrap 3 style),
$("input[name='INPUT_RADIO_NAME']").prop("disabled", true);
$("input[name='INPUT_RADIO_NAME']").closest("div").css("pointer-events", "none");
The above to enable again,
$("input[name='INPUT_RADIO_NAME']").prop("disabled", false);
$("input[name='INPUT_RADIO_NAME']").closest("div").css("pointer-events", "auto");
You can also extend JQuery and create a dummy disable method (that you could upgrade with more functionality) like this,
(function ($) {
$.fn.disableMe = function () {
// Validate.
if ($.type(this) === "undefined")
return false;
// Disable only input elements.
if ($(this).is("input") || $(this).is("textarea")) {
// In case it is a radio inside a label.
if ($(this).is("[type='radio']") && $(this).parent().is("label.btn")) {
$("input[name='safeHtml']").closest("label").addClass("disabled");
$(this).closest("div").css("pointer-events", "none");
}
// General input disable.
$(this).prop("disabled", true);
}
};
$.fn.enableMe = function () {
// Validate.
if ($.type(this) === "undefined")
return false;
// Enable only input elements.
if ($(this).is("input") || $(this).is("textarea")) {
// In case it is a radio inside a label.
if ($(this).is("[type='radio']") && $(this).parent().is("label.btn")) {
$("input[name='safeHtml']").closest("label").removeClass("disabled");
$(this).closest("div").css("pointer-events", "auto");
}
// General input enable.
$(this).prop("disabled", false);
}
};
$.fn.toggleDisable = function () {
if ($.type(this) === "undefined")
return false;
// Toggle only input elements.
if ($(this).is("input") || $(this).is("textarea")) {
var isDisabled = $(this).is(":disabled");
// In case it is a radio inside a label.
if ($(this).is("[type='radio']") && $(this).parent().is("label.btn")) {
$("input[name='safeHtml']").closest("label").toggleClass("disabled");
$(this).closest("div").css("pointer-events", isDisabled ? "auto" : "none");
}
// General input enale.
$(this).prop("disabled", !isDisabled);
}
};
}(jQuery));
Usage example,
$("input[name='INPUT_RADIO_NAME']").disableMe();
$("input[name='INPUT_RADIO_NAME']").enableMe();
$("input[name='INPUT_RADIO_NAME']").toggleDisable();
In bootstrap if you want to disabled any input type or button, You just have to add bootstrap's .disabled class then your button become disabled.
Like this
<input type="radio" class="btn btn-primary disabled">Primary Button</button>
Related
I have a boostrap toggle with the code below. It is visually working right
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-primary active">
<input type="radio" name="options" id="showBuildQuantity" autocomplete="off" checked>Build Quantity
</label>
<label class="btn btn-primary">
<input type="radio" name="options" id="showNumberOfScreens" autocomplete="off" onclick="showBuildQuantity()">Number of Screens
</label>
</div>
Below it I have some code to handle click events:
$(document).ready(function () {
$('#showBuildQuantity').on('click', function () {
<code here>
});
$('#showNumberOfScreens').on('click', function () {
<code here>
});
});
The issue I am having is that the click event's are never run when I click the toggle buttons.
I have other buttons on the same page using the same kind of jQuery click event and they do not have an issue.
After some research I found I need to use change instead of click. So the code should look like this:
$('#showBuildQuantity').on('change', function () {
if (myChart != null) {
myChart.destroy();
}
setChart(getBuildQuantityData);
});
$('#showNumberOfScreens').on('change', function () {
if (myChart != null) {
myChart.destroy();
}
setChart(getNumScreensData);
});
I'm having trouble getting the correct value from a segmented control I made with the radio button component of button.js in Twitter Bootstrap 3. When I bind a click event to the segmented control that runs $.serialize() on the parent form, it return the unchecked value of the radio button along with all the other correct values from the other inputs.
I suspect it might be related to the fact that I can't bind this event directly to the segmented control's input. When I tried to bind the event directly to the input I didn't get a response back, so I bound it to the label.
Here's an example of the problem in a fiddle: https://jsfiddle.net/stevekas/9w94pL4o/
<form id="form">
<div id="radios">
<div class="radio">
<label class="major-category">
<input facet="exclusive" type="radio" name="hipsum" value="hashtag" />hashtag</label>
</div>
<div class="radio">
<label class="major-category">
<input facet="exclusive" type="radio" name="hipsum" value="farm-to-table" />farm-to-table</label>
</div>
<div class="radio">
<label class="major-category">
<input facet="exclusive" type="radio" name="hipsum" value="gastropub" />gastropub</label>
</div>
</div>
<!--/ #radios -->
<div id="segmented-control" class="btn-group btn-group-justified" data-toggle="buttons">
<label class="btn btn-default active">
<input type="radio" name="segmented-control" id="roof" value="roof" autocomplete="off" checked />roof</label>
<label class="btn btn-default">
<input type="radio" name="segmented-control" id="party" value="party" autocomplete="off" />party</label>
</div>
<!--/ #segmented-control -->
</form>
<script>
$('.radio input').on('click', function () {
var data = $('#form').serialize();
});
$('#segmented-control label').on('click', function () {
var data = $('#form').serialize();
});
</script>
It probably happens because the click for the label is processed before the click for the input (the label is higher in the DOM tree).
You can force debug to be called after all the events have been processed using setTimeout() without any delay, like this:
$('#segmented-control label').on('click', function () {
setTimeout(function() {
debug();
}, 0);
});
This works because setTimeout() enqueues a new event, which will be run after all the current pending ones.
I have a group of 3 bootstrap styled checkboxes like so:
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-primary btn-sm" data-bind=""><input type="checkbox">Checkbox 1</label>
<label class="btn btn-primary btn-sm"><input type="checkbox">Checkbox 2</label>
<label class="btn btn-primary btn-sm"><input type="checkbox">Checkbox 3</label>
</div>
At runtime if the first checkbox is pressed, when I inspect the element it gets an active css class appended to it:
<label class="btn btn-primary btn-sm active" >
How should my data-bind="" property look like if I want a function to execute when the input receives the active class? I would also want the opposite to happen as well. When the active class is no longer present, a function must also be called.
I can't use a click binding on the checkbox because it doesn't work because of bootstrap's way of "ticking" a checkbox.
Thank you (demo - http://jsfiddle.net/H7Js6/)
knockout is about having a viewmodel that represents your UI. Instead of a click binding, you can have checked binding and use the subscribe function:
<label class="btn btn-primary btn-sm" data-bind="">
<input type="checkbox" data-bind="checked: cb1" />Checkbox 1
</label>
And in the js:
var viewmodel = function () {
this.cb1 = ko.observable();
this.cb1.subscribe(function (newValue) {
//your code here gets called every time the checked status changes
// use newValue to know the new state
});
}
Demo
Update
Thank you for your fiddle, it always helps to have one.
Indeed, in this case the checked is not changed when the bootstrap css is loaded (if you remove the resource, you'll see it works).
To workaround it, you can have a custom binding handler that will check the presence of the css class for you:
ko.bindingHandlers.bootstrapCheckbox = {
init: function (element, valueAccessor, allBindingAccessor, viewModel,
bindingContext) {
if (ko.isObservable(allBindingAccessor().value)) {
$(element).change(function () {
//invert it because called before the class is added/removed :(
allBindingAccessor().value(!$(element).hasClass("active"));
});
}
allBindingAccessor().value($(element).hasClass("active")); //init value
}
}
Usage:
<label class="btn btn-primary btn-sm"
data-bind="bootstrapCheckbox: true, value: cb1">
<input type="checkbox" />Checkbox 1
</label>
Then keep the code from the first part of this answer (the subscribe).
Demo
Understanding there's already a good answer and trying to get how it was done I thought of using the already existing click binding for this, which may be another option (not saying it's better at all)
var vm = function(){
this.checkedButtons = ko.observableArray([]);
this.isActive = function(item, event){
if (!$(event.target).hasClass("active")){
this.checkedButtons.push(event.target);
}
else{
this.checkedButtons.pop();
}
};
};
ko.applyBindings(new vm());
Usage:
<div class="btn-group" data-toggle="buttons">
<label id="label1" class="btn btn-primary btn-sm" data-bind="click: isActive"><input id="input1" type="checkbox">Checkbox 1</label>
<label class="btn btn-primary btn-sm" data-bind="click: isActive"><input type="checkbox">Checkbox 2</label>
<label class="btn btn-primary btn-sm" data-bind="click: isActive"><input type="checkbox">Checkbox 3</label>
</div>
<div>How many buttons are clicked?
<span data-bind="text: checkedButtons().length "></span>
</div>
Fiddle
If you're using jquery, you can bind change event on the radio buttons themselves
$(".btn-group input[type=checkbox]").on("change",function(){
//you can do whatever you want here
});
Consider the HTML as
<div class="btn-group col-lg-3" data-toggle="buttons" data-ng-model="transaction.debit" required>
<label class="btn btn-default" data-ng-click="setDebitTransaction('true')">
<input type="radio">Debit
</label>
<label class="btn btn-default" data-ng-click="setDebitTransaction('false')">
<input type="radio">Credit
</label>
<div>
and my Controller looks like
$scope.transaction = {};
$scope.setDebitTransaction = function(value) {
$scope.transaction.debit = value;
console.log('Debit = ', $scope.transaction.debit);
};
What I want?
- When I click on radio button I see that the $scope.transaction.debit is correctly set and that the corresponding radio button is enabled
- But when my model changes its value from backend processing, I see that $scope.transaction.debit is correctly set but corresponding radio element is not enabled
Question
- How can I enable the radio button based on value in $scope.transaction.debit?
DEMO
I have put this on plunker
I assume what you are trying to do is get the appropriate button in the btn-group to change its state to "active" (bootstrap style class). To do this, there are probably a million ways, here is one:
Use the ng-class directive in angular, to inject a class to the btn div, based on some $scope attribute (in your case $scope.transaction.debit).
Here is how that might look in code:
<label class="btn btn-default" ng-class="{'active': transaction.debit}" data-ng-click="setDebitTransaction('true')">
<input type="radio">Debit
</label>
<label class="btn btn-default" ng-class="{'active': !transaction.debit}" data-ng-click="setDebitTransaction('false')">
<input type="radio">Credit
</label>
Updated plunker.
Set the active class via ng-class on your labels like so:
<label class="btn btn-default" ng-class="{active: transaction.debit}" data-ng-click="setDebitTransaction('true')">
<input type="radio">Debit
</label>
<label class="btn btn-default" ng-class="{active: !transaction.debit}" data-ng-click="setDebitTransaction('false')">
<input type="radio">Credit
</label>
Plunker here: http://plnkr.co/edit/tUzF4J9ixEnKxLNdI1Bm
I have a button group and am willing to update some other field on change according to the active buttons.
See the jsfiddle here
This is the HTML, copied from the documentation:
<div class="btn-group arrActiviteit arrUpdate" data-toggle="buttons">
<label class="btn btn-primary active" data-wat='foo'>
<input type="checkbox"> Item 1
</label>
<label class="btn btn-primary" data-wat='bar'>
<input type="checkbox"> Item 2
</label>
<label class="btn btn-primary" data-wat='something'>
<input type="checkbox"> item 3
</label>
<label class="btn btn-primary" data-wat='orElse'>
<input type="checkbox"> item 4
</label>
</div>
The Button row acts like it should do.
Then I watch for a click event on the .arrUpdate div for change. I've got multiple button groups which all have the .arrUpdate class. That's the reason for the second class: .arrActiviteit
$('.arrUpdate').click(function(e){
val = ''; // for holding the temporary values
$('.arrActiviteit label').each(function(key, value){
if(value.className.indexOf('active') >=0){
val += value.dataset.wat
}
})
// just for debug reasons.
$('#hierHier').html(val);
})
But it appears that the 'active' class gets added after the click event is fired. So the value in #hierHier is always behind one click, so to say.
How can I resolve this?
Or is there a better way to retrieve all the active buttons in this checkbox-array?
SOLVED
update: better solution Twitter Bootstrap onclick event on buttons-radio
http://jsfiddle.net/hA423/7/
I solved it using a timeout to make your function run after bootstrap events...
There must be some other ways to do it...
$('.btn').on('click',function(e){
setTimeout(count);
})