JQGrid Source not populating after delete - javascript

I am using a jqGrid that is set up in the $(document).ready like this:
jQuery("#list").jqGrid({
datatype: 'json',
colNames: ['ID', 'Note', 'Date Added'],
colModel: [
{ name: 'ID', index: 'ID', width: 60, key: true },
{ name: 'ContactNote', index: 'ContactNote', width: 300, cellattr: function (rowId, tv, rawObject, cm, rdata) { return 'style="white-space: normal;"'; } },
{ name: 'ContactDate', index: 'DateAdded', width: 100 }
],
mtype: 'POST',
viewrecords: true,
jsonReader: { repeatitems: false },
ignoreCase: true,
height: 450,
loadonce: false,
onSelectRow: function (id) { $('#ContactId').val(id); }
});
Here is the HTML of the page:
<div class="col-12">
<div class="ui-content-6 ui-widget-content ui-corner-all">
#using (Html.BeginForm())
{
<h3 class="ui-widget-header ui-corner-all">Enter account number</h3>
<div class="field-container">
#Html.LabelFor(o => o.AccountNumber)
#Html.TextBoxFor(o => o.AccountNumber)
</div>
<div class="form-submit">
<button id="btnSearchContactItems">Get Contact Items</button>
</div>
<h3 class="ui-widget-header ui-corner-all">Contact item list</h3>
<table id="list" class="scroll" cellpadding="0" cellspacing="0"></table>
<div class="form-submit">
<button id="btnRemoveContactItem" type="submit">Remove Selected Contact Item</button>
</div>
#Html.HiddenFor(o => o.ContactId)
#Html.ValidationSummary()
}
</div>
The btnSearchContactItems button has a click event:
$("#btnSearchContactItems").click(function () {
$("#list")
.jqGrid('setGridParam', { postData: { accountNumber: $('#AccountNumber').val() }, url: baseSearchURL })
.trigger('reloadGrid');
return false;
});
Here is the issue:
I am having the user enter in their account number and, on the btnSearchContactItems button click, fill in the grid with some notes. When one of the notes is selected and the btnRemoveContactItem button is clicked the action is called and the note is removed. The problem is that once the not is removed the grid empties. What I would like to happen is to have the grid reload with the data minus the row that was removed.
I swear, for the life of me, I cannot get the data to repopulate. I have tried firing the button click in the grid load, on page load, ect and still nothing. It will only fill the grid again if I physically click the button. Anyone have any thoughts?

How I suppose you don't want to sent any request to the server at the page start. To do this you can use datatype: "local" if you create the grid. You can set url: baseSearchURL at the time of creating of the grid. The parameter will be ignored with datatype: "local".
Now I go back to you main question: you can define postData option directly at the creating of the grid, but you should use functions (methods) as properties (see the answer for details):
postData: {
accountNumber: function () {
var account = $('#AccountNumber').val();
return account ? account : null;
}
}
The method accountNumber will be called every time if grid will be reloaded. So you can use
$("#btnSearchContactItems").click(function () {
$("#list").jqGrid('setGridParam', { datatype: "json" }}).trigger('reloadGrid');
return false;
});
If you want you can additionally set inside of click handler datatype: "local" if $('#AccountNumber').val() is empty.
If you really don't want to send any accountNumber property to the server it the value is null or "" you can use serializeGridData in the following form
serializeGridData: function (postData) {
var propertyName, propertyValue, dataToSend = {}, val;
for (propertyName in postData) {
if (postData.hasOwnProperty(propertyName)) {
propertyValue = postData[propertyName];
val = $.isFunction(propertyValue) ? propertyValue() : propertyValue;
if (propertyName !== "accountNumber" || val) {
// don't send "accountNumber" with empty value
dataToSend[propertyName] = val;
}
}
}
return dataToSend; // ?? probably you can use JSON.stringify(dataToSend);
}
(see the answer for details)
Additionally I would recommend you to set gridview: true to improve performance of the grid and add rowNum: 10000. jqGrid is designed to display paged data. You don't use pager option, but the default value of rowNum is 20. So without setting rowNum: 10000 jqGrid will display only the first 20 rows of data. It's not what you want.

Related

dropdown not being populated in filter toolbar in jquery grid

