jtable child table not POSTing key value - jquery-jtable

I have a Jquery jtable that has a child table. As far as I can see it is set up as per the example in the jtable demos. The main tables= (contacts) and the child tables (categories) display without any problem. My problem is that the delete action on the category child table is not posting the row key value (categoryID) as I would expect it to and I cannot see why not. The similar action on the main table posts its just fine. Note the two console.log lines in the code below that output the postData variable, the first one reports the ID of the contact table line (ID), but the second one prints an empty array instead of the CategoryID. Any help appreciated.
Thanks
function ReturnAjax(theurl, postdata, errorfn) {
return $.ajax({
url: theurl,
type: 'POST',
dataType: 'json',
data: postdata,
cache: false,
error: errorfn
});
}
$('#ContactsTableContainer').jtable({
title: 'Contacts',
paging: true,
pageSize: 30,
sorting: true,
defaultSorting: 'LastName ASC',
selecting: true,
selectOnRowClick: true,
openChildAsAccordion: true,
deleteConfirmation: false,
actions: {
listAction: function(postData, jtParams) {
console.log("ContactsTableContainer - Loading list from custom function...");
return $.Deferred(function($dfd) {
$.ajax({
url: 'ContactsData.php?action=list&jtStartIndex=' + jtParams.jtStartIndex + '&jtPageSize=' + jtParams.jtPageSize + '&jtSorting=' + jtParams.jtSorting,
type: 'POST',
dataType: 'json',
data: postData,
success: function(data) {
if(data['RowIDs']) { RowIDs = data['RowIDs'].toString().split(','); }
$dfd.resolve(data);
},
error: MyError
});
});
},
deleteAction: function(postData) {
console.log('deleting from contacts - custom function..., '+JSON.stringify(postData));
$.when(
ReturnAjax(
'ContactsData.php?action=list&ContactID='+postData['ID'],
postData,
MyError
)
).then(
function(data) {
if (data.Result != 'OK') { alert(data.Message); }
var msg = '';
var len = data.Records.length;
if(len>0) {
msg = '\t'+data.Records[0].Category;
for(var i=1 ; i<len ; i++) { msg += '\n\t'+data.Records[i].Category; }
msg = 'Contact is in the following categories\n'+msg;
}
msg += '\n\nConfirm deletion of this contact';
if(confirm(msg)) {
$.when(
ReturnAjax(
'ContactsData.php?action=delete',
postData,
MyError
)
).done(
$('#ContactsTableContainer').jtable('reload')
);
} else {
$('#ContactsTableContainer').jtable('reload'); // Had to put this here to ensure that same delete button could be used again
}
}
).fail( function() { console.log('ajax call went wrong'); } );
}, // end of delete action
}, // end of actions
fields: {
ID: {
key: true,
create: false,
edit: false,
list: false,
visibility: 'hidden'
},
Categories: {
title: '',
width: '5%',
sorting: false,
create: false,
display: function(contact) {
var $img = $('<img src="Images/layers.png" title="Show contact\'s categories" />');
//Open child table when user clicks the image
$img.click(function() {
console.log('display function (contact)..., '+JSON.stringify(contact));
$('#ContactsTableContainer').jtable(
'openChildTable',
$img.closest('tr'), //Parent row
{
title: contact.record.Name + ' - Categories',
selecting: true,
selectOnRowClick: true,
actions: {
listAction: 'ContactsData.php?action=list&ContactID=' + contact.record.ID,
deleteAction: function(postData) {
console.log('deleting from custom category function..., '+JSON.stringify(postData));
$.when(
ReturnAjax(
'ContactsData.php?action=deleteAssignment&ContactID=' + contact.record.ID,
postData,
MyError
)
).done(
$('#ContactsTableContainer').jtable('reload')
);
}
},
fields: {
CategoryID: { key: true, create: false, edit: false, list: false, visibility: 'hidden' },
ContactID: { type: 'hidden', defaultValue: contact.record.ID },
Category: { title: 'Category' }
}
},
function(data) { data.childTable.jtable('load'); }
);
});
//Return image to show on the person row
return $img;
}
},
FirstName: {
  title: 'Forename',
  width: '25%',
},
LastName: {
  title: 'Surname',
  width: '25%',
},
HomePhone: {
title: 'Phone',
width: '15%',
sorting: false,
},
Mobile: {
title: 'Mobile',
width: '15%',
sorting: false,
},
Email: {
title: 'Email',
width: '20%',
sorting: false,
},
Name: {
  type: 'hidden'
},
}
});
//Load list from server
$('#ContactsTableContainer').jtable('load');

