How to update column after inline add in jqGrid - javascript

jqGrid contains columns defined in colmodel as
{"name":"_actions",
"formatoptions":{"editbutton":true,"keys":true
,"delbutton":true
} },
{ "name":"Kood","editable":true,"hidden":true}
New row is added to grid pressing inline add button in toolbar.
After data in saved, controller returns new Kood column value.
This new value should assigned to Kood column.
Code below shows two methods which I tried but both fail. Kood column values does not change
How to update column after inline add ?
How to update column also if inline added row is saved using save action button ?
$grid.jqGrid('inlineNav', '#grid_toppager', {
addParams: {
addRowParams: {
keys: true,
// This is called if enter key is pressed to save added row
aftersavefunc: afterSaveFuncAfterAdd,
}
},
editParams: {
keys: true,
// This is called if saver button in toolbar is pressed on inline add
aftersavefunc: afterSaveFuncAfterAdd,
},
add: true,
edit: false,
save: true,
cancel: true
});
function afterSaveFuncAfterAdd(rowID, response ) {
var json = $.parseJSON(response.responseText);
postData = $grid.jqGrid('getGridParam', 'postData');
// this shows correct value:
alert(json.PrimaryKeyValues[0]);
// attempt 1:
$('#' + rowID + '_Kood').val(json.PrimaryKeyValues[0]);
// attempt2:
postData['Kood'] = json.PrimaryKeyValues[0];
}

The callback aftersavefunc of the editRow will be called after the and of editing. At the moment you will find no $('#' + rowID + '_Kood'). Moreover the postData will be not changed during inline editing so $grid.jqGrid('getGridParam', 'postData') will get you no helpful information.
So I recommend you to post back all the data which you need as the response from the editurl. For example the columns which have default values calculated by the server, like last editing timestamp, you can post back. The response of the Add operation should additionally contains the id generated by the server. You can use setRowData or setCell to modify the data in the grid after receiving the response from the server.
For example, You can return
{"Id": "DB_Id", "Kood": "new Kood value"}
from the server as the response on the "Add" operation and return
{"Kood": "new Kood value"}
as the response on the "Edit" operation. In the case the code of afterSaveFuncAfterAdd can be like the following
var afterSaveFunc = function (rowId, response) {
var data = $.parseJSON(response.responseText);
if ($.isPlainObject(data) && typeof data.Kood !== "undefined") {
if (typeof data.Id !== "undefined") {
// if we have 'Id' column in the grid we have to update the column
// together with the value of `Kood`
$(this).jqGrid('setRowData', rowId, { Id: data.Id, Kood: data.Kood });
// if we have no additional `Id` we can update the Kood column only with
// the statement like below
// $(this).jqGrid('setCell', rowId, 'Kood', data.Kood);
// in case of "Add" operation we have to update the row Id
$('#' + $.jgrid.jqID(rowId)).attr('id', data.Id);
} else {
$(this).jqGrid('setCell', rowId, 'Kood', data.Kood);
}
}
}

Related

PHP & Jquery Creating Multiple Dynamic Select Lists with Probable Conditional Behaviors