I have referred this link and also this one link Both are Oleg's solutions to the problem. I used the same solution but the drop down doesn't populate with the values except for 'All'
I placed the code in load complete and I see the values when you call the 'setSearchSelect' function but only 'All' shows up in the dropdown.
Here's the code-
setupGrid: function (grid, pager) {
$(grid).jqGrid({
datatype: 'local', // set datatype to local to not inital load data
mtype: 'GET',
url: swUrl + ptSearchDashboardUrl,
colNames: colNames,
colModel: colModel,
altRows: false,
pager: $(pager),
loadonce: true,
sortable: true,
multiselect: true,
viewrecords: true,
loadComplete: function (data) {
//setSearchSelect.call($grid, 'RequestType');
//setSearchSelect.call($grid, 'Country');
},
onSelectRow: function() {
var checkedIDs = $(this).jqGrid('getGridParam', 'selarrrow');
if (checkedIDs.length > 0)
$("#ReassignBtn").show();
else
$("#ReassignBtn").hide();
}
}).navGrid(pager, { add: false, edit: false, del: false }).trigger('reloadGrid', [{ current: true }]);
setSearchSelect.call($grid, 'RequestType');
setSearchSelect.call($grid, 'Country');
$grid.jqGrid("setColProp", "Name", {
searchoptions: {
sopt: ["cn"],
dataInit: function(elem) {
$(elem).autocomplete({
source: getUniqueNames.call($(this), "Name"),
delay: 0,
minLength: 0,
select: function(event, ui) {
var $myGrid, grid;
$(elem).val(ui.item.value);
if (typeof elem.id === "string" && elem.id.substr(0, 3) === "gs_") {
$myGrid = $(elem).closest("div.ui-jqgrid-hdiv").next("div.ui-jqgrid-bdiv").find("table.ui-jqgrid-btable").first();
if ($myGrid.length > 0) {
grid = $myGrid[0];
if ($.isFunction(grid.triggerToolbar)) {
grid.triggerToolbar();
}
}
} else {
// to refresh the filter
$(elem).trigger("change");
}
}
});
}
}
});
$(grid).jqGrid('filterToolbar', {stringResult:true, searchOnEnter:true, defaultSearch:"cn"});
}
This is from the UI - I can only see one option value even though there are many.
<td class="ui-search-input">
<select name="RequestType" id="gs_RequestType" style="width: 100%;">
<option value="">All</option>
</select>
</td>
The code which you use getUniqueNames which uses .jqGrid("getCol", columnName) to get the data from the column. On the other side you use datatype: 'local' to create empty grid. The calls setSearchSelect.call($grid, 'RequestType');, setSearchSelect.call($grid, 'Country'); and getUniqueNames.call($(this), "Name") will be made before the grid will be filled with data. Thus you fill set empty set of select elements.
I suppose that you change later the datatype to "json" or "xml" and reload the grid. Only after your get response from the server you will ba able to fill the select values. I would suggest you to use beforeProcessing, which will be called after loading the data from the server, but before processing of the data. You can modify getUniqueNames and setSearchSelect so that it get the data from the input data directly and calls setColProp. Finally you should call destroyFilterToolbar and call filterToolbar once more to create the filter toolbar with the current data.

load jqGrid on button click but it fails on second time