OK, I solved it, sorry to bother anyone who may have spent time looking at this. The problem was that my child table variable names were wrong they should have been category_ID and Contact_ID

Related

Export To Excel filtered data with Free jqgrid 4.15.4 in MVC

I have a question regarding Export to Excel in free-jqgrid 4.15.4. I want to know how to use this resultset {"groupOp":"AND","rules":[{"field":"FirstName","op":"eq","data":"Amit"}]} into my Business Logic Method.
Just for more clarification, I've using OfficeOpenXml and if I don't use filtered resultset(aforementioned) it is working fine and I'm able to download file with full records in an excel sheet. But I'm not sure what to do or how to utilize the resultset {"groupOp":"AND","rules":[{"field":"FirstName","op":"eq","data":"Amit"}]}
If required I can share my controller and BL code.
I have added a fiddle which shows implementation of Export to Excel button in jqGrid pager.
Before coming to here, I've read and tried to understand from following questions:
1] jqgrid, export to excel (with current filter post data) in an asp.net-mvc site
2] Export jqgrid filtered data as excel or CSV
Here is the code :
$(function () {
"use strict";
var mydata = [
{ id: "10", FirstName: "test", LastName: "TNT", Gender: "Male" },
{ id: "11", FirstName: "test2", LastName: "ADXC", Gender: "Male" },
{ id: "12", FirstName: "test3", LastName: "SDR", Gender: "Female" },
{ id: "13", FirstName: "test4", LastName: "234", Gender: "Male" },
{ id: "14", FirstName: "test5", LastName: "DAS", Gender: "Male" },
];
$("#list").jqGrid({
data: mydata,
colNames: ['Id', 'First Name', 'Last Name', 'Gender'],
colModel: [
{
label: "Id",
name: 'Id',
hidden: true,
search: false,
},
{
label: "FirstName",
name: 'FirstName',
searchoptions: {
searchOperators: true,
sopt: ['eq', 'ne', 'lt', 'le','ni', 'ew', 'en', 'cn', 'nc'],
}, search: true,
},
{
label: "LastName",
name: 'LastName',
searchoptions: {
searchOperators: true,
sopt: ['eq', 'ne', 'lt', 'ni', 'ew', 'en', 'cn', 'nc'],
}, search: true,
},
{
label: "Gender",
name: 'Gender',
search: true, edittype: 'select', editoptions: { value: 'Male:Male;Female:Female' }, stype: 'select',
},
],
onSelectRow: function (id) {
if (id && id !== lastsel) {
jQuery('#list').restoreRow(lastsel);
jQuery('#list').editRow(id, true);
lastsel = id;
}
},
loadComplete: function (id) {
if ($('#list').getGridParam('records') === 0) {
//$('#grid tbody').html("<div style='padding:6px;background:#D8D8D8;'>No records found</div>");
}
else {
var lastsel = 0;
if (id && id !== lastsel) {
jQuery('#list').restoreRow(lastsel);
jQuery('#list').editRow(id, true);
lastsel = id;
}
}
},
loadonce: true,
viewrecords: true,
gridview: true,
width: 'auto',
height: '150px',
emptyrecords: "No records to display",
iconSet:'fontAwesome',
pager: true,
jsonReader:
{
root: "rows",
page: "page",
total: "total",
records: "records",
repeatitems: false,
Id: "Id"
},
});
jQuery("#list").jqGrid("navButtonAdd", {
caption: "",
buttonicon: "fa-table",
title: "Export To Excel",
onClickButton: function (e) {
var projectId = null;
var isFilterAreUsed = $('#grid').jqGrid('getGridParam', 'search'),
filters = $('#grid').jqGrid('getGridParam', 'postData').filters;
var Urls = "/UsersView/ExportToExcel_xlsxFormat?filters="+ encodeURIComponent(filters); //' + encodeURIComponent(filters);/
if (totalRecordsCount > 0) {
$.ajax({
url: Urls,
type: "POST",
//contentType: "application/json; charset=utf-8",
data: { "searchcriteria": filters, "projectId": projectId, "PageName": "MajorsView" },
//datatype: "json",
success: function (data) {
if (true) {
window.location = '/UsersView/SentFiletoClientMachine?file=' + data.filename;
}
else {
$("#resultDiv").html(data.errorMessage);
$("#resultDiv").addClass("text-danger");
}
},
error: function (ex) {
common.handleAjaxError(ex.status);
}
});
}
else {
bootbox.alert("There are no rows to export in the Participant List")
if (dialog) {
dialog.modal('hide');
}
}
}
});
});
https://jsfiddle.net/ap43xecs/10/
There are exist many option to solve the problem. The simplest one consist of sending ids of filtered rows to the server instead of sending filters parameter. Free jqGrid supports lastSelectedData parameter and thus you can use $('#grid').jqGrid('getGridParam', 'lastSelectedData') to get the array with items sorted and filtered corresponds to the current filter and sorting criteria. Every item of the returned array should contain Id property (or id property) which you can use on the server side to filter the data before exporting.
The second option would be to implement server side filtering based on the filters parameter, which you send currently to the server. The old answer (see FilterObjectSet) provides an example of filtering in case of usage Entity Framework. By the way, the answer and another one contain code, which I used for exporting grid data to Excel using Open XML SDK. You can compare it with your existing code.
In some situations it could be interesting to export grid data to Excel without writing any server code. The corresponding demo could be found in the issue and UPDATED part of the answer.

