I have a page with a jqGrid in it. Is has to be multiselect:false because I have to allow only one row to be selected, but I also need to select multiple rows (i.e. I want to have many rows marked but only one active).
So I've created a grid whith multiselect:false and a checkbox row with formatter: 'checkbox'
I've also created a master checkbox in the collumn header (the 'name' of the collumn in the colNames is <input id="cbSelectAll" type="checkbox">)
To change all the rows at once when the header is clicked I've created the function:
$('#cbSelectAll').click(function (e) {
var valor = $(this).is(':checked');
$.each($('#grid input[type="checkbox"]'), function (idx, elm) {
var id = $(elm).closest('tr').attr('id');
var cb = $('#' + id + ' td').children().first();
$(cb).attr('checked', valor);
selectedRows[id] = valor;
});
/* other non relevant code */
});
Now that's my problem.
This function works nicelly when I try to unselect the checkbox's but when i try to select then it only works in the first time. On the subsequent clicks the checked attribute is changed but the box is not visually changed.
Instead of attr, try using prop
Please have a look at this similar issue
Related
I have a Listbox that I need refreshed after a user selects an option in DropdownList.
Image is self explanatory. If one selects Department -> load list of departmetns in Listbox, if one selects Vat Rate refresh/load list of vat rates into the listbox below. (Default department list is loaded on page load). I am currently attempting this with trigger("chosen:updated") and having no luck refreshing listbox. Here is my code for that functionality.
$(function () {
$("#SelectFilter").change(function () {
if (document.getElementById('SelectFilter').value == 1) //dropdownlist
{
//empty listbox
$('#SelectItems').empty();
//append new list to listbox
$.each(data.Departments, function (index, element) {
$('#SelectItems').append('<option value="' + element.Value + '">'
+ element.Text + '</option>');
});
//refresh
$('#SelectItems').trigger("chosen:updated");
}
if (document.getElementById('SelectFilter').value == 2)
{
$('#SelectItems').empty();
$.each(data.VatRates, function (index, element) {
$('#SelectItems').append('<option value="' + element.Value + '">'
+ element.Text + '</option>');
});
$('#SelectItems').trigger("chosen:updated");
}
});
});
Recognising the selected value from the dropdownlist isnt an issue, that works fine. Listbox is currently not getting updated/refresh with new selection. And I cannot figure out were I am going wrong with this.
Try to put all your code for creating the list into a function, and then bind an event on chosing one of the selected items to call this function which generates a new list instead of using .trigger(). If you provide the HTML part as well, I'll post example code soon.
It's not clear to me if you have a problem with recognizing the selected value, or with populating the secondary select tag, or with the initial loading of the data. So I am providing an example of the three steps.
First, to detect the selected value, you need to provide a .change() handler and extract the selected value with .val(). Something similar to this:
$("#SelectFilter").change( function() {
var v = $(this).val();
if (v=="value1") {
} else if (v=="value2") {
} else {
}
});
then each of the changes detected has to refresh the contents of the secondary select tag, something as simple as this...
$("#SelectItems").empty();
['first item','second item','troisième'].forEach( (v,i) =>
$("#SelectItems").append($("<option>").val("item"+i).text(v))
);
}
And finally triggering the initial load should be as simple as triggering a change event
$("#SelectFilter").change();
I have put all the steps together in this fiddle https://jsfiddle.net/mud9u8yL/6/
The table involves a dropdown box and a normal <td> with a value. When onChange of the dropdown, the specific <td> must change to another dropdown. I've used jQuery to implement the function, but while I change the dropdown for the first row, the change is happening for the entire table. I just need the change to happen for the single row where the onChange function has been called.
$('td:nth-child(11),th:nth-child(11)').hide();
$('td:nth-child(10),th:nth-child(10)').show();
is used to hide and show the 10th and 11th columns.
doc.ready function() :
$(document).ready(function() {
$('td:nth-child(11),th:nth-child(11)').show();
$('td:nth-child(10),th:nth-child(10)').hide();
// ...
onChange function used :
$(document).on('change','.mySelect', function(event) {
event.preventDefault();
$('td:nth-child(11),th:nth-child(11)').hide();
$('td:nth-child(10),th:nth-child(10)').show();
//$(this).closest("td").show();
var _this = $(this);
var id =_this.val();
var statusValue = id;
$.get('AssignedTo', { statusVal : statusValue }, function(response) {
var select = _this.closest("tr").find("select[name='assigned']");
/* var select = $('#assigned'); */
select.find('option').remove();
$.each(response, function(index, value) {
$('<option>').val(value).text(value).appendTo(select);
});
});
});
Rather than using nth-child, consider using eq() - it's cleaner and doesn't come with some of the specificity issues of nth-child.
To get all <td> elements in the "changed" row, you can get the parent<td> by doing .closest("td") and select all of its siblings using .siblings("td")
To include the original one (and not only siblings), you'd use .addBack().
Finally, now that we have all the cells in the row, select the one you want using eq().
Put all together, it looks like this:
//Select the 11th cell in the row
var $cell = $(this).closest('td').siblings('td').addBack().eq(10);
Or, you could get the parent and choose all its children (instead of siblings) using .closest("tr") and children():
//Select the 11th cell in the row
var $cell = $(this).closest("tr").children("td").eq(10);
I've got two datatables and there is a dropdown created in the second one with data from the first. I've created a jsbin here
If you add a couple of instructions to the first table (add any text and then click Add Instruction) - then click on the Load Copied Data button, you will see the dropdown box is populated from the first table.
If I do:
$('#btnTest').on('click', function (e) {
var tsor = $('#tblSORSInstall').dataTable();
var ins = tsor.fnGetData();
alert(ins);
});
It basically gives me the html for the dropdown - how do I get which value they have chosen? I was thinking of having a hidden column and updating that on the onchange of the dropdown, but is there a better way?
Thanks in advance
You may use jQuery.map() to generate an array of selected text/value, like below.
$('#btnTest').on('click', function (e) {
//var tsor = $('#tblSORSInstall').dataTable();
var ins = $('#tblSORSInstall').find("tbody select").map(function() {
return $(this).find(":selected").text() // get selected text
//return $(this).val() // get selected value
}).get()
alert ( JSON.stringify(ins, null, 2) )
});
Here is your JS Bin - updated
Using tsor.fnGetNodes() you can get all table row nodes, then you can loop through those and get the select values.
Final code will look something like
$('#btnTest').on('click', function (e) {
var tsor = $('#tblSORSInstall').dataTable();
var ins = tsor.fnGetData();
var a = tsor.fnGetNodes();
$.each(tsor.fnGetNodes(), function (index, value) {
alert($(value).find('select').val());
});
});
I have two multiple select2 boxes, Box1 options are populated dynamically,when i select any option from this select box, it should get added to the new Box2. This scenario is working as required. Problem i am facing is. When i remove any selected item from the Box1, i am able to remove it from Box2. But if that item is selected in Box2 it still remains.
Ex: A,B,C are selected values in Box 1, Box2 gets populated with A,B,C. If i select B,c in Box 2 and if i remove B from Box1. My Box2 items will now be AC. But B,C will still remain selected in Box2.
Can anyone help me in solving this tricky problem.
$("#Box1").on("change", function() {
var box1List = $('#Box1').val();
$('#Box2').empty();
for (var key in box1List) {
var valueField = box1List[key];
var textField = $("#Box1 > option[value='"+valueField+"']").text();
$("#Box2").append($('<option>', {value: valueField, text: textField}));
}
});
$("#Box1").on("select2-removed", function(e) {
console.log("removed val=" + e.val + " choice=" + e.choice.text);
$('#Box2 option[value="'+e.val+'"]').remove();
});
After you alter the child <option> elements of a Select2 <select> element, you should call .change() on it to get it to update its display.
$('#Box2').change();
But in your case, you probably also want to restore the value of the Select2 after you remove and re-add the options.
$("#Box1").on("change", function() {
var val = $('#Box2').select2('val');
$('#Box2').empty();
$.each($('#Box1').select2('data'), function(i, item) {
$("#Box2").append($('<option>', {value: item.id, text: item.text}));
});
$('#Box2').select2('val', val);
});
When you use .select2('val', val) to set the value, you do not need to call .change().
jsfiddle
I have referenced from the post of Pierre de LESPINAY
Glideh. And I tried to apply to my project.
new_data = $.grep($('#my_input').select2('data'), function (value) {
return value['id'] != id_to_remove;
});
$('#my_input').select2('data', new_data);
It worked fine.
I have an editable Kendo Grid that may have a column with a checkbox to change a boolean value. I have used this solution proposed by OnaBai that is working perfectly!
The only problem is that the checkbox value change is too slow. When user clicks it, it takes about 1 second to change. I realize that the dataItem.set() method is responsible by this delay.
My grid has a considerable amount of data. About 30-40 columns and 300+ lines. It is defined as follows:
$("#mainGrid").kendoGrid({
dataSource: dataSource,
pageable: false,
sortable: true,
scrollable: true,
editable: true,
autoBind: false,
columnMenu: true, // Cria o menu de exibição de colunas
height: getGridHeight(),
toolbar: [/* hide for brevity */],
columns: [/* hide for brevity */],
dataBound: function() { /* hide for brevity. */},
edit: function() { /* hide for brevity. */}
});
Another detail is that, when dataItem.set() is called, it calls dataBound() event but that is not causing the delay. Grid's edit() method is not being called on this process. I don't know if worths to post dataSource code.
I would suggest using the approach from this code library article when it comes to use checkboxes. It does not use the set methods of the model and still works the same way. Even with 2000 records on a single page CheckAll will work flawlessly.
I have found an alternative way for doing what OnaBai proposed and it's working better.
// This is the grid
var grid = $("#mainGrid").data("kendoGrid");
// .flag is a class that is used on the checkboxes
grid.tbody.on("change", ".flag", function (e)
{
// Get the record uid
var uid = grid.dataItem($(e.target).closest("tr")).uid;
// Find the current cell
var td = $(e.target).parent().parent();
// This opens the cell to edit(edit mode)
grid.editCell(td);
// This ones changes the value of the Kendo's checkbox, that is quickly shown,
// changed and then hidden again. This marks the cell as 'dirty' too.
$(td.find("input")[0]).prop("checked", $(e.target).is(":checked") ? "checked" : null).trigger("change").trigger("blur");
}
Should try something like this:
I'll set the column with the Edit button to look like this:
columns.Command(command => {command.Edit().HtmlAttributes(new { id = "btnEdit_" + "${Id}" }); }).Width(100).Hidden(true);
And have it where clicking into the first column (I have an image with a hyperlink) uses an onclick function to programmatically click the Edit button, click the checkbox, then click the Update button. Probably more "old school", but I like knowing it is following the order I would be doing if I were updating it, myself.
I pass in the object ("this"), so I can get the row and checkbox when it appears, the new status as 0 or 1 (I have some code that uses it, not really necessary for this demo, though, so I'm leaving that part out of my function for simplicity), and the ID of that item:
columns.Bound(p => p.IsActive).Title("Active").Width(100).ClientTemplate("# if (IsActive == true ) {# <a href=javascript:void(0) id=btnActive_${Id} onclick=changeCheckbox(this, '0', ${Id}) class='k-button k-button-icontext k-grid-update'><img style='border:1px solid black' id=imgActive src=../../Images/active_1.png /></a> #} else {# <a href=javascript:void(0) id=btnActive_${Id} onclick=changeCheckbox(this, '1', ${Id}) class='k-button k-button-icontext k-grid-update'><img style='border:1px solid black' id=imgActive src=../../Images/active_0.png /></a> #}#");
function changeCheckbox(obj, status, id) {
var parentTr = obj.parentNode.parentNode;
$('[id="btnEdit_' + id + '"]').click();
parentTr.childNodes[5].childNodes[0].setAttribute("id", "btnUpdate_" + id); // my Update button is in the 6th column over
parentTr.childNodes[0].childNodes[0].setAttribute("id", "chkbox_" + id);
$('[id=chkbox_' + id + ']').click().trigger("change");
$('[id=chkbox_' + id + ']').blur();
var btnUpdate = $('[id="btnUpdate_' + id + '"]');
$('[id="btnUpdate_' + id + '"]').click();
}
Code above assumes, of course, the checkbox is in the first column. Otherwise, adjust the first childNodes[0] on that chkbox setAttribute line to the column it sits in, minus one because it starts counting from zero.
I did a solution much like #DontVoteMeDown. But I have a nested grid (master / detail) so I get the parent grid from the event parameter. Also I just trigger a click-event on the checkbox.
$("#grid .k-grid-content").on("change", "input.chkbx", function (e) {
// Get the parent grid of the checkbox. This can either be the master grid or the detail grid.
var parentGrid = $(e.target).closest('div[data-role="grid"]').data("kendoGrid");
// Get the clicked cell.
var td = $(e.target).closest("td");
// Enter the cell's edit mode.
parentGrid.editCell(td);
// Find the checkbox in the cell (which now is in "edit-mode").
var checkbox = td.children("input[type=checkbox]");
// Trigger a click (which will toggle check/uncheck).
checkbox.trigger("click");
});