I have some data coming back from a resource that looks like:
$scope.phones = [
{
Value: <some value>,
IsDefault: true
},
{
Value: <some value>
IsDefault: false
}
];
And for simplicity sake, here's the repeater:
<div ng-repeat="phone in phones">
<input type="radio" name="phone" ng-model="phone.IsDefault" />
</div>
I would like whichever radio is checked to update the model accordingly - this is not happening. On page load, nothing is checked. I can use ng-checked - but without ng-model it wont bind back to the array. Am I missing something simple or am I stuck writing an ng-change event to manually update the array?
As of now, I wrote a ng-change event as well, it currently looks like:
ng-model="phone.IsDefault" ng-value="true" ng-change="newPhoneSelected($index)"
$scope.newPhoneSelected = function (index) {
for (var i = 0; i < $scope.phones.length; i++) {
if (i == index) $scope.phones[i].IsDefault = true;
else $scope.phones[i].IsDefault = false;
}
}
You are missingng-value... it is radio button they work based on value to mark a value as selected. You need either [value="" | ng-value=""]
<input type="radio"
ng-model=""
[value="" |
ng-value=""]>
Like:
<input type="radio" ng-value="true" name="boolean" ng-model="myValue" /> True
<input type="radio" ng-value="false" name="boolean" ng-model="myValue" /> False
Here is a plunker demo
Or with strings values:
$scope.myValue = 'Car'
html
<input type="radio" ng-value="'Car'" name="string1" ng-model="myValue" /> Car
<input type="radio" ng-value="'Airplane'" name="string1" ng-model="myValue" /> Airplane
Here is the second demo
This is probably the closest sample to what you have:
http://jsfiddle.net/JbMuD/
A radio button is used to select one out of many values. You want to change the property of one item (isDefault = true) and simultaneously of another one (isDefault = false).
The semantically correct way would be to have some kind of defaultPhone value:
<div ng-repeat="phone in phones">
<input type="radio" name="phone" ng-model="temp.defaultPhone" ng-value="phone"/>
</div>
Since your model requires that each phone "knows" itself wether it's default or not, you can add a listener:
$scope.$watch('temp.defaultPhone', function(defaultPhone) {
$scope.phones.forEach(function(phone) {
phone.isDefault = phone === defaultPhone;
});
});
Here's a working example.
Related
I am creating a web app in which i am using toggle button when a user click once on the toggle button 'yes' should be store in a $scope variable if the user click twice 'no' should be stored in a $scope variable
here is my codding for toggle button
<div class="switch">
<input ng-click="clickcheckbox()" id="cmn-toggle-1" class="cmn-toggle cmn-toggle-round" type="checkbox">
<label for="cmn-toggle-1"></label>
</div>
i have taken ng-click because i am not able to do this with ng-checked
here is my controller
$scope.clickcheckbox=function(){
//if user check the checkbox
$scope.check='yes';
//if user uncheck the checkbox
$scope.check='no';
}
if there are other better ways to do this(please help me out with them)
You can use the following code:
HTML
<input type="checkbox" ng-model="checkboxModel.value2"
ng-true-value="'YES'" ng-false-value="'NO'">
javascript:
$scope.checkboxModel = {
value2 : 'YES'
};
Where:
ngTrueValue : The value to which the expression should be set when selected.
ngFalseValue : The value to which the expression should be set when not selected.
Working example
Source
Try this:
$scope.clickcheckbox=function(){
$scope.check=='yes'? $scope.check='no': $scope.check='yes';
}
Inh HTML:
<div class="switch" ng-init="check='yes'">
<input ng-click="clickcheckbox()" id="cmn-toggle-1" class="cmn-toggle cmn-toggle-round" type="checkbox">
<label for="cmn-toggle-1">{{check}}</label>
</div>
The following code should work.
$scope.clickcheckbox = function() {
if($scope.check == undefined || $scope.check = 'no') {
$scope.check = 'yes';
} else {
$scope.check = 'no';
}
}
As a side note, a common way to deals with checkboxes and boolean values is do to the following:
<input type="checkbox" ng-click="check = !check">
Here, each click will revert the value between true and false.
I'm having some checkboxes and text inputs. The Text inputs are disabled when the pages loads. If a checkbox is checked, the corresponding input should be fillable. Here's my current code
For some reason I can't seem to get it right, I'm pretty new to JS and Jquery.
When I click the checkboxes, nothing happens, and when I load the page I get 6 times the text "false"
var c1 = $('#check1');
var c2 = $('#check2');
var c3 = $('#check3');
var f1 = $('#field1');
var f2 = $('#field2');
var f3 = $('#field3');
$(function() {
enable_cb(c1, f1);
enable_cb(c2, f2);
enable_cb(c3, f3);
c1.click(enable_cb(c1, f1));
c2.click(enable_cb(c2, f2));
c3.click(enable_cb(c3, f3));
});
function enable_cb(checkbox, field) {
if (checkbox.checked) {
console.log('if');
field.removeAttr("disabled");
} else {
console.log('else');
field.attr("disabled", true);
}
}
Here's a piece of html, the other parts look the same as this one:
<div class="form-group" >
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect customcheckbox" for="check1">
{{ Form::checkbox('check', 1, null, ['class' => 'mdl-checkbox__input', 'id' => 'check1']) }}
<span class="mdl-checkbox__label">test</span>
</label>
</div>
<div class="form-group" >
<label for="field1">test<br></label>
<select id="field1" name="field1" disabled class="searchselect searchselectstyle">
</select>
#if ($errors->has('field1'))
<span class="help-block">
<strong>{{ $errors->first('field1') }}</strong>
</span>
#endif
</div>
You have several issues.
You should use the change event when dealing with checkboxes so that people who navigate with the keyboard can use them.
You should provide an anonymous function to the event handler. You current code is immediately executing the enable_cb() function and then ignoring any further events.
The checkbox parameter passed to the function is a jQuery object which has no checked property. You should use is(':checked') instead.
You should use prop() over attr() and removeAttr() where possible.
Try this:
$(function() {
enable_cb(c1, f1);
enable_cb(c2, f2);
enable_cb(c3, f3);
c1.change(function() {
enable_cb(c1, f1)
});
c2.change(function() {
enable_cb(c2, f2)
});
c3.change(function() {
enable_cb(c3, f3)
});
});
function enable_cb(checkbox, field) {
if (checkbox.is(':checked')) {
console.log('if');
field.prop("disabled", false);
} else {
console.log('else');
field.prop("disabled", true);
}
}
Working example
That said, you should really look to DRY up your code to reduce repetition. Exactly how you do this depends on your HTML structure, but here's an example.
<div class="checkbox-group">
<input type="checkbox" id="check" />
<input type="text" id="subcomplex"/>
</div>
<div class="checkbox-group">
<input type="checkbox" id="yearlymanagermaintainancedayscheck" />
<input type="text" id="yearlymanagermaintainancedays" />
</div>
<div class="checkbox-group">
<input type="checkbox" id="yearlysuppliermaintainancedayscheck" />
<input type="text" id="yearlysuppliermaintainancedays" />
</div>
$('.checkbox-group :checkbox').change(function() {
$(this).siblings('input').prop('disabled', !this.checked);
}).change();
Working example
Note how much simpler the code is for the latter version, and how the JS will require no updates or maintenance no matter how many input elements you add to the HTML.
If you need to toggle a property using jQuery, you can use the prop() function, which you could use to toggle the disabled property :
$(yourElement).prop('disabled',!checkbox.checked);
which in your case might look something like :
function enable_cb(checkbox, field) {
$(field).prop('disabled',!checkbox.checked);
}
OK, here goes.
Problem 1:
I want to, based on the radio button checked, display a tr-element or not. Threre will be 3 buttons, displaying 'unlocked achievements', 'locked', and 'all' (both locked + unlocked).
The code below shows how it looks when I try to call three different functions, each setting the tr:s visibility to true/false depending on radio button checked. (D.R.Y, I know, but right now I'm just looking for the functionality).
Problem 2:
Making the for-loop run. itemsListForFilter is declared globally, outside the filter function. itemsListForFilter is a copy of an object arrayMap which is initiallized and filled elsewhere in the code. The array contains items with - amongst other things - the boolean "radioCheck", with the default value "true", which I want to check.
When I access itemsListForFilter in the function where the copying takes place it's filled with items but...
When I try to access itemsListForFilter in the filter function it displays as having the value of null. So the copy is "lost" somewhere :)
View / HTML:
<div class="widget-header-container">
<h3 class="widget-header">Achievements</h3>
<div class="wrapper">
<input type="radio" name="appliedFilter" value="all" data-bind="checked: filterAll"/><label for="all">Show all</label>
<input type="radio" name="appliedFilter" value="unlocked" data-bind="checked: filterUnlocked"/><label for="unlocked">Unlocked</label>
<input type="radio" name="appliedFilter" value="locked" data-bind="checked: filterLocked"/><label for="locked">Locked</label>
</div>
<div><div class="widget-header-line-game1"></div><div class="widget-header-line-game2"></div><div class="widget-header-line-shadow"></div></div>
</div>
<div>
<div class="rounded-box" style="padding:15px;padding-top: 0;background-color:#fff;overflow:hidden;">
<table id="game-achievements" class="table table-condensed" style="margin-top:10px;">
<tbody data-bind="foreach: viewGame.achievements()">
<tr data-bind="visible: radioCheck" style="display: none">
Viewmodel / JS:
filterUnlocked: function(){
return filter('unlocked');
},
filterLocked: function(){
return filter('locked');
},
filterAll: function(){
return filter('all');
},
filter: function(x){
for (var item in itemsListForFilter){
if (x === 'locked'){
item.radioCheck = '!achieved';
}
if (x === 'unlocked') {
item.radioCheck = 'achieved';
}
else {item.radioCheck = true;}
}
Observe that the viewmodel is an object and not a function:
var gamesViewModel = {
self: this,
settings: null,
gameId: null,
authorized: false,
(...)
Right now the functions named filterUnlocked, etc (except filter) displays as "unused properties" in the JS file. What should i do to call them from the HTML? Or is there a better way to accomplish what I'm looking for?
Thank you.
You can get the effect you want with less complexity.
First, the radio group. The checked binding in Knockout kind of replaces (or acts like) the name attribute for a radio group: all the radio buttons should share one. The bound variable will be updated to the value of the selected radio button, which will cause others bound to the same variable to de-select. Now you have one variable to look at instead of three.
Instead of doing filtering by hiding rows, it is more usual to have a computed filter the data, and the table just displays it. The computed can get the data from "outside"; it doesn't have to be an observable or part of the viewmodel (although if it's not an observable, you'll need to tell the computed when to update, if the source changes).
Here's a little working example:
var achievements = [{
name: 'The locked one',
locked: true
}, {
name: 'The unlocked one',
locked: false
}];
var vm = {
appliedFilter: ko.observable('all'),
viewGame: {}
};
vm.viewGame.achievements = ko.computed(function() {
var filter = vm.appliedFilter();
if (filter === 'all') {
return achievements;
}
return ko.utils.arrayFilter(achievements, function(item) {
return item.locked === (filter === 'locked');
});
});
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="widget-header-container">
<h3 class="widget-header">Achievements</h3>
<div class="wrapper">
<input type="radio" value="all" data-bind="checked: appliedFilter" />
<label for="all">Show all</label>
<input type="radio" value="unlocked" data-bind="checked: appliedFilter" />
<label for="unlocked">Unlocked</label>
<input type="radio" value="locked" data-bind="checked: appliedFilter" />
<label for="locked">Locked</label>
</div>
</div>
<div>
<div class="rounded-box" style="padding:15px;padding-top: 0;background-color:#fff;overflow:hidden;">
<table id="game-achievements" class="table table-condensed" style="margin-top:10px;">
<tbody data-bind="foreach: viewGame.achievements()">
<tr><td data-bind="text: name"></td></tr>
</tbody>
</table>
</div>
</div>
I have a checkbox that should check all checkboxes. The checkbox works as it should by checking all the checkbox's, however angular doesnt think they have been checked? The only way angular knows if they are checked is if i manually check each one. (The brackets and for loop are blade php from laravel)
<label class="checkbox-inline">
<input type="checkbox" ng-model="everyoneCheck"/> Everyone
</label>
#foreach($company->users as $tagIndex => $user)
<label class="checkbox-inline">
<input type="checkbox" ng-checked="everyoneCheck" ng-model="newDiscussion.notify_partners[{{$tagIndex}}]" ng-true-value="{{$user->id}}" /> {{ $user->first_name }} {{ $user->last_name }}
</label>
#endforeach
upon click of the submit button i proceed to $http.post to my server, i just pass in an object to the post function, this is the object.
var discussionData = {
'title': $scope.newDiscussion.title,
'discussion': $scope.newDiscussion.summary,
'company_id': company_id,
'notify_partners': $scope.newDiscussion.notify_partners
};
for some reason when i use the check all approach, nothing gets put into notify_partners, however when i manually click each checkbox, they will get entered and submitted properly.
Any help? I feel like its some sort of binding issue, where i just need to tell angular, hey its updated!
Here's a way to do it:
<p><input type="checkbox" ng-model="globalCheck" ng-click="toggleCheckAll()" /> Check All</p>
<ul>
<li ng-repeat="i in init">
<input type="checkbox" ng-model="checkbox[$index]" /> Checkbox {{ $index + 1 }} {{ checkbox[$index] }}
</li>
</ul>
Then in your controller:
function myControl($scope) {
$scope.globalCheck = false;
$scope.checkbox = {};
$scope.init = [0,1,2,3,4,5,6,7,8,9];
$scope.toggleCheckAll = function() {
var k, val = !$scope.globalCheck;
console.log(val);
for(k in $scope.init) {
$scope.checkbox[k] = val;
}
}
}
See JSfiddle for working example
ng-checked does not update the value bound in ng-model. It only affects the presence of the checked attribute on the element itself.
Your best bet is to use ng-change to execute some function and update all your models accordingly.
<input type="checkbox"
ng-model="everyoneCheck"
ng-change="toggleCheckAll()"/>
And in your controller, you can have toggleCheckAll() loop over your models and set them based on the value of everyoneCheck
I have a javascript array like so:
$scope.quantityMachines = [
{ 'snippet' : 'One' },
{ 'snippet' : 'Two' },
{ 'snippet' : 'Three or more',
'extraField' : true },
{ 'snippet' : 'Not sure, need advice' }
];
Then I have a list of radio buttons generated by Angular JS using the array:
<ul>
<li ng-repeat="quantity in quantityMachines">
<input type="radio" id="quantityMachines{{$index}}" name="quantityMachines" value="{{quantity.snippet}}" ng-model="howMany" />
<label for="quantityMachines{{$index}}">{{quantity.snippet}}</label>
</li>
</ul>
This works. In the array there is an extraField with value true in one of the indexes. I need Angular to show an extra input field when a radio button with the extraField setting is checked. The array may change to have more than one index with the extraField value.
So the extra field would look something like this.
<input type="text" ng-model="extraInfo" ng-show="howMany" />
Other than knowing to use ng-show, I'm not sure what would be the correct way to do this. The above example of course does nothing.
You could use ng-if and ng-show combination and a scope variable to keep track what is selected. ng-if will make sure the textbox is not added unwantedly to the DOM and ng-show to show and hide as the radio gets toggled.
In your input:-
<input type="text" ng-model="extraInfo" ng-if="quantity.extraField" ng-show="option.selected === howMany" />
and in your Radio add ng-click="option.selected=quantity.snippet"
<ul>
<li ng-repeat="quantity in quantityMachines">
<input type="radio" id="quantityMachines{{$index}}" name="quantityMachines" value="{{quantity.snippet}}" ng-model="howMany" ng-click="option.selected=quantity.snippet"/>
<label for="quantityMachines{{$index}}">{{quantity.snippet}}</label>
<input type="text" ng-model="extraInfo" ng-if="quantity.extraField" ng-show="option.selected === howMany" />
</li>
</ul>
and add in your controller:-
$scope.option = { selected:'none'};
Bin
You could even use howMany to track what was selected except that you need to set it as a property to an object on the scope (Since ng-repeat creates its own child scope and proto inheritance comes to play).
So in your radio just add ng-model="option.howMany", in your controller add $scope.option = { }; and in the text box ng-if="quantity.extraField" ng-show="quantity.snippet === option.howMany"
Bin
If only you had a plunker...without that try this
<ul>
<li ng-repeat="quantity in quantityMachines">
<input type="radio" id="quantityMachines{{$index}}" name="quantityMachines"
value="{{quantity.snippet}}" ng-model="howMany" />
<label for="quantityMachines{{$index}}">{{quantity.snippet}}</label>
<input type="text" ng-model="extraInfo" **ng-if="quantity.extraField"** />
</li>
</ul>
http://jsbin.com/biwah/1/edit?html,js,output
<ul>
<li ng-repeat="quantity in quantityMachines">
<input type="radio" id="quantityMachines{{$index}}" name="quantityMachines" value="{{quantity.snippet}}" ng-model="howMany" />
<label for="quantityMachines{{$index}}">{{quantity.snippet}}</label>
<input type="text" ng-model="quantity.extraInfo" ng-show="quantity.extraField" />
</li>
</ul>
The easiest way to show something when radio button is checked is the following:
Lets say you have a radio-group with: ng-model="radio-values"
To show or hide your input then depends on the values within the radio-group: value="radio-value1", value="radio-value2"
To finally show or hide the input field (lets say you want to show something if "radio-value1" is set) you do:
<input ng-show="radio-values == 'radio-value1'" ...>