The title is a bit much so let me break this down. What I am trying to accomplish here is selecting an option from select 1 (onChange) retrieves the prebuilt select for select 2 from an external php script. Same for 2 -> 3 and 3 -> 4. I know how to do this, perhaps not efficiently, but, I can get it done.
The problem I crashed into was, the 3rd select is not always an option. This is a problem because the 4th select is the end result I need. The second select in this case will give me the ID's to create select 4 instead. Make sense?
HTML:
<td>
<select name="collectionID" id="bpCollection" class="form-control">
<option value="">Select Collection</option>
<?PHP echo optionsFromDatabase();?>
</select>
</td>
<td><select name="bpClass"id="bpClass" class="form-control"></select></td>
<td><select name="bpFaction"id="bpFaction" class="form-control"></select></td>
<td><select name="bpID"id="bpID" class="form-control"></select></td>
JQUERY :
<script>
$("#bpCollection").change(function() {
$("#bpClass").load("inc/api/auto.php?type=class&choice=" + $("#bpCollection").val());
});
$("#bpClass").change(function() {
$("#bpFaction").load("inc/api/auto.php?type=faction&choice=" + $("#bpClass").val());
});
$("#bpFaction").change(function() {
$("#bpID").load("inc/api/auto.php?type=blueprint&choice=" + $("#bpFaction").val());
});
</script>
As Previously stated this does work perfectly.
Auto.php
$group = $db->escape($_GET['type']);
$choice = $db->escape($_GET['choice']);
$list = '';
switch ($group) {
case 'blueprint':
$db->where('marketGroupID',$choice);
$db->orderBy('typeName','ASC');
$map = $db->get('invTypes');
foreach ( $map as $val ) {
$list .= '<option value="'.$val['typeID'].'">'.$val['typeName'].'</option>';
}
break;
default:
$db->where('parentGroupID',$choice);
$db->orderBy('marketGroupName','ASC');
$map = $db->get('invmarketgroups');
foreach ( $map as $val ) {
$list .= '<option value="'.$val['marketGroupID'].'">'.$val['marketGroupName'].'</option>';
}
}
echo $list;
This works perfectly, except. #bpFaction is not always an option where it can't populate since #bpClass holds the ID options for #bpID. I can select the #bpClass select option and will need to jump straight to #bpID. I think a good part of the problem I have is that I don't visualize the code needed on either end to make this work properly. Do I need to make the jquery do this, do I need to change auto.php, or both?
Do you have any thoughts on how best to do it?
I recommended using Ajax with JSON above. Here I will go more in-depth of how to do that. I will be writing this sample using States, Cities, and Jurisdictions as the select box types.
We will be using one controller in PHP for all select boxes (just like yours above) except we will be re-writing it to return JSON instead. I don't know what framework you are using so I just wrote a sample of what it would look like:
// if no state passed in, return list
if(!$stateId = $request->get('state')) {
$loadedStatesFromDb = ...; // states loaded from DB
// if your $loadedCitiesFromDb is an array of classes we need to format it into a flat array for JSON
$states = [];
foreach($loadedStatesFromDb as $state) {
$states[$state->getId()] = $state->getName();
}
// your framework may require a different method of passing json data
return json_encode([
'result' => 'ok', // we pass this so the Ajax jquery call can check it returned successfully
'states' => $states
]);
}
// if no city passed in, load cities for the selected state
if(!$cityId = $request->get('city')) {
$loadedCitiesFromDb = ...; // cities loaded from DB for $stateId
// if your $loadedCitiesFromDb is an array of classes we need to format it into a flat array for JSON
$cities = [];
foreach($loadedCitiesFromDb as $city) {
$cities[$city->getId()] = $city->getName();
}
// your framework may require a different method of passing json data
return json_encode([
'result' => 'ok', // we pass this so the Ajax jquery call can check it returned successfully
'cities' => $cities
]);
}
// if no jurisdiction selected, load list
if(!$jurisdictionId = $request->get('jurisdiction')) {
$loadedJurisdictionsFromDb = ...; // jurisdictions loaded from DB for $cityId
// if your $loadedCitiesFromDb is an array of classes we need to format it into a flat array for JSON
$jurisdictions = [];
foreach($loadedJurisdictionsFromDb as $jurisdiction) {
$jurisdictions[$jurisdiction->getId()] = $jurisdiction->getName();
}
// your framework may require a different method of passing json data
return json_encode([
'result' => 'ok', // we pass this so the Ajax jquery call can check it returned successfully
'jurisdictions' => $jurisdictions
]);
}
And this is what your view would sort of look like (untested, but generally how you would do it):
<select name="state" id="state-select"></select>
<select name="city" id="city-select"></select>
<select name="jurisdiction" id="jurisdiction-select"></select>
<script type="text/javascript">
function _load_select_boxes(e) {
if(
$("#state-select").val() && $("#city-select").val() && $("jurisdiction-select").val() && // if we have an item selected in all select boxes
typeof e !== 'undefined' && e.target.id == 'jurisdiction-select' // if the select box that triggered the event is the last one
) {
_select_box_completed('jurisdiction', $("jurisdiction-select").val());
}
$.ajax({
url: '/where/you/load/select/boxes',
type: 'POST',
data: $("#state-select, #city-select, #jurisdiction-select").serialize(),
dataType: 'json', // what server will return
success: function (data) {
if (data.result === 'ok') {
if(typeof data.states !== 'undefined') {
// no need to reset options for the first select (unless we will be re-loading it without selecting a value)
// set select box options using the array of cities
for(var stateId in data.states) {
var stateName = data.states[stateId];
$("#city-select").append('<option value="' + stateId + '">' + stateName + '</option>')
}
} else if(typeof data.cities !== 'undefined') {
// reset select box
$('#city-select').find('option').remove();
// set select box options using the array of cities
for(var cityId in data.cities) {
var cityName = data.cities[cityId];
$("#city-select").append('<option value="' + cityId + '">' + cityName + '</option>')
}
} else if(typeof data.jurisdictions !== 'undefined') {
if(!data.jurisdictions.length) {
// no jurisdictions returned so we reached end
_select_box_completed('city', $("#city-select").val());
} else {
// reset select box
$('#jurisdiction-select').find('option').remove();
// set select box options using the array of jurisdictions
for(var jurisdictionId in data.jurisdictions) {
var jurisdictionName = data.jurisdictions[jurisdictionId];
$("#jurisdiction-select").append('<option value="' + jurisdictionId + '">' + jurisdictionName + '</option>')
}
}
}
} else {
// handle error for app
}
},
error: function (jqXHR, textStatus, errorThrown) {
// handle error for app
}
});
}
function _select_box_completed(type, id) {
// fired when we have selected as far as we can go
}
$(function(){
// this runs when page finishes loading, so we can load in the defaults and set events on the select boxes
$("#state-select, #city-select, #jurisdiction-select").on('change', function(e){
_load_select_boxes(e);
});
_load_select_boxes();
});
</script>
The simplest way to do this without changing much code is make your switch a function, build in a condition and call it again with changed parameters if that condition is met.
$list= myswitch($db, $group, $choice);
function myswitch($db, $group, $choice){
$list='';
switch ($group) {
case 'blueprint':
...
break;
default:
$db->where('parentGroupID',$choice);
$db->orderBy('marketGroupName','ASC');
$map = $db->get('invmarketgroups');
//*** CONDITION HERE ***
//IF condition met: set new variables
if($choice === ... && $map === ...)){
$group="xxx";
$choice="yyy";
//call the function again with new values
$list = myswitch($db, $group, $choice);
}
//ELSE create normal list
else{
foreach ( $map as $val ) {
$list.= ....
}
}
return list;
}