How do I populate a User Story's Revision History in a grid

I found an answer related to Revision History "Querying for User Story revisions in Rally"
I am having trouble determining how to populate a grid with it.
Can I use the model and populate a story that the gird references?
Here is a working example, using other examples.
I had to populate an array with revision history info and add it to a story.
Then the story populated the grid.
// Also referenced
// https://stackoverflow.com/questions/22334745/does-rally-data-custom-store-have-magic-uniqueness
//
Ext.define('CustomApp',
{
extend: 'Rally.app.App',
componentCls: 'app',
launch: function()
{
var panel = Ext.create('Ext.panel.Panel',
{
layout: 'hbox',
itemId: 'parentPanel',
componentCls: 'panel',
items: [
{
xtype: 'panel',
title: 'Artifacts updated in the last two days',
width: 600,
itemId: 'childPanel1'
},
{
xtype: 'panel',
title: 'Last Revision',
width: 600,
itemId: 'childPanel2'
}]
});
this.add(panel);
var artifacts = Ext.create('Rally.data.wsapi.artifact.Store',
{
models: ['UserStory','Defect', 'TestCase'],
fetch: ['Owner', 'FormattedID','Name','ScheduleState','RevisionHistory','Revisions','Description','CreationDate','User'],
autoLoad: true,
listeners:
{
load: this._onDataLoaded,
scope: this
}
});
},
_onDataLoaded: function(store, data)
{
this._customRecords = [];
_.each(data, function(artifact, index)
{
this._customRecords.push(
{
_ref: artifact.get('_ref'),
FormattedID: artifact.get('FormattedID'),
Name: artifact.get('Name'),
RevisionID: Rally.util.Ref.getOidFromRef(artifact.get('RevisionHistory')),
RevisionNumber: 'not loaded'
});
}, this);
this._createGrid(store,data);
},
_createGrid: function(store,data)
{
var that = this;
var g = Ext.create('Rally.ui.grid.Grid',
{
itemId: 'g',
store: store,
enableEditing: false,
showRowActionsColumn: false,
columnCfgs:
[{text: 'Formatted ID', dataIndex: 'FormattedID'},
{text: 'Name', dataIndex: 'Name'},
{text: 'ScheduleState', dataIndex: 'ScheduleState'},
{text: 'Last Revision',
renderer: function (v, m, r)
{
var id = Ext.id();
Ext.defer(function ()
{
Ext.widget('button',
{
renderTo: id,
text: 'see',
width: 50,
handler: function ()
{
that._getRevisionHistory(data, r.data);
}
});
}, 50);
return Ext.String.format('<div id="{0}"></div>', id);
}
}], height: 400,
});
this.down('#childPanel1').add(g);
},
_getRevisionHistory: function(artifactList, artifact)
{
this._artifact = artifact;
this._revisionModel = Rally.data.ModelFactory.getModel(
{
type: 'RevisionHistory',
scope: this,
success: this._onModelCreated
});
},
_onModelCreated: function(model)
{
model.load(Rally.util.Ref.getOidFromRef(this._artifact.RevisionHistory._ref),
{
scope: this,
success: this._onModelLoaded
});
},
_onModelLoaded: function(record, operation)
{
var list = [];
record.getCollection('Revisions').load(
{
fetch: true,
scope: this,
callback: function(revisions, operation, success)
{
_.each(revisions, function(artifact, index)
{
var creationdate;
if (Rally.environment.useSystemTimezone || Rally.environment.useWorkspaceTimeZone)
{
creationdate = Rally.util.DateTime.formatDate(artifact.data.CreationDate, true);
}
else
{
creationdate = Rally.util.DateTime.formatWithDefaultDateTime(artifact.data.CreationDate);
}
var nodedata =
{
rev_num: artifact.data.RevisionNumber,
descript: artifact.data.Description,
author: artifact.data.User._refObjectName,
creationdate: creationdate
};
if(nodedata.descript.indexOf('SCHEDULE STATE') > -1)
{
list.push(nodedata);
}
else
{
if(nodedata.descript .indexOf('PLAN ESTIMATE') > -1)
{
list.push(nodedata);
}
}
}, this);
var myStore = Ext.create("Rally.data.custom.Store",
{
autoLoad: true,
data : list,
});
var revGrid = Ext.create('Rally.ui.grid.Grid',
{
itemId: 'revGrid ',
store: myStore,
enableEditing: false,
showRowActionsColumn: false,
height: 400,
columnCfgs:
[
{text: 'Rev #', dataIndex: 'rev_num'},
{text: 'Description', dataIndex: 'descript'},
{text: 'Author', dataIndex: 'author'},
{text: 'Change Date', dataIndex: 'creationdate'}
]
});
this.down('#childPanel2').add(revGrid);
}
});
},
});

