Simple Angular radio buttons not working... seem broken? - javascript

This works:
<h4>Radio & Uncheckable Radio</h4>
<pre>{{radioModel || 'null'}}</pre>
<div class="btn-group">
<label class="btn btn-primary" ng-model="radioModel" btn-radio="'Left'">Left</label>
<label class="btn btn-primary" ng-model="radioModel" btn-radio="'Middle'">Middle</label>
<label class="btn btn-primary" ng-model="radioModel" btn-radio="'Right'">Right</label>
</div>
This doesn't work
{{radioModel || 'null'}}
<div class="btn-group">
<label class="btn btn-primary" data-ng-repeat="store in global.user.store" ng-model="radioModel" btn-radio="{{store}}" uncheckable>{{store}}</label><br>
</div>
If you select one radio button, the other radiobuttons don't de-select. Instead of having one radio button checked at a time, all 3 can be checked! And the {{radioModel}} won't display any value. For the first example, {{radioModel}} would display 'Left,' 'Right,' or 'Middle' depending on the value of btn-radio.
It's like data-ng-repeat="store in global.user.store" breaks the button behavior!

Try setting the scope variable with a dot, like if it an object.
$scope.radio = {model: null}; //for example
And use always radio.model instead of radioModel.
This is because the way the scope inheritance works each ng-model of the ng-repeat will generate a new scope. With the 'dot' rule you want have this problem.
Here is more information https://github.com/angular/angular.js/wiki/Understanding-Scopes

Try removing the {{}} in the btn-radio attribute :
<label class="btn btn-primary" data-ng-repeat="store in global.user.store" ng-model="radioModel" btn-radio="store" uncheckable>{{store}}</label>

Related

ng-option not selecting model value on first call

I have multiple drop downs with different data arrays. On Edit click, I want to set the selected value. I have set ng-model to be the object but its not working.
<div class="form-group">
<label class="control-label">Category{{product.categoryDto}}</label>
<select ng-model="product.categoryDto" class="form-control" ng-options="a.categoryName for a in categories"></select>
</div>
Following is the edit code.
<button type="button" ng-click="editProduct(row)" class="btn btn-sm btn-primary">
<i class="glyphicon glyphicon-pencil"></i>
</button>
$scope.editProduct = function(row){
console.log($scope.product.categoryDto);
$scope.product = row;
$scope.showAddProductForm = true;
$scope.product.categoryDto = row.categoryDto;
};
In label categoryDto is showing correct values but not selecting the option. Any idea?

AngularJS: Unable to read radio button value in nested ng-repeat

I am creating a calendar like grid which generates numbers from 1 to 31 using two ng-repeats. Each element of the grid is a radio button, whose value I want to get inside a controller.
For example, user clicks on '12', the value gets stored somewhere, and on click of submit propagates to the controller.
The problem is that I am unable to read the value of the element checked.
Code:
<div data-toggle="buttons">
<div class="row" ng-repeat="date in dates track by $index" ng-if="$index % 5 == 0">
<label ng-class="{'btn-online': isOnline(i+1), 'btn-paper': isPaper(i+1)}" class="singleDate btn btn-default col-no-gutter col-xs-2 letter-box"
ng-repeat="i in [$index, $index + 1, $index + 2, $index + 3, $index + 4]"
ng-if="dates[i] != null">
<input type="radio" name="dates" id="date-{{i+1}}" ng-model="$parent.dueDate" ng-value="{{date[i]}}" class="date radio radio-primary">{{dates[i]}}
</label>
</div> <!--row div ends here -->
{{dueDate}} <!--no output here as well-->
</div>
<button type="submit" ng-click="changeDueDate(dueDate)" class="btn btn-block btn-default">Change Payment Due Date</button>
Don't Bind to Primitives
<!-- instead bind to objects -->
<button type="submit" ng-click="changeDueDate(obj.dueDate)">
Change Payment Due Date
</button>
Each ng-repeat and ng-if adds a new scope and level of hierarchy. Instead of counting levels of hierarchy, make dueDate a property of an object, obj.dueDate. Then prototypical inheritance will do its magic properly. For more information, see The Nuances of Scope Prototypal Inheritance.

Bind element if css class exists

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
});

AngularJS: How to change radio button view when model changes?

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

Getting active buttons in button-group (bootstrap)

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);
})

Categories