Dynamic Javascript sourced data - DataTable

I am using DataTable in my application. My application is not a server hosted one. (I will render the HTML directly in my standalone application. Well, that is a different story.)
Currently I am populating DataTable like below,
$(dataTableSelector).dataTable({
"sDom": 't <f> <i> <p> > ',
"bRetrieve": true,
"aaSorting": [],
"aaData": rows,
"aoColumns": columns,
"oLanguage": {
"sSearch": "",
"sInfo": "_START_ - _END_ Total: _TOTAL_ ",
"sInfoFiltered": "(filtered from _MAX_)"
}
});
Here rows are my entire data, in array of arrays as a Javascript sourced data.
But now my problem is, if the data I am going to render with DataTable is huge, then loading takes longer time.
So I am trying to change the data table similar to server side processing(but please note that I don't have any server. It is just a local HTML page). On clicking next,it should load next only, page data.Till then, it should not load the same.
Say, I have a function in javascript
function loadData(start,end, searchString){
//Function to fetch records from a Table with start and end numbers of records.
//searchString is optional.
//rows= GetDataFromTable(start,end, searchString);
return rows;
}
So, whenever the next or previous button is clicked in the data table, or searched, my javascript method should be called and it should repopulate Datatable. Any ideas?
You can load from a local variable into Datatables on every user interaction by using the ajax option and providing your own custom function. One example of its use is on their site, called "Pipelining data to reduce Ajax calls for paging".
Below is a simple example of slicing and filtering a large array and returning a small set based on the selections made on the Datatable. Note that Datatables sends more parameters which I haven't used, but you should use them to make a proper implementation. Also, it's possible that Datatables sends request.length = -1, but I have not dealt with that either.
JavaScript
var rows;
$(document).ready(function() {
rows = getLongArrayOfData();
$("#example").dataTable({
"columns": [
{"data": "column1", "title": "Column 1"},
{"data": "column2", "title": "Column 2"}
],
"serverSide": true,
"ajax": getRows()
});
});
function getRows() {
return function ( request, drawCallback, settings ) {
var dataFiltered;
var recordsTotal = rows.length;
if (request.search.value !== "") {
dataFiltered = rows.filter(FilterStartsWith(request.search.value));
}
var recordsFiltered =
(dataFiltered === undefined) ? rows.length : dataFiltered.length;
var dataSliced =
(dataFiltered === undefined ? rows : dataFiltered)
.slice(request.start, request.start + request.length);
var returnData = {
draw: request.draw,
recordsTotal: recordsTotal,
recordsFiltered: recordsFiltered,
data: dataSliced
};
drawCallback(returnData);
};
}
function FilterStartsWith(wordToCompare) {
return function(element) {
if (typeof element == "object") {
returnValue = false;
for (var property in element) {
if (element.hasOwnProperty(property)) {
if (startsWith(element[property], wordToCompare)) {
returnValue = true;
break;
}
}
}
return returnValue;
}
return startsWith(element, wordToCompare);
}
}
function startsWith(element, wordToCompare) {
if (typeof element != "string") element = new String(element);
return element.slice(0, wordToCompare.length) == wordToCompare;
}
function getLongArrayOfData() {
var retArr = new Array();
for(i=1; i<=100000; i++) {
retArr.push({column1: i, column2: "abc" + (500+i)});
}
return retArr;
}
HTML
<table id="example">
<thead>
</thead>
<tbody>
</tbody>
</table>

How to load json response which contain string values only to a combo box already created

I have a String array containing some names. I return it as a Json response and now I need to load those names in to a combo box in my html page. Combo box have been already created ans say its id is names. This is the function I wrote.
function loadSiteOfficers(ele){
var selected = ele.value;
if(selected == "Site Officer"){
jQuery.ajax({
type : "POST",
url : "/TFProject/load_officers.htm",
success : function(response) {
if (response.status == "SUCCESS") {
alert(response.result);
// load response results to the combo box
} else {
////// some code here
}
},
error : function(e) {
alert('Error: ' + e);
}
});
}
}
alert(response.result) gives me names separated by commas. They are retrieved from the database.
I am bit confused here and need to know how to load the data. I will be grateful if you can help me
Thanks.
try something like this...
$.each(response.result, function(key, value) {
$('#names').append($('<option></option>').val(key).html(value));
});

Kendo Grid Batch destroy, how to get ID's to delete?

I'm trying to process batch delete request, so i deleted some rows from grid and i clicked on save changes button.
For example:
I deleted two items from grid, but after save changes click button i get only first item ID using:
console.log("delete id: " +options.data.id);
Delete request is processed two times but I get only one Id.
How i should to do batch delete in right way?
Thanks for any advice:
Here is example of delete method:
// DELETE FUNCTION
destroy: function (options) {
console.log("delete");
console.log(options.data);
// add data to request params
console.log("delete id: " +options.data.id);
// call the service
ApiService.doHttpRequest("POST", $rootScope.apiBaseUrl + "/location/delete", requestParams)
.success(function (data, status, headers, config) {
// successful data retrieval
console.log("request success, checking state");
console.log(data);
// sent status to global HTTP status service
var jsonResponse = ApiService.processReturnedHttpState(status);
console.log("Status response is " + jsonResponse.result);
// do something with data
switch (jsonResponse.result) {
case true:
options.success(data);
break;
case false:
growlNotifications.add($translate.instant('LIST_LOADING_ERROR'), 'error', $rootScope.notificationLifetime);
break;
}
})
.error(function (data, status, headers, config) {
var jsonResponse = ApiService.processReturnedHttpState(status);
console.log("Processing error with status " +status);
growlNotifications.add($translate.instant('PROCESSING_REQUEST_ERROR') + jsonResponse.message , 'error', $rootScope.notificationLifetime);
// hide loading spinner
kendo.ui.progress(gridView, false);
});
},
options is an array. Every time you select a row to delete the data gets populated in to the options array. So the clicked row is the last index of the options array. To get the selected row id you can simply do this.
var len = options.models.length;
var curr = options.models[len - 1];
var id = curr.Id;

JQGRID: Save row after change value of a calculated cell

I'm stucked with this problem. I have a grid with a subgrid. When I edit a cell value of a column, my function goes through all subgrid rows and get's all values from that column and changes the value of a column of the parent row that opens this subgrid.
Here is my functions code:
function reloadGrid(rowid, dataResponse) {
$('#' + rowid).parent().trigger('reloadGrid');
}
function calculate(rowid, cellname, value, iRow, iCol) {
var id = $.jgrid.stripPref("_" + $.jgrid.stripPref(subGrid.getGridParam('idPrefix'), rowid), rowid);
id = $.jgrid.stripPref("s_", id);
var ids = subGrid.getDataIDs();
var result = 0.0;
for (var i = 0; i < ids.length; i++) {
result = result + parseFloat(subGrid.getCell(ids[i], 'value'));
}
grid.setCell(id, 'Total', result);
reloadGrid(rowid);
}
I tried to use this after setCell, but It seems to work only if you edited a cell, not if it's value changed automatically.
grid.saveRow(id, function(){alert("It works!");}, 'foo/edit.html?identifier=' + grid.getCell(id, 'identifier'));
What I want is to save the parent row that opens the subgrid after the cell has changed his value.
Thanks in advance.
PS: grid and subGrid variables are defined at the beginning of the JS. I think no need to explain what contains these variables...
UPDATE
Already solved, thanks anyway to all.
What I do is getting the row_id of the parent grid with $.jgrid.stripRef(...) in my current edited row. Using a function, every time I save my edited subgrid data I call that function that get all values from import column in my subgrid and sum them. After I get the total value, just have to do grid.editCell(row_id, 'total', sumResult), var data = grid.getRowData(row_id) and do an ajax call to the same URL where I send my edited data as if I do it via form:
$.ajax({
url: 'foo/edit.html?identifier=' + data.identifier,
type: 'PUT',
dataType: 'json',
contentType: 'application/json;charset=utf-8',
data: JSON.stringify(data),
success: null,
error: function(jqXHR, status, errorText) {
alert("HTTP Status code: " + jqXHR.status + "\nStatus text: "
+ status + "\nError: " + errorText);
}
});
That's what I wanted to do. I dont know if it is clear, but I have the solution. If someone don't understand something, just ask. ;)

Categories

Resources