jTable dynamic custom toolbar item in child table

I have a jTable with a child table for each row. On the toolbar header of the child table I have added a custom toolbar item. I want to make that toolbar item dynamic in the sense that if there are already some rows I do not want it to show. I came across a very similar query for the main toolbar "add new" button which added a function to run on recordsLoaded:
Below is my first attempt - it is just the field entry for the main table that specifies the child table. However the ".find(....)" spec will not work in my case as mine is a custom toolbar item. What do I need to put as the .find criteria?
Thanks
Dance: {
title: '',
width: '4%',
sorting: false,
create: false,
listClass: 'centreCol',
display: function(book) {
var $img = $('<img src="Images/layers.png" title="Show associated dance entries" />');
//Open child table when user clicks the image
$img.click(function() {
var thisrow = $img.closest('tr'); //Parent row
if($('#BookTableContainer').jtable('isChildRowOpen',thisrow)) { // Clicking image a second time closes the child row
$('#BookTableContainer').jtable('closeChildRow',thisrow);
} else {
currentTitleID = book.record.DanceTitleID;
$('#BookTableContainer').jtable(
'openChildTable',
thisrow,
{
title: 'Related Dance',
toolbar: {
items: [
{
icon: 'Images/add.png',
text: 'New dance',
tooltip: 'Add dance details',
click: function() { CreateDanceDialog(); }
}
]
},
actions: {
listAction: 'BookPageData.php?action=listChildDances&DanceTitleID=' + currentTitleID,
// createAction: 'dancesData.php?action=createAssignment',
// deleteAction: 'dancesData.php?action=deleteAssignment'
},
recordsLoaded: function(event, data) {
var rowCount = data.records.length;
if (rowCount>0){
$('#BookTableContainer').find('.jtable-toolbar-item.jtable-toolbar-item-add-record').remove();
}
},
fields: {
DanceID: { key: true, create: false, edit: false, list: false, visibility: 'hidden' },
DanceTitleID: { type: 'hidden', defaultValue: currentTitleID },
ChoreographerID: { title: 'Choreographer', width: '40%', options: function() { return ChoreographerOptions; } },
FormationID: { title: 'Formation', width: '30%', options: function() { return FormationOptions; } },
GenreID: { title: 'Genre', width: '30%', options: function() { return GenreOptions; } }
}
},
function(data) { data.childTable.jtable('load'); }
);
}
});
//Return image to show on the person row
return $img;
}
},
Try this
$('#BookTableContainer').find('.jtable-toolbar').remove();

