I have a DataTable called Branches which has three columns: Name, Code and Email (along with an ID column hidden to users). It originally has an Edit button on top, and only after clicking on a row can the user click on the button to open a dialog box with the fields populated and edit them. Now however I need to change it so that each row has its own Edit button, therefore removing the need to click on the row first.
So now I have an Edit button for each row in a DataTable, but I can't pass the data for that particular row besides the Index number. The relevant blocks of code are below (unless I missed something, please tell me if I have):
var txtName2 = $("#txtName2"); //For Update
var txtCode2 = $("#txtCode2");
var txtEmail2 = $("#txtEmail2");
var dialog;
var tblBranch = $("#tblBranches");
var branchList;
var selectedIndex;
branchList = response.branches;
var data = { "aaData": [] };
$.each(response.branches, function (i, item) {
data.aaData.push({
"id": item.id,
"name": item.name,
"code": item.code,
"email": item.email,
"action": "<button> class='btnUpdate' type='button' onClick='testUpdateButton(" + i + ")'</button>"
});
});
function testUpdateButton(index, name, code, email) {
//alert(index);
selectedIndex = tblBranch.row(this).index();
var selectedName = tblBranch.row(index).name;
var selectedCode = tblBranch.row(index).code;
var selectedEmail = tblBranch.row(index).email;
//alert(name);
onBtnUpdateClicked(index, name, code, email);
}
function onBtnUpdateClicked(index, name, code, email) {
if (branchList != null && branchList.length > 0) {
var selectedItem = branchList[selectedIndex];
txtName2.val(selectedItem.name);
txtCode2.val(selectedItem.code);
txtEmail2.val(selectedItem.email);
dialog = $("#dialog-form-update").dialog("open");
}
}
When I only pass in the index number 'i' at the button and not the name, code or email, the alert(index) under testUpdateButton displays the correct index number of the selected row, therefore confirming it can get the index number, but not the other three columns (the alert(name) displays nothing).
So I've tried passing all four fields at the button like such:
"action": "<button> class='btnUpdate' type='button' onClick='testUpdateButton(" + i + ", " + item.name + ", " + item.code + ", " + item.email + ")'</button>"
but it only gives me an error: "Uncaught SyntaxError: missing ) after argument list" when I inspect the page in Chrome. I can't see where the missing bracket should be.
Basically, I can obtain the index number but cannot use it to get the corresponding name, code and email.
For reference, here is the function that's the closest thing to a solution I had earlier - this would pass all the row data and load the Editing dialog box with the input fields populated whenever I clicked anywhere on the row itself. It was modified from the previous "Click on row first" version, though I merely added the onBtnUpdateClicked function. Not ideal, but at least it did what it should.
$("#tblBranches tbody").on('click', 'tr', function () {
selectedIndex = tblBranch.row(this).index();
onBtnUpdateClicked();
});
Any help is much appreciated.
Since you are able to get the index of row, you can use this to get other values. Try something like this
function testUpdateButton(index){
//alert(index);
selectedIndex = index;
var name=$("table tr").eq(index).children('td').eq(1).text();
var email=$("table tr").eq(index).children('td').eq(2).text();
alert(name);
alert(email);
onBtnUpdateClicked(index, name, email);
}
A woorking fiddle to get these values is https://jsfiddle.net/shoaibakhter/atpgdofh/19/. This is not a complete solution, but yes this will help you to get other values, which you can pass in your onBtnUpdateClicked function. You have to change the functions as per your table structure and in your onBtnUpdateClicked use these values as below-
function onBtnUpdateClicked(index, name, email) {
if (branchList != null && branchList.length > 0) {
var selectedItem = branchList[index];
txtName2.val(name);
txtEmail2.val(email);
dialog = $("#dialog-form-update").dialog("open");
}
}
Hope this will help you.
Related
I have a ASP.Net MVC Kendo Grid with checkbox selection, as the documentation I added the checkbox using columns.Select().Width(50); as, then I want to fill an array of selected checkboxes inside of onChange function with javascript as:
Note: the stations array already have some values I.E [1,2,3], so I want to add new values in the next script
function onChange(e) {
const grid = $("#grid").data("kendoGrid");
var items = grid.items();
let ids = '';
grid.select().each(function() {
if (ids === '')
ids = grid.dataItem(this).StationId.toString();
else
ids = ids + ',' + grid.dataItem(this).StationId.toString();
stations.push(grid.dataItem(this).StationId);
})
}
The problem is on each check it is adding all existing checked checkboxes, I have no way to do something like if(checkbox is not checked) do a pop instead a push.
How can I check if clicked checkbox is checked or not in order to implement push or pop logic?
The select method will return all rows that are currently selected. If you need to figure out which is the checkbox that the user clicked last, you can probably toggle a class when the checkbox is checked/unchecked
function onChange(e) {
const grid = e.sender;
var items = grid.items();
let ids = '';
grid.select().each(function(idx,itm) {
$(itm).find("input").hasClass("checkedFlag") ?
kendoConsole.log(grid.dataItem(itm).ProductName + " was checked") :
kendoConsole.log(grid.dataItem(itm).ProductName + " was NOT checked");
})
var selected = $.map(this.select(), function(item) {
return $(item).text();
});
kendoConsole.log("Selected: " + selected.length + " item(s), [" + selected.join(", ") + "]");
}
function onDataBound(arg) {
$("input.k-select-checkbox").change(function(){
$(this).toggleClass("checkedFlag")
})
kendoConsole.log("Grid data bound");
}
If you are interested in only the Id's of the selected items then the Grid exposes a selectedKeyNames method, that you could use instead.
The change event of the Kendo grid will fire when the user selects or deselects a table row or cell in the grid (documentation), but it does not provide us with which rows are selected or deselected.
What you will need to do is store the selected items outside of the grid, compare it to the results of the select method in the change event, then store the updated results.
Something along these lines:
var selectedRecords = [];
function onChange(e) {
var updatedSelectedRecords = e.sender.select();
if (selectedRecords) {
var recordsSelected = updatedSelectedRecords.filter(record => !selectedRecords.includes(record)).map(record => record.StationId.toString());
stations.push(...recordsSelected);
var recordsDeselected = selectedRecords.filter(record => !updatedSelectedRecords.includes(record));
// do something with deselected records?
}
selectedRecords = updatedSelectedRecords;
}
I have a table of data containing a checkbox that the user can select to either export the record or edit the record. For editing the checkbox has a data attribute that shows whether the specific set of data is editable (based on user-permissions).
I am trying to get a list of the checkbox values where the checkbox is checked AND the data attribute has a value "True".
In my view model I have the field:
public bool ShortageIsEditable {get;set;}
This is set in the view model mapper to either true or false depending on the status of the record and the permissions of the user.
In my view I have a table that has the following checkbox with data attribute for each record:
#(Html.Kendo().Grid(item.Shortages)
.Name(string.Format("ShortagesGrid_{0}", item.Id))
.Columns(columns =>
{
columns.Template(GetViewLink)
.Title("View")
.Width(38);
columns.Template(o => "<input type=\"checkbox\" name=\"selectedRequestId\" " + (o.IsSelected ? "checked=\"checked\"" : "") + "class=\"myCssCheckAllCheckBox\" value=\"" + o.ShortageNo + "\" data-iseditable=\"" + o.ShortageIsEditable + "\"/>")
.Width(30);
columns.Bound(o => o.ShortageNo)
.Title("Shortage #")
.Width(120);
...
When the user selected some records for edit (checked the checkboxes) and presses the Edit button, the following javascript/JQuery function is executed:
function submitGridSelectedItemsForEdit() {
$('#gridExportForm').attr('action', '/Requests/Shortage/MultiEditShortages');
$('#gridExportForm').attr('method', 'GET');
var chkdlist = $('input[name="selectedRequestId"]:checked');
var newlist = chkdlist.filter(function (el) {
return el.data("iseditable") === "True";
});
newlist.submit();
This will always crash on the line "return el.data("iseditable") === "True";".
I have also tried using the following, but this crashes on submitting the newlist array:
function submitGridSelectedItemsForEdit() {
$('#gridExportForm').attr('action', '/Requests/Shortage/MultiEditShortages');
$('#gridExportForm').attr('method', 'GET');
var chkdlist = $('input[name="selectedRequestId"]:checked');
var newlist = [];
for (var chk in chkdlist)
{
if (chk.data("isEditable") == true) {
newlist.push(chk);
}
}
if (newlist.length == 0) {
alert("Please select at least 1 request to Edit.");
}
else {
newlist.submit();
}
}
What is the easiest way to get the list of objects that is both checked and has a data-attribute value of "True"?
el in filter() callback is the dom element, not a jQuery object. LAso it is not the first argument of the callback it is the second.
So to use jQuery methods you need to wrap el in $()
var newlist = chkdlist.filter(function (_,el) {
return $(el).data("iseditable") === "True";
});
Or filter based on the attribute value as selector
var newlist = chkdlist.filter('[data-iseditable="True"]')
I have a table where in each row for each id we have 'Client' column. When a user clicks on the row he is able to change client. I am using jquery.dialog for this operation. When a dialog appears the user sees a dropdownlist with Clients. How I can make that after dialog appears, the user sees the current client as the selected item in the dropdown? I've tried as below:
onDblClickRow: function (row, $element) {
$.getJSON('/ManageProjects/GetAvaibleClients/', function (clients) {
if (clients.length == 0) {
$('#clientNameEdit').empty();
$('#clientNameEdit').append('<option value="0">Tasks</option>');
}
$.each(clients, function (index, clientt) {
$('#clientNameEdit').append("<option value='" + clientt.Value + "'>" + clientt.Text + "</option>");
});
})
var currentClient = row.clientName; // Client name from Row
$('#clientNameEdit select').val(currentClient); // Tried to set like that
}
but doesn't work
The value passed in to .val needs to be the clientt.Value and not the text name.
if you dont have the clientt.Value, then try something like:-
$("#clientNameEdit option[text=" + currentClient + "]").attr("selected", true);
And bring the setting of the select inside of the success function.
The following alteration to your code snippet should do the trick:
onDblClickRow: function (row, $element) {
$.getJSON('/ManageProjects/GetAvaibleClients/', function (clients) {
if (clients.length == 0) {
$('#clientNameEdit').empty();
$('#clientNameEdit').append('<option value="0">Tasks</option>');
}
$.each(clients, function (index, clientt) {
$('#clientNameEdit').append("<option value='" + clientt.Value + "'>" + clientt.Text + "</option>");
});
var currentClient = row.clientName; // Client name from Row
$('#clientNameEdit').val(currentClient); // Tried to set like that but doesn't work
});
As indicated above, if you do the currentClient = row.clientName outside the success of the ajax call, it will probably fire before the dropdown is populated and therefore not have any effect.
Secondly the jQuery selector '#clientNameEdit select' should only be '#clientNameEdit' as it refer to the dropdown itself and not it's parent.
In my own "ToDoList" where you can add tasks, delete them, and check/uncheck them with their corresponding checkboxes, and all the tasks are displayed in order by their corresponding categories, which in Django, is stored as a CharField.
However, there's a problem I'm noticing. When I am adding a new task that its category is new, the div that holds the category name is added at the bottom of my list instead of added in the place where it should go to make my categories in the list in Unicode order. And so, I'm wondering what I need to do to make my list in order when I add tasks at runtime instead of having to let Django render an ordered task list by clicking on the Refresh button.
Here's my JavaScript code; it uses jQuery (for simplicity, I'm only showing the function that's called after the POST request has been made when the user clicks on the "Add Task" button and there is a character in the "Task" input field):
$.post("process-request", {new_task: taskInput, category_of_task: categoryOfTask}, function () {
$.get("retrieve-actual-id-of-model-after-adding-task", {category_of_task: categoryOfTask}, function(data) {
newTask.attr("task_id", data.id_of_last_task_added);
if ($("#category__" + categoryOfTask).length == 0)
{
if ($("#category__").length == 0)
var newDiv = $("<div id=\"category__" + categoryOfTask + "\"><span>" + categoryOfTask + "</span>");
else
var newDiv = $("<br/><div id=\"category__" + categoryOfTask + "\"><span>" + categoryOfTask + "</span>");
$("#listOfThingsToDo").append(newDiv);
$("#listOFThingsToDO").append("</div>");
newDiv.show();
}
$("#category__" + categoryOfTask).append(newTask);
});
});
Here are a couple of images to show a better picture:
A category-based sorted list, as it is rendered by the Django template when the Refresh button is clicked and tasks do exist for the logged in user.
Unsorted List at runtime after I add a new task with a new category
Please let me know if you need to see additional code; just let me know what kind of code you need to see based on the jQuery code I got here.
You can sort the categories you already have and then use a $insertAfter or $prepend in case of the first sorted category.
Take a look on this working example based on the code you gave:
https://jsfiddle.net/e6g4fu84/
// ADDING A NEW TASK IN A NEW CATEGORY
categoryOfTask = "baa";
newtask = document.createElement("task");
$(newtask).html('<div><input type="checkbox"/><label>task foo inserted</label></div>');
// When you gonna add your new category holder add it like this:
if ($("#category__" + categoryOfTask).length == 0){
//Create your new Div just like you have done
if ($("#category__").length == 0)
var newDiv = $("<div id=\"category__" + categoryOfTask + "\"><span>" + categoryOfTask + "</span></div>");
else
var newDiv = $("<br/><div id=\"category__" + categoryOfTask + "\"><span>" + categoryOfTask + "</span></div>");
//But the trick happens when you will add your new category holder
//----------------------------------------------------------
//find all elements that have #category__X as id
categoriesElements = $("#listOfThingsToDo div[id*=category__]");
//And then add them on an array
categoriesNames = [];
$.each(categoriesElements, function(i, category){
categoriesNames.push($(category).attr("id").split("__")[1]);
});
//Add your new category to the group and sort
categoriesNames.push(categoryOfTask);
categoriesNames.sort();
//find where you should fit
putCategoryAfter = categoriesNames.indexOf(categoryOfTask) - 1;
//Then add it where it should be
if(putCategoryAfter == -1) //If it's the first of the list
$("#listOfThingsToDo").prepend(newDiv);
else{ //If it isn't the first find where it should be and insert it there
$(newDiv).insertAfter("#category__"+categoriesNames[putCategoryAfter]);
}
newDiv.show();
}
// And after all add your task to it
$("#category__" + categoryOfTask).append(newtask);
I comment the steps to clarify, hope i could help.
If this is what you are expecting just let me know. Best regards! :-)
What I'm trying to do is get one of my drop down list to change its contents whenever the selected item in another one cahnges. I have this code in my aspx file:
function ModifyDDLItems(id1, id2)
{
var ddlcontrolShown = document.getElementById(id1);
var ddlcontrolHidden = document.getElementById(id2);
if (ddlcontrolShown.options[ddlcontrolShown.selectedIndex].value == "DD1")
{
//Get number of items of hidden ddl
var length = ddlcontrolHidden.options.length;
//Clear items of shown ddl
ddlcontrolShown.options.length = 0;
//Add itmems of hidden ddl to shown ddl
for (i = 0; i < length; i++)
{
ddlcontrolShown.options.add
var newoption = document.createElement("option")
newoption.text = ddlcontrolHidden.options[i].text;
newoption.value = ddlcontrolHidden.options[i].text.value;
}
}
}
Now, i give it the front end ID's thru this:
protected void SetDD1ConfItems(GridViewRow gvRow, DataSet BaseConfItems)
{
DataView dvConfType = new DataView(BaseConfItems.Tables[0]);
DataSet dsTemp = BaseConfItems.Clone();
DropDownList ddlConfType2 = (DropDownList)form1.FindControl("ddlConfType2");
DropDownList ddlBA = (DropDownList)gvRow.FindControl("ddlBA");
DropDownList ddlConfType = (DropDownList)gvRow.FindControl("ddlConfType");
dvConfType.RowFilter = "ref_code = 'FAX' or ref_code = 'EEX' or ref_code = 'EPD'";
dsTemp.Tables.Clear();
dsTemp.Tables.Add(dvConfType.ToTable());
ddlConfType2.DataSource = dsTemp;
ddlConfType2.DataBind();
//ddlBA.Attributes["onchange"] = "function GetDDLD(" + ddlConfType.ClientID + ", " + ddlConfType2.ClientID + ") {ModifyDDLItems(id1, id2);}";
ddlBA.Attributes.Add("onchange", "ModifyDDLItems('" + ddlConfType.ClientID + "', '" + ddlConfType2.ClientID + "')");
}
When I run it, VS keeps on telling me that id1 and id2 are both null, it seems the id's aren't passed to the client properly.
I think you have code wrongly, the first mistake i found at a glance is,
You cannot find the controls inside gridview by using
gvRow.FindControl("ddlBA");
There may be multiple rows in GridView, so you have to find your controls in each Row as all of them will have different ClientIDs. First to try to replace the below code
gvRow.Rows[RowIndex].FindControl("ControlID");
ALso, it should be written in the some kind of loop in order to find the RowIndex value of the Grid.
Describe your exact requirement in brief. So, that i can help you in writing the proper code.