I'm using jqGrid to display data from database. There are 2 textboxes to input the criteria. After inputting the criteria and clicking the Show button, jqGrid is shown to the page.
The second time I clicked the Show button with a different set of criteria entered nothing happens. It still shows data from the first click. How do I solve this?
View:
#section styles {
<link href="~/Content/themes/redmond/jquery-ui.css" rel="stylesheet" />
<link href="~/Content/jquery.jqGrid/ui.jqgrid.css" rel="stylesheet" />
}
<h2>Index</h2>
<p class="form-inline">
Ext: <input type="text" class="form-control" id="extUsed" />
Date: <input type="text" class="form-control" id="startOfCall" readonly="readonly" />
<button class="btn btn-primary" id="btnShow">Show</button>
</p>
<table id="grid"></table>
<div id="pager"></div>
#section scripts {
<script src="~/Scripts/i18n/grid.locale-en.js"></script>
<script src="~/Scripts/jquery.jqGrid.min.js"></script>
<script>
var firstClick = true;
$(function () {
$("#startOfCall").datepicker();
$("#btnShow").click(function (e) {
e.preventDefault();
if (!firstClick) {
$("#grid").trigger("reloadGrid");
} else {
$("#grid").jqGrid({
mtype: "GET",
url: "#Url.Content("~/CallTransaction/GetCallTransactionList")",
datatype: "json",
colNames: ["Ext Used", "Start of Call", "Destination Number"],
colModel: [
{ name: "ExtUsed", index: "ExtUsed" },
{ name: "StartOfCall", index: "StartOfCall", formatter: "date", formatoptions: { srcformat: 'd/m/Y', newformat: 'd/m/Y' } },
{ name: "DestinationNumber", index: "DestinationNumber" }
],
postData: {
"CallTransaction.ExtUsed": $("#extUsed").val(),
"CallTransaction.StartOfCall": $("#startOfCall").val()
},
pager: jQuery("#pager"),
rowNum: 10,
rowList: [10, 25, 50],
height: "100%",
caption: "Call Transaction",
autowidth: true,
//sortname: "ExtUsed",
sortable: true,
viewrecords: true,
emptyrecords: "No records to display",
});
$("#grid").jqGrid('navGrid', '#pager', { edit: false, add: false, del: false, search: false });
}
firstClick = false;
});
});
</script>
}
Controller:
public JsonResult GetCallTransactionList(CallTransaction callTransaction, string sidx, string sord, int page, int rows)
{
int pageIndex = page - 1;
int pageSize = rows;
var callTransactionResult = db.Search(callTransaction);
int totalRecords = callTransactionResult.Count();
var totalPages = (int)Math.Ceiling((float)totalRecords / (float)rows);
if (sord.ToUpper() == "DESC")
{
callTransactionResult = callTransactionResult.OrderByDescending(ct => ct.ExtUsed).ToList();
callTransactionResult = callTransactionResult.Skip(pageIndex * pageSize).Take(pageSize).ToList();
}
else
{
callTransactionResult = callTransactionResult.OrderBy(ct => ct.ExtUsed).ToList();
callTransactionResult = callTransactionResult.Skip(pageIndex * pageSize).Take(pageSize).ToList();
}
var jsonData = new
{
total = totalPages,
page,
records = totalRecords,
rows = callTransactionResult
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
It's important to understand that the current code set one value of postData during creating the grid. The value of postData parameter will be object with properties evaluated at the moment of creating of the grid.
To fix the code you need use function as the value of postData properties:
postData: {
"CallTransaction.ExtUsed": function () { return $("#extUsed").val(); },
"CallTransaction.StartOfCall": function () { return $("#startOfCall").val(); }
}
See the answer for more details. For understanding: jqGrid uses jQuery.ajax internally and jQuery.ajax uses jQuery.param helper function to process the data parameter (construction using postData) and jQuery.param execute functions if it is the properties of data (postData).
Additionally I would strictly recommend you to use gridview: true option in all your grids (see the answer), add autoencode: true to interpret the input data as the data instead of HTML fragments (it's the default behavior) and to use pager: "#pager" instead of pager: jQuery("#pager").
I recommend you to remove all index properties from colModel and to consider to include additional id property in the data returned from the server with an unique values which come from the database. If some column of the grid already contains the unique value you can add key: true property to the definition of the corresponding column. The reason of such changes is easy to understand if you know that jqGrid have to assign id attribute to every row of grid. The value of id attribute must be unique. The value, used as rowid in the documentation, will be used in the most callbacks of jqGrid to identify the row. The same value will be send to the server if you will implement editing of data later. If you don't specify any rowid in the input data jqGrid have to assign some other value to id. The default value will be 1,2,3... On the other side if you load the data from the database you have native ids of the rows. The usage of the native ids can "simplify your live" in the future.

Extending kendo multiselect and working with MVVM

I'm trying to extend a kendo multiselect so that it has a default data source as well as templates. It's all working except the pre-loaded values in the MVVM object. When I start updating the exented multiselect, the value of the MVVM gets updated, the initial items are just not pre-loaded:
kendo.ui.plugin(kendo.ui.MultiSelect.extend({
init: function(element, options) {
var ds = new kendo.data.DataSource({
type: "json",
serverFiltering: true,
transport: {
read: {
url: "/SecurityEntities",
dataType: "json"
},
parameterMap: function(data) {
return {
prefixText: '',
count: 5,
getUsers: true,
getGroups: false
};
}
},
schema: {
data: function(data) {
console.log($.parseJSON(data));
return $.parseJSON(data);
}
}
});
options = options == null ? {} : options;
options.itemTemplate = "...";
options.tagTemplate = "...";
options.dataSource = ds;
kendo.ui.MultiSelect.fn.init.call(this, element, options);
},
options: {
name: 'EntityMultiSelect'
}
}));
kendo.data.binders.widget.entitymultiselect =
kendo.data.binders.widget.multiselect;
Then my html is:
<div data-bind="value: machine.Managers" data-role="entitymultiselect"
data-delay="400" data-animation="false"
data-placeholder="Select users to notify"></div>
And I am binding the whole container to the page's viewModel object.
I've seen other people have issues with this very problem and added the
kendo.data.binders.widget.entitymultiselect =
kendo.data.binders.widget.multiselect;
(And yes that does seem like a bug)
But it still doesn't work.
When there are already values in Machine.Managers, it doesn't load them. However, if I add values to the multiselect, they get added to Machine.Managers .
EDIT:
I've added a live example
At least in your demo it's a trivial problem: your data-value-field is wrong. As a result, the binder can't match the selected elements.
Instead of
<div data-role="entitymultiselect"
data-bind="value: selected"
data-value-field="ProductId"></div>
you need
<div data-role="entitymultiselect"
data-bind="value: selected"
data-value-field="ProductID"></div>
(working demo)
Since you're not defining the value field in the code in your question, it might be the same issue.

kendoui: How to display foreign key from remote datasource in grid

i have a kendoui grid which list claims. one of the columns is lenders which is a foreign key reference to the lenders table. what i want is to be able to display the lender name in the grid instead of its id reference.
ive setup the lenders datasource as follows
var dsLenders = new kendo.data.DataSource({
transport: {
read: {
url: "../data/lenders/",
dataType: "jsonp"
},
parameterMap: function(options, operation) {
if (operation === "read") {
return options;
}
}
}
});
and the grid looks like this
$("#gridClaims").kendoGrid({
dataSource: claimData,
autoSync:true,
batch: true,
pageable: {
refresh: true,
pageSizes: true
},
filterable: true,
sortable: true,
selectable: "true",
editable: {
mode: "popup",
confirmation: "Are you sure you want to delete this record?",
template: $("#claimFormPopup").html()
},
navigable: true, // enables keyboard navigation in the grid
toolbar: ["create"], // adds insert buttons
columns: [
{ field:"id_clm", title:"Ref", width: "80px;" },
{ field:"status_clm", title:"Status", width: "80px;" },
{ field:"idldr_clm", title:"Lender", values: dsLenders },
{ field:"type_clm", title:"Claim Type"},
{ field:"value_clm", title:"Value", width: "80px;", format:"{0:c2}", attributes:{style:"text-align:right;"}},
{ field:"created", title:"Created", width: "80px;", format: "{0:dd/MM/yyyy}"},
{ field:"updated", title:"Updated", width: "80px;", format: "{0:dd/MM/yyyy}"},
{ field:"user", title:"User" , width: "100px;"},
{ command: [
{text: "Details", className: "claim-details"},
"destroy"
],
title: " ",
width: "160px"
}
]
});
however its still displaying the id in the lenders column. Ive tried creating a local datasource and that works fine so i now is something to do with me using a remote datasource.
any help would be great
thanks
Short answer is that you can't. Not directly anyway. See here and here.
You can (as the response in the above linked post mentions) pre-load the data into a var, which can then be used as data for the column definition.
I use something like this:-
function getLookupData(type, callback) {
return $.ajax({
dataType: 'json',
url: '/lookup/' + type,
success: function (data) {
callback(data);
}
});
}
Which I then use like this:-
var countryLookupData;
getLookupData('country', function (data) { countryLookupData = data; });
I use it in a JQuery deferred to ensure that all my lookups are loaded before I bind to the grid:-
$.when(
getLookupData('country', function (data) { countryLookupData = data; }),
getLookupData('state', function (data) { stateLookupData = data; }),
getLookupData('company', function (data) { companyLookupData = data; })
)
.then(function () {
bindGrid();
}).fail(function () {
alert('Error loading lookup data');
});
You can then use countryLookupData for your values.
You could also use a custom grid editor, however you'll probably find that you still need to load the data into a var (as opposed to using a datasource with a DropDownList) and ensure that the data is loaded before the grid, because you'll most likely need to have a lookup for a column template so that you're newly selected value is displayed in the grid.
I couldn't quite get ForeignKey working in any useful way, so I ended up using custom editors as you have much more control over them.
One more gotcha: make sure you have loaded your lookup data BEFORE you define the column. I was using a column array that was defined in a variable I was then attaching to the grid definition... even if the lookup data is loaded before you use the grid, if it's defined after the column definition it will not work.
Although this post past 2 years, I still share my solution
1) Assume the api url (http://localhost/api/term) will return:
{
"odata.metadata":"http://localhost/api/$metadata#term","value":[
{
"value":2,"text":"2016-2020"
},{
"value":1,"text":"2012-2016"
}
]
}
please note that the attribute name must be "text" and "value"
2) show term name (text) from the foreign table instead of term_id (value).
See the grid column "term_id", the dropdownlist will be created if added "values: data_term"
<script>
$.when($.getJSON("http://localhost/api/term")).then(function () {
bind_grid(arguments[0].value);
});
function bind_grid(data_term) {
$("#grid").kendoGrid({
dataSource: ds_proposer,
filterable: true,
sortable: true,
pageable: true,
selectable: "row",
columns: [
{ field: "user_type", title: "User type" },
{ field: "user_name", title: "User name" },
{ field: "term_id", title: "Term", values: data_term }
],
editable: {
mode: "popup",
}
});
}
</script>
For those stumbling across this now, this functionality is supported:
https://demos.telerik.com/aspnet-mvc/grid/foreignkeycolumnbinding

How do I create a delete button on every row in slickgrid with confirmation?

As the title said it, how do I do it?, I am using this button created by jiri:
How do i create a delete button on every row using the SlickGrid plugin?
when I add an if(confirmation(msg)) inside the function it repeats me the msg ALOT
maybe its because i refresh-ajax the table with each modification.
ask me if you need more info, I am still noob here in stackoverflow :P
(also if there is someway to "kill" the function)
here is the button, iam using(link) i added the idBorrada to check whetever the id was already deleted and dont try to delete it twice, also here is a confirm, but when i touch cancel it asks me again.
$('.del').live('click', function(){
var me = $(this), id = me.attr('id');
//assuming you have used a dataView to create your grid
//also assuming that its variable name is called 'dataView'
//use the following code to get the item to be deleted from it
if(idBorrada != id && confirm("¿Seguro desea eleminarlo?")){
dataView.deleteItem(id);
Wicket.Ajax.ajax({"u":"${url}","c":"${gridId}","ep":{'borrar':JSON.stringify(id, null, 2)}});
//This is possible because in the formatter we have assigned the row id itself as the button id;
//now assuming your grid is called 'grid'
//TODO
grid.invalidate();
idBorrada= id;
}
else{
};
});
and i call the entire function again.
hope that help, sorry for the grammar its not my native language
Follow these steps,
Add a delete link for each row with of the columns object as follows,
var columns =
{ id: "Type", name: "Application Type", field: "ApplicationType", width: 100, cssClass: "cell-title", editor: Slick.Editors.Text, validator: requiredFieldValidator, sortable: true },
{ id: "delete", name: "Action", width: 40, cssClass: "cell-title", formatter: Slick.Formatters.Link }
];
Add a Link Formatter inside slick.formatters.js as follows,
"Formatters": {
"PercentComplete": PercentCompleteFormatter,
"YesNo": YesNoFormatter,
"Link": LinkFormatter
}
function LinkFormatter(row, cell, value, columnDef, dataContext) {
return "<a style='color:#4996D0; text-decoration:none;cursor:pointer' onclick='DeleteData(" + dataContext.Id + ", " + row + ")'>Delete</a>";
}
Add the following delete function in javascript
function DeleteData(id, rowId) {
var result = confirm("Are you sure you want to permenantly delete this record!");
if (result == true) {
if (id) {
$.ajax({
type: "POST",
url: "DeleteURL",
data: { id: id },
dataType: "text",
success: function () {
},
error: function () {
}
});
}
dataView.deleteItem(id);
dataView.refresh();}
}

Categories

Resources