jQuery JTable Problems to find selected rows in ChildTable

I have some problems finding my selected rows in a nested JQuery JTable via a Toolbar Click.
This is my nested table which works fine:
$(document).ready(function () {
$('#TableContainer').jtable({
title: 'MyList',
sorting: true,
defaultSorting: 'list_id desc',
actions: {
listAction: 'lists_list_action.php?action=list',
updateAction: 'lists_list_action.php?action=update',
},
fields: {
list_id: { title: 'Nr.', key: true, list: true, width: '10px', listClass: 'psg_list_center' },
//CHILD TABLE "Abos"
abos: {
title: 'Abos',
width: '5%',
sorting: false,
edit: false,
create: false,
display: function (ListData) {
//Create an image that will be used to open child table
var $img = $('<img src="../../images/list_metro.png" title="manage Listabos" />');
//Open child table when user clicks the image
$img.click(function () {
$('#TableContainer').jtable('openChildTable',
$img.closest('tr'), //Parent row
{
title: 'List: ' + ListData.record.list_name,
selecting: true, //Enable selecting
multiselect: true, //Allow multiple selecting
selectingCheckboxes: true, //Show checkboxes on first column
selectOnRowClick: false, //Enable this to only select using checkboxes
actions: {
listAction: 'lists_list_action.php?action=AbosList&ListId=' + ListData.record.list_id,
deleteAction: 'lists_list_action.php?action=AbosDelete&ListId=' + ListData.record.list_id,
},
fields: {
list_id: { type: 'hidden', defaultValue: ListData.record.list_id },
person_id: { key: true, create: false, edit: false, list: false },
person_name: { title: 'Name', width: '40%' },
created_name: { title: 'created from', create: false, edit: false },
created_on: { title: 'created on', create: false, edit: false },
updated_name: { title: 'updated from', create: false, edit: false },
updated_on: { title: 'updated on', create: false, edit: false },
},
toolbar: {
items: [{
//icon: '/images/trash.png',
text: 'remove selected Abos',
click: function () {
// here i need to something like this:
alert('list_id=' + record.list_id + ', person_id=' + record.person_id);
delete_abo(record.list_id, record.person_id);
}
}]
},
}, function (data) { //opened handler
data.childTable.jtable('load');
});
});
//Return image to show on the person row
return $img;
}
},
list_name: { title: 'List Name' },
list_description: { title: 'Description', type: 'textarea' },
list_active: { title: 'activ', options: { 1: 'Yes', 0: 'No' } },
list_allow_subscribe: { title: 'Subscribe erlaubt', options: { 1: 'Yes', 0: 'No' } },
list_allow_unsubscribe: { title: 'Unsubscribe erlaubt', options: { 1: 'Yes', 0: 'No' } },
},
});
$('#TableContainer').jtable('load');
});
Can anybody help me at the toolbar-click Section, finding the selected Rows of the Child-Table?
I tried to do something like this:
click: function (ListData) {
var $selectedRows = ListData.jtable('selectedRows');
or:
click: function () {
var $selectedRows = $('#TableContainer').jtable-child-table-container.jtable('selectedRows');
$('#TableContainer').jtable('delete', $selectedRows);
}
or:
click: function () {
var $selectedRows = $('#TableContainer').jtable-child-table-container.jtable('selectedRows');
if ($selectedRows.length > 0) {
$selectedRows.each(function () {
var record = $(this).data('record');
alert('list_id=' + record.list_id + ', person_id=' + record.person_id);
//delete_abo(record.list_id, record.person_id);
});
} else {
//No rows selected
alert('please select some rows first!');
}
}
because the last part worked fine in an "not nested" part of my program,
but I did not come to an resolution anyhow...
Thanks for help!
finaly found the solution!
The Key to get the selected Rows:
var $selectedRows = $('#TableContainer>.jtable-main-container>.jtable>tbody>.jtable-child-row .jtable-row-selected');
or the whole working function:
click: function () {
var $selectedRows = $('#TableContainer>.jtable-main-container>.jtable>tbody>.jtable-child-row .jtable-row-selected');
if ($selectedRows.length > 0) {
$selectedRows.each(function () {
var record = $(this).data('record');
alert('list_id=' + record.list_id + ', person_id=' + record.person_id);
//delete_abo(record.list_id, record.person_id);
});
} else {
//No rows selected
alert('please select some rows first!');
} }

Highmaps Group Countries and Hover, Follow link on Click

As the topic states, I would like to group countries to create my own "areas". It works nearly, but I don't know whats wrong.
Here is my map: http://jsfiddle.net/wiesson/oktajn6e
It is mostly derived from the examples, but it does not work. If I set "allAreas" to false, it is okay but I would like to display all other countries, too!
Any ideas?
$(function () {
// Instanciate the map
$('#container').highcharts('Map', {
chart: {
borderWidth: 0
},
title: {
text: 'Group Hover'
},
legend: {
enabled: true
},
plotOptions: {
map: {
allAreas: true,
joinBy: ['iso-a2', 'code'],
mapData: Highcharts.maps['custom/world']
},
series: {
states:{
normal: {
animation: false
}
},
point: {
events: {
mouseOver: function(){
var ser = this.series;
var data = ser.data;
$.each(data, function(){
this.setState("hover")
});
},
mouseOut: function(){
var ser = this.series;
var data = ser.data;
$.each(data, function(){
this.setState()
});
}
}
}
}
},
series: [{
name: 'Nordic Countries',
data: $.map(['IS', 'NO', 'SE', 'FI', 'DK'], function (code) {
return {
code: code
};
}),
}, {
name: 'Some of central Europe',
data: $.map(['DE', 'AT', 'GB', 'FR'], function (code) {
return {
code: code
};
}),
}]
});
});
This solution should fix your problem: http://jsfiddle.net/oktajn6e/5/
But let me explain what happens in your code:
With both series you create a full world map with all areas. So if you activate both series, the second series covers the complete first series.
It means, the blue areas get covered by series' two grey areas.
I managed to solve it this way:
series: [{
allAreas: true,
mapData: Highcharts.maps['custom/world'],
showInLegend: false,
}, {
allAreas: false,
name: 'Nordic Countries',
joinBy: ['iso-a2', 'code'],
mapData: Highcharts.maps['custom/world'],
data: $.map(['IS', 'NO', 'SE', 'FI', 'DK'], function (code) {
return {
code: code
};
}),
}, {
allAreas: false,
name: 'Some of central Europe',
joinBy: ['iso-a2', 'code'],
mapData: Highcharts.maps['custom/world'],
data: $.map(['DE', 'AT', 'GB', 'FR'], function (code) {
return {
code: code
};
}),
}]
By creating each series individually and setting "allAreas:false" we can simply render it on the first series, where we only show the full map.

Resources