Pass additional parameters to handsontable autocomplete source function - handsontable

I am implementing HandsOnTable autocomplete ajax as documented here: https://docs.handsontable.com/3.0.0/demo-autocomplete.html#strict-ajax
But I would like to pass additional parameter to the autocomplete source function, something like row.id below:
hot3 = new Handsontable(container3, {
data: getCarData(),
colHeaders: ['Car', 'Year', 'Chassis color', 'Bumper color'],
columns: [
{
type: 'autocomplete',
source: function (query, process, row.id) {
$.ajax({
//url: 'php/cars.php', // commented out because our website is hosted as a set of static pages
url: 'scripts/json/autocomplete.json',
dataType: 'json',
data: {
query: query
},
From the documentation, source function only accepts two parameters (query and process), anyone knows how can I pass additional parameters?

You can't add an argument to source function. It does not "accept" parameters, it provides. This function is called internally by Handsontable with predefined arguments.
But you can still access the data you are looking for. Check the context that source function is called with. It's a ColumnSettings object which contains (among others) column and row ids.
Something like:
columns: [
{
type: 'autocomplete',
source: function (query, process) {
var rowId = this.row;
var columnId = this.col;
$.ajax({
... // do whatever you want
});
}
}
]

Related

Redraw datatables with search

I am using DataTables. I have added the below code when the page is loading and the table getting all data as expected.
var table = $('#expensesTable').DataTable({
responsive: true,
searchDelay: 500,
processing: true,
serverSide: true,
ajax: {
url: '/books/daybooks/datatable',
type: 'POST',
},
columns: [
{data: 'expense_id'},
{data: 'expense_date'},
{data: 'expense_description'},
{data: 'expense_amount'},
{data: 'vendor_name'},
],
});
Now, I have added a date range picker where it will search data in the server and response will be given back to query via Ajax.
$('#datepicker').on('apply.daterangepicker', function(ev, picker) {
var start = picker.startDate.format('YYYY-MM-DD');
var end = picker.endDate.format('YYYY-MM-DD');
jQuery.ajax({
type: "POST",
url: '/books/daybooks/datatable',
data: {start : start, end : end},
success: function(data)
{
console.log(data);
} // Success End
}); //AJAX End
});
Now i am getting all expected filter data as success, but now I need to redraw the table with newly got data after the filter of Ajax call.
if i use $('#expensesTable').DataTable().draw(); then it will do draw without filter,
So i can draw table with filter data?
Thanks in advance.
Instead of introducing a new ajax call (the jQuery ajax), you can re-use your existing DataTables ajax call when submitting your date range filter data.
To do this, you need to take the following steps:
(1) Update your DataTables ajax option:
ajax: {
url: '/books/daybooks/datatable',
type: 'POST',
data: function () {
return { "start": start, "end" end };
}
},
This data function allows you to dynamically assign values to your request. They will be added as standard URL-encoded form data, in the usual way for POST requests.
See here for more information. There are several different ways to use ajax.data. For example, if you were using serverSide processing (which you are not) then the above approach would not work correctly.
(2) To re-use your DataTables ajax call, you can use this:
table.ajax.reload();
See here for more information.
This replaces your jQuery ajax call:
var start;
var end;
$('#datepicker').on('apply.daterangepicker', function(ev, picker) {
start = picker.startDate.format('YYYY-MM-DD');
end = picker.endDate.format('YYYY-MM-DD');
table.ajax.reload();
});
When the table first loads (not using reload()), the filter values will be null.

How to load kendo grid data with ajax call

How to load kendo grid data with ajax call using dataSource.data method. I have tried following but it is not working. $('#AAMaintenance').data('kendoGrid').dataSource.data(result);
function filterOnSubmit() {
var data = {};
data["ExaminerNo"] = $("#txtExaminerNo").val();
data["ExaminerName"] = $("#txtExaminerName").val();
$.ajax(
{
type: 'POST',
url: '#Url.Action("GetFilteredAAMaintenanceDetails", "AAMaintenance")',
contentType: "application/json",
dataType: 'json',
data: JSON.stringify({ aaMaintenanceFilter: data }),
success: function (result) {
$('#AAMaintenance').data('kendoGrid').dataSource.data(result);
$('#AAMaintenance').data('kendoGrid').refresh();
}
});
}
Assuming that the dataSource hasn't been setup for the Kendo grid control prior to the ajax call to retrieve the data, you should instantiate this before setting it as the datasource:
var ds = new kendo.data.DataSource({
data: result
});
$("#AAMaintenance").data("kendoGrid").setDataSource(ds);
A few notes aside from this, and based on Telerik documentation:
If the result returned from the server is a complex object (unknown currently), you may need to look into schema.model.
Ensure that the column declaration field attributes match the names assigned to the object attributes you wish to display, for example note in this example how the field: "name" column matches the name attribute being added to the dataSource.

Populating a kendo multiselect with ajax data

I am using a kendo multiselect widget for users to select different values pulled from the database via an ajax call. The ajax call takes one parameter, searchValue, which will narrow down the returned data. Here is my controller:
[HttpPost]
public JsonResult ProfitabilitySearch(string searchValue)
{
return Json(InventoryDataAccess.ProfitabilitySearch(searchValue));
}
1) How do you get the value from the text box to use as your searchValue? I commented the area in question below.
Here is my dataSource:
var searchDataSource = new kendo.data.DataSource({
transport: {
read: function () {
$.ajax({
type: 'POST',
url: Firm.ProfitabilitySearchURL,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
//'SuperClient' is test data to see if it works, but what do i
//need to make searchValue = what I type?
data: JSON.stringify({ searchValue: 'SuperClient'}),
success: function (data) {
return data.RESULT;
}
});
}
},
group: { field: 'category' },
serverFiltering: true
});
And here is where I create the multiselect widget:
var TKSearch = $("#TKSearch").kendoMultiSelect({
dataSource: searchDataSource,
autoBind: false,
minLength: 3,
placeholder: 'Search Timekeepers...',
dataTextField: 'label',
dataTextValue: 'value',
delay: 200
}).data("kendoMultiSelect");
I'm not sure if this will help, but here is the structure of the json that is returned from the ajax call:
{"label":"SUNFLOWER REALTY CORP. (023932)","value":"023932","category":"RC"}
Solving the first question above may answer my second question so I will wait to ask that until after.
You can use functions for the request parameters.
var searchDataSource = new kendo.data.DataSource({
transport: {
read: function (options) {
$.ajax({
type: 'POST',
url: Firm.ProfitabilitySearchURL,
contentType: 'application/json; charset=utf-8',
data: {
searchValue: function () {
// better: use a model property instead of this
return $("#TKSearch").data('kendoMaskedTextBox').value();
}
},
success: function (data) {
options.success(data.RESULT);
}
});
}
},
group: { field: 'category' },
serverFiltering: true
});
Notes
This really should be a GET request. Use POST for requests that actually change data on the server and GET for requests that merely retrieve data from the server.
You do not have to JSON.stringify() yourself. jQuery does that transparently.
Specifying dataType is completely superfluous, jQuery will figure this out from the response headers.
Reading the input value via jQuery is not clean. Use the data-bound model property instead.
The callback invocation (options.success())
This sample lacks HTTP error handling, you must add that.

Using jqGrid's inline-editing with RESTful urls?

I'm using jqGrid and would like to be able to use its built-in editing functions to make ajax calls to add/edit/delete. Our API uses RESTful verbs and urls like so:
verb url action
--------------------------------------------------------------
GET /api/widgets get all widgets (to populate grid)
POST /api/widgets create new widget
PUT /api/widgets/1 update widget 1
DELETE /api/widgets/1 delete widget 1
Is it possible to use the built-in ajax handling with these restrictions, or do I have to use local data (as outlined here & here) and manage the ajax calls myself? If it is possible, what properties do I set on the grid?
(ajaxRowOptions looks promising, but the documentation is a bit thin on how to use it.)
The usage of POST in Add form is by default.
The main idea for customizing jqGrid for RESTfull backend you can find in the old answer.
To use 'DELETE' in form editing if you use the Delete button of the navigator toolbar. Look at here or here. So you should use about the following settings:
$("#grid").jqGrid('navGrid', '#pager',
{edit: false, add: false, search: false}, {}, {},
{ // Delete parameters
mtype: "DELETE",
serializeDelData: function () {
return ""; // don't send and body for the HTTP DELETE
},
onclickSubmit: function (params, postdata) {
params.url = '/api/widgets/' + encodeURIComponent(postdata);
}
});
I use in the example above the encodeURIComponent function to be sure that if the id will have some special characters (spaces for example) if will be encoded so that the server part automatically received the original (decoded) data. Probably you will need to set some additional settings for the $.ajax call used during sending Delete request to the server. You can use for it ajaxDelOptions property.
You can make the above settings as your default settings. You can do this with respect of the following
$.extend($.jgrid.del, {
mtype: "DELETE",
serializeDelData: function () {
return ""; // don't send and body for the HTTP DELETE
},
onclickSubmit: function (params, postdata) {
params.url = '/api/widgets/' + encodeURIComponent(postdata);
}
});
The method onclickSubmit from the example above can be used for the Edit operations (in case of form editing) to modify the URL dynamically to /api/widgets/1. In many cases the usage of onclickSubmit in the above form is not possible because one need to use different base urls ('/api/widgets') different grids. In the case one can use
$.extend($.jgrid.del, {
mtype: "DELETE",
serializeDelData: function () {
return ""; // don't send and body for the HTTP DELETE
},
onclickSubmit: function (params, postdata) {
params.url += '/' + encodeURIComponent(postdata);
}
});
Then the usage of navGrid should be with explicit setting of url
$("#grid").jqGrid('navGrid', '#pager',
{edit: false, add: false, search: false}, {}, {},
{ // Delete parameters
url: '/api/widgets'
});
and
To use 'PUT' in inline editing you can set the following default jqGrid settings:
$.extend($.jgrid.defaults, {
ajaxRowOptions: { contentType: "application/json", type: "PUT", async: true },
serializeRowData: function (data) {
var propertyName, propertyValue, dataToSend = {};
for (propertyName in data) {
if (data.hasOwnProperty(propertyName)) {
propertyValue = data[propertyName];
if ($.isFunction(propertyValue)) {
dataToSend[propertyName] = propertyValue();
} else {
dataToSend[propertyName] = propertyValue;
}
}
}
return JSON.stringify(dataToSend);
}
});
The setting contentType: "application/json" is not required in general, but it could be required for some server technologies. The callback function serializeRowData from the example above sent the data as JSON. It is not required for RESTfull, but it's very common. The function JSON.stringify is native implemented in the most recent web browsers, but to be sure that it work in old browsers to you should include json2.js on your page.
The code of serializeRowData could be very simple like
serializeRowData: function (data) {
return JSON.stringify(data);
}
but I use above code to be able to use functions inside of the extraparam of the method editRow (see here and the problem description here).
The usage of the RESTfull URL (like /api/widgets/1) in the editRow is very simple:
$(this).editRow(rowid, true, null, null, '/api/widgets/' + encodeURIComponent(rowid));
To use it in case of the form editing you should use
grid.navGrid('#pager', {},
{ mtype: "PUT", url: '/api/widgets' });
and
$.extend($.jgrid.edit, {
ajaxEditOptions: { contentType: "application/json" }, // can be not required
onclickSubmit: function (params, postdata) {
params.url += '/' + encodeURIComponent(postdata.list_id);
}
});
It is important to remark that to get id from the postdata inside of onclickSubmit and need use postdata.list_id instead of postdata.id, where 'list' is the id of the grid. To be able to use different grid (<table>) ids one can use new non-standard parameter. For example, in the code below I use myGridId:
var myEditUrlBase = '/api/widgets';
grid.navGrid('#pager', {},
{ mtype: "PUT", url: myEditUrlBase, myGridId: 'list' },
{ // Add options
url: myEditUrlBase },
{ // Delete options
url: myEditUrlBase });
and the default setting defined as
$.extend($.jgrid.del, {
mtype: "DELETE",
serializeDelData: function () {
return ""; // don't send and body for the HTTP DELETE
},
onclickSubmit: function (params, postdata) {
params.url += '/' + encodeURIComponent(postdata);
}
});
$.extend($.jgrid.edit, {
ajaxEditOptions: { contentType: "application/json" }, // can be not required
onclickSubmit: function (params, postdata) {
params.url += '/' + encodeURIComponent(postdata[params.myGridId + '_id']);
}
});
In case of the usage of formatter:'actions' (see here and here) with inline or form editing (or a mix) you can use the same technique as described before, but forward all needed Edit/Delete option using editOptions and delOptions formatoptions.
The last your question was the usage of GET as /api/widgets. The classical RESTfull services will returns just array of all items as the response on /api/widgets. So you should just use loadonce: true and jsonReader which used methods instead of properties (See here and here).
loadonce: true,
jsonReader: {
repeatitems: false,
root: function (obj) { return obj; },
page: function () { return 1; },
total: function () { return 1; },
records: function (obj) { return obj.length; }
}
You should in some way include information which item property can be used as the id of grid rows. The id must be unique on the page. It your data has no id I would recommend you to use
id: function () { return $.jgrid.randId(); }
as an additional jsonReader method because per default the current version of jqGrid use sequential integers ("1", "2", "3", ...) as the row ids. In case of having at least two grids on the same page it will follow to the problems.
If the size of the data returned by 'GET' are more as 100 rows I would you recommend better to use server side paging. It means that you will add an additional method in the server part which support server side sorting and paging of data. I recommend you to read the answer where I described why the standard format of the input data are not RESTfull array of items and has page, total and records additionally. The new method will be probably not strange for the classical RESTful design, but the sorting and paging data in native or even SQL code can improve the total performance from the side of enduser dramatically. If the names of the standard jqGrid input parameters (page, rows, sidx and sord) you can use prmNames jqGrid parameter to rename there.
Also check out this excellent general tutorial for how to set-up jqGrid for RESTful URL's here, which also includes how the corresponding Spring MVC server portion would look.
I have managed to achieve it by implementing beforeSubmitCell event handler:
beforeSubmitCell: function(rowId) {
jQuery("#grid-HumanResource-table").jqGrid(
'setGridParam',
{
cellurl: s.getBaseModule().config.baseAPIUrl + "humanResource/" + rowId
}
);
},
I am using jqGrid 4.6 version.

Handling objects and routes with MVC3/Razor?

I have a geo collection that contains items like:
[state name]
[city], [state]
[country]
A text box is available for a user to begin typing, and a jQuery autocomplete box fills displays possible options.
The URL structure of the post request will depend on which was selected from the collection above, ie
www.mysite.com/allstates/someterms (if a country is selected)
www.mysite.com/city-state/someterms (if a city, state is selected)
www.mysite.com/[state name]/someterms (if a state is selected)
These are already defined in my routes.
I was initially going to add some logic on the controller to determine the appropriate URL structure, but I was thinking to simply add that as an additional field in the geo table, so it would be a property of the geo collection.
Here is my jQuery function to display the collection details when, fired on keypress in the textbox:
$(function () {
$("#txtGeoLocation").autocomplete(txtGeoLocation, {
source: function (request, response) {
$.ajax({
url: "/home/FindLocations", type: "POST",
dataType: "json",
selectFirst: true,
autoFill: true,
mustMatch: true,
data: { searchText: request.term, maxResults: 10 },
success: function (data) {
response($.map(data, function (item) {
return { label: item.GeoDisplay, value: item.GeoDisplay, id: item.GeoID }
}))
}
})
},
select: function (event, ui) {
alert(ui.item ? ("You picked '" + ui.item.label + "' with an ID of " + ui.item.id)
: "Nothing selected, input was " + this.value);
document.getElementById("hidLocation").value = ui.item.id;
}
});
});
What I would like is to have structure the URL based on an object parameter (seems the simplest). I can only seem to read the parameters on "selected", and not on button click.
How can I accomplish this?
Thanks.
To resolve this, I removed the select: portion from the Javascript, and added the selected object parameters in the MVC route sent to my controller.

Resources