I am facing problem because I have a checkbox inside a div and I want to call a function in both the cases: if we change the checkbox value or click the div.
Now the problem is that, When I click the checkbox, The event is fired twice and I am not getting expected result.
<div ng-click="checkEntry(config.id)"><input type="checkbox" ng-model="modelCheckbox" ng-change="checkEntry(config.id)" ng-checked="someArray.indexOf(config.id) !== -1"></div>
$scope.checkEntry = function(id){
var idx = $scope.someArray.indexOf(id);
if(idx === -1){
$scope.someArray.push(id);
}else{
$scope.someArray.splice(idx, 1);
}
}
Now If i click div, it works fine and the checkbox gets selected. But if i click the checkBox, the function is called twice, and it doesn't work as expected.
Please help me with a solution
You don't need two event handler for two identical events.When you click on the input, the div will be clicked as well. so you just need to remove ng-change from your code.
<div ng-click="checkEntry(config.id)">test
<input type="checkbox" ng-model="modelCheckbox" ng-checked="checked">
and in your controller:
$scope.checked = true;
$scope.checkEntry = function(id){
$scope.checked = !$scope.checked;
}
Look at this plunker
Checkbox is situated inside of that div, so when you click checkbox you are actually clicking also on div.
Actually, in your case you can remove ng-change attribute from checkbox and it will still work, because function will be called via click on div anyway. But that is not correct way to work with checkboxes!
First question here is if you really need that div?
I would rather use label instead:
<label for="my-checkbox"><input id="my-checkbox" type="checkbox" ng-model="modelCheckbox" ng-change="checkEntry(config.id)" ng-checked="someArray.indexOf(config.id) !== -1"></label>
In such case it will work fine, you just need to write proper CSS to style that label correctly. This is the best and the most correct solution.
Related
I have some issue understanding the jQuery().change() behavior.
The HTML is basically a lot of input elements - checkboxes ( each with ID of id^='o99-post-visible-XXX' - and they are pure CSS images as Checkboxes, but this is irrelevant ) and I have another checkbox ("#o99-check-all") to "check all" and a text input field ('#o99-post-visible-ids') that receives the IDs of the selected boxes.
The jQuery code is as follows:
jQuery(document).ready(function() {
jQuery("#o99-check-all").change(function () {
jQuery("input:checkbox[id^='o99-post-visible-']").prop('checked', jQuery(this).prop("checked")).trigger('change');
});
var checkboxes = jQuery("input.o99-cbvu-posts-checkbox:checkbox");
checkboxes.on('change', function() {
// get IDS from all selected checkboxes and make a comma separated string
var ids = checkboxes.filter(':checked').map(function() {
return this.value;
}).get().join(',');
// put IDS inside a text input field
jQuery('#o99-post-visible-ids').val(ids);
// console.log(ids);
});
});
Now, more or less everything works now, but that is not the issue.
at first , the first chunk of code was:
jQuery("#o99-check-all").change(function () {
// without .trigger('change') chained
jQuery("input:checkbox[id^='o99-post-visible-']").prop('checked', jQuery(this).prop("checked"));
});
and it did not work ( why?? ) - meaning the boxes were selected as expected but the '#o99-post-visible-ids' input field was not receiving the IDs - until I chained a .trigger('change') event - when suddenly it works well.
my confusion is with the following ( which perhaps for my little understanding of jQuery internal works is counter-intuitive )
after chain adding .trigger('change') - isn't it somehow an endless loop where a chain() event is trigger inside a listener of change() ? and if not why?
Why is the code functioning now and did not function correctly before? because again, for my understanding, there was a change, even if not triggered by direct user click. Why would I need to trigger it manually?
I'm not sure I understand what you mean. What is happening now, is that whenever you change the all checkbox, the other checkboxes will be checked/unchecked the same as all, and then the change event is triggered.
Because you added a listener for change, that function will then fire. I.e. this function will run:
function() {
// get IDS from all selected checkboxes and make a comma separated string
var ids = checkboxes.filter(':checked').map(function() {
return this.value;
}).get().join(',');
// put IDS inside a text input field
jQuery('#o99-post-visible-ids').val(ids);
// console.log(ids);
}
Without your .trigger("change") (or .change() in short), you only change a property of the inputs. So the object changes, indeed, but that does not mean the change event is triggered. It does sound counter-intuitive, but events are only triggered by user actions or if you call the event explicitly - in no other way do events get triggered.
its because you have written jQuery('#o99-post-visible-ids').val(ids); inside a function which happens only when the change event done on the inputs, assigning prop directly through .prop does not trigger the change event and so the result handler wont run
Now if I understand you correctly...
...because you're giving every check box the same ID? If you wish to apply it to more than a single element, it is best practice to use a class selector instead.
jQuery(".o99-check-all").change(function () {
// without .trigger('change') chained
jQuery(".o99-check-all").prop('checked', jQuery(this).prop("checked"));
});
See link
https://api.jquery.com/change/
Using:
function CheckToggle(which){
jQuery(which).each(function() {
jQuery(this).attr('checked', !jQuery(this).attr('checked'));
});
}
On first click, all checkboxes get checked, click it again, and they get unchecked.
Second click, no checkmarks show in the boxes, however, the checked="checked" attribute does appear in the element, and dissapears if clicking the checkall again.
How can I keep them showing the checkmark?
In this situation, .prop() would be used instead of .attr(). But honestly, it'd be even better to not use either:
this.checked = !this.checked;
Use prop instead of attr
function CheckToggle(which){
jQuery(which).each(function() {
jQuery(this).prop('checked', !jQuery(this).attr('checked'));
});
}
I need to hide a button until a check box is clicked, however I am stepping into someone elses code who used tag libraries that did not define ID in the button tag. Here is what I have:
The button code:
<html:button name="Next" value="BTN.NEXT" styleClass="button" localeCd="<%= localeCd %>" onClick='Submit("Next")'/>
The checkbox code:
<input type="checkbox" name="fedCheck" onclick="checkFed(this, 'myNext')" value="y" />
The Javascript Code
function checkFed(ele, id) {
x = document.getElementById(id);
if (ele.checked == true) x.disabled = false;
else x.disabled = true;
}
I can get this to work in a seperate page but the page that it is on does not allow for the button to have an ID so it crashes every time. Any suggestions?
There would be better ways of doing this, listening for the click event, etc... but, to simply modify your code see this jsFiddle (note: this assumes this is the only element named "Next"):
function checkFed(ele, name) {
x = document.getElementsByName(name)[0];
x.disabled = !x.disabled
}
And change the onclick="checkFed(this, 'myNext')" to:
onclick="checkFed(this, 'Next')"
And add disabled="true" to the button so that it's initial state is disabled
...also note that this doesn't actually hide it like the title asks, it disables it, like the content of the question seems to ask.
Instead of finding the button using document.getElementById, use document.querySelector.
For example, if you have a single button on the page with "Next" as the value of its name attribute:
document.querySelector('button[name="Next"]')
Hi guys I am having a problem with Events. I have a checkbox list and I have a main check box that checks all boxes. When I clickEvent some of my checkbox list items it should add data-id attr to the "selected obj". So in my case when I press main check box to check all others every thing is ok (it simply clicks all other elements). but when i do that it empties my array. I mean if i uncheck it will be the way it supposed to be but checked (when uncheck it fills when i check it empties).
......
var selected = {};
var reload = function(){
selected = {};
$('.checkbox_all').unbind('click');
$('.table_checkbox').unbind('click');
$('.checkbox_all').bind('click', checkAll);
$('.table_checkbox').bind('click', checkMe);
}
var checkMe = function(e){
var checkbox = $(e.target);
var id = checkbox.attr('data-id');
//console.log(id);
if(checkbox.attr('checked')){
selected[id] = id;
}else{
if(selected[id]) delete selected[id];
}
console.log(selected);
}
var checkAll = function(e){
if($(e.target).attr('checked')){
$('.table_checkbox').each(function(){
if($(this).attr('checked') === false){
$(this).click();
}
});
}else{
$('.table_checkbox').each(function(){
if($(this).attr('checked') === true){
$(this).click();
}
});
}
//console.log(selected);
}
.......
HTML:
<tr><th class="table-header-check"><input type="checkbox" class="checkbox_all"/></th></tr>
<tr class=""><td><input type="checkbox" data-id="5" class="table_checkbox"></td></tr>
<tr class="alternate-row"><td><input type="checkbox" data-id="6" class="table_checkbox"</td></tr>
<tr class="alternate-row"><td><input type="checkbox" data-id="8"
....ETC\
My problem is that when i click .checkbox_all it should click on all .table_checkbox(that r cheched or uncheched)... it just clicks all checkboxes like a main checkbox... it works fine, but i have an event all other checkboxes if i click em i add some data to array when i unclick em it removes data from array.... so when im clicking checkboxes sepperatly they add /remove data to array properly... but when im clicking on main checkbox... it clicks on right checkboxes but the data array is empty when all checked and full when all unchecked... it must be the opposite way
Could you instead go for a cleaner solution, and generate selected on the fly? See here for an example (and a JSFiddle for everyone else): http://jsfiddle.net/turiyag/3AZ9C/
function selected() {
var ret = {};
$.each($(".table_checkbox"),function(index,checkbox) {
if($(checkbox).prop("checked")) {
ret[$(checkbox).prop("id")] = true;
}
});
return ret;
}
** EDIT: **
If you're looking to have an array that is added to and removed from, then this JSFiddle (http://jsfiddle.net/turiyag/pubGb/) will do the trick. Note that I use prop() instead of attr(), in most cases, especially this one, you should use prop() to get the value you want.
To work with your own code you need to understand the order of events. When you programmatically call click() on the checkbox the javascript (checkMe() for children) executes before the state of each child checkbox is changed (e.g., adding attribute 'checked'). It is because of this reason that the checkMe() function was adding and removing ids in the selected array in the reverse order. You can confirm this by adding the following debug line in the checkMe function:
console.log('Checked state of checkbox id:' + id + ' is: ' + checkbox.prop('checked'));
Case1: Clicking checkAll when it is Unchecked; it calls checkMe() for each child checkbox but finds the 'checked' attribute as undefined. So it executes the delete code. After executing checkMe the 'checked' attribute is added on the checkbox.
Case2: Clicking checkAll when it is Checked; the checkMe() function finds the 'checked' attribute previously added and fills the array. Later an event is probably fired to remove the 'checked' attribute.
I changed the following lines to quickly test this and seems to be working:
Bind checkMe on change event instead of click in reload function:
$('.table_checkbox').bind('change', checkMe);
Change the condition for unchecked children in checkAll function when the .checkbox_all is checked:
if($(this).prop('checked') === false) {/*call child click*/}
//Use prop instead of attr because it takes care of 'undefined' cases as well. If you want to keep using attr because you're on an older version of jquery then add something like:
typeof $(this).attr('checked') == 'undefined'
and also the condition when .checkbox_all is unchecked:
if($(this).prop('checked') === true) {/*call child click*/}
Hope this helps. Here's a jsbin to play with..
Well, I'm stuck and have been banging my head for a little while now to try to figure what I'm doing wrong.
Scenario:
I have a question with a Yes/No answer (ie 2 radio buttons). When a user selects the either Yes or No, I call a function to .toggle() a hidden div to show a link. That works great. And if they go back and check that Yes/No again it disappears again due to the .toggle()
My issue is that if a user clicks the No (and the link is shown) but then clicks the Yes I want the link that is showing due to the No result to disappear and vice-versa.
So basically only show 1 link at a time.
I figured that maybe an If statement would work but I can't seem to get it right.
My code:
<div id="Question1">
<div>Do you kazoo?</div>
<input type="radio" ID="Q1RB1" runat="server" value="Yes" text="Yes" name="RadioGroup1"/>Yes<br />
<input type="radio" ID="Q1RB2" runat="server" value="No" text="No" name="RadioGroup1"/> No
<span id="Q1RB1Results" style="display:none"> <a href=#>Click here</a></span>
<span id="Q1RB2Results" style="display:none"> <a href=#>Click here</a></span>
</div>
My jQuery code that works for each individual radio button:
$("input[id$=Q1RB1]:radio").change(function () {
$("[id$=Q1RB1Results]").toggle();
});
$("input[id$=Q1RB2]:radio").change(function () {
$("[id$=Q1RB2Results]").toggle();
});
This is the If statement I'm trying to get to work. Amy I going about this the wrong way?
if ($("input[id$=Q1RB2]").is(":checked")) {
$("input[id$=Q1RB2]:radio").change(function () {
$("[id$=Q1RB2Results]").toggle();
});
});
Thanks for any thoughts/advice. I've tried a multitude of answers here in Stackoverflow and the 'net but can't seem to figure out what I'm doing wrong. :(
~V
Update: I put a sample form and the dialogue up on JSFiddle. http://jsfiddle.net/Valien/7uN6z/4/ I tried some of the solutions mentioned here and couldn't get them working so not sure what I'm doing wrong.
When you register an event listener in JQuery (.change, .click, .blur, etc.), the Javascript engine matches the selector and applies them at that point. With that in mind, you can rearrange your code (which is close to being right) to this, which should do the trick:
/* The function you're about to define applies to all radio button
inputs whose ID ends with Q1RB2 */
$("input[id$=Q1RB2]:radio").change(function()
{
/* Inside the change function, $(this) refers to the instance that
was changed. So, this checks to see if the instance that was just
changed is currently checked, after being changed. */
if ($(this).is(":checked"))
{
// If that was the case, then toggle the item
$("[id$=Q1RB2Results]").toggle();
}
});
Try this:
$('input:radio[name=RadioGroup1]').change(function(){
var show = "#" + $(this).attr('id') + 'Results';
$('#Question1 span').hide();
$(show).show();
});
I believe this is what you need:
// declare common variables so it's easier to target
var question = $("#Question1"),
group = question.find("input[name='RadioGroup1']"),
span = question.find("span");
// change listener for each radio button group
group.click(function(){
var id = $(this).attr("id"); // get the radio button id for reference
span.each(function(){ // loop through each span and check which one to hide/show
var item = $(this);
if (item.attr("id")===id+"Results") { item.show(); } else { item.hide(); }
});
});