Start Building Professional
Web Apps Today


 
Categories Question details Back To List
Question  posted by John Rodriguez on Oct 13, 2008 00:25
open dhtmlx forum
DHTMLXGrid Serialization and Drag and Drop

Just received the new Version 2.0 controls and now have an issue.

Within a DHTMLXTabber control, we have two tabs that each contain another DHTMLXTabber control of various tabs. Within each of those tabs, we have added a DHTMLXToolbar and DHTMLXGrid control. We have an input field which we use to set filters on rows as well as clear the filters. We also have the undo/redo functionality enabled.

When we use drag and drop, the onGridReconstruction event does not fire. The rows can be moved without a problem, but when we do a serialization, the XML comes back as if it were originally loaded AND then the onGridReconstruction event fires. It's as if something has stopped the onGridReconstruction event from firing before it gets to my handler. BTW: I always return true for the handler.

We added a button and input field to the toolbar to allow us to filter a particular column as well as a clear button where we set the filter to a zero-length string (grid.filterBy(0, '')) which returns the lines back to their order if we were doing a filter. Here's the interesting twist..

If I load the grid with XML, drag a line to anywhere, then click the button I assigned to clear the filter (which is not set), the rows magically return back to the way they were on the initial load.. THEN the onGridReconstruction event fires.

Attached is the javascript file that sets up the grids, toolbars, and tabs. I don't think there is anything wrong with it, just give you an idea of where I'm at.

Thanks.

<pre>
// JScript File

function InitializeGrid(strDivID, pfEnableDrag) {

var thisGrid = new dhtmlXGridObject(strDivID);
thisGrid.setImagePath('codebase/imgs/');
thisGrid.setSkin('xp');
// dhtmlxError.catchError('LoadXML', GridCatchError);
if (pfEnableDrag)
thisGrid.enableDragAndDrop(true);

return thisGrid;

}


function GridCatchError(plngType, pstrDesc, aobjData) {

//alert('Error caught!!');

alert('plngType = ' + plngType + ' - pstrDescr = ' + pstrDesc);
return false;
}


/* SelectTabView */

function SelectTabView(pobjTab, pstrID) {
var objTab = null;
var strHeader = '';
var strAjaxURL = '';


switch (pstrID) {

case 'pu_tab1':
break;

case 'pu_tab2':
break;

case 'pu_tab3':
break;

case 'pu_satab1':
strAjaxURL = 'ajax_planutilities_getItemA.aspx';
strHeader = 'fa_';
break;

case 'pu_satab2':
strAjaxURL = 'ajax_planutilities_getItemB.aspx';
strHeader = 'pt_';
break;

case 'pu_satab3':

strAjaxURL = 'ajax_planutilities_getItemC.aspx';
strHeader = 'bf_';
break;

case 'pu_satab4':

strAjaxURL = 'ajax_planutilities_getItemD.aspx';
strHeader = 'bi_';
break;

case 'pu_satab5':
strAjaxURL = 'ajax_planutilities_getItemE.aspx';
strHeader = 'bl_';
break;


case 'pu_sbtab1':
break;


case 'pu_sbtab2':
break;

case 'pu_sbtab3':
break;


// case 'pu_sctab1':

// break;

//

// case 'pu_sctab2':

// break;

//

}

// here we go..

if (strAjaxURL.length != 0) {

objTab = LoadTabInfo(pobjTab, pstrID, strAjaxURL, true);

if (objTab) {

// add buttons..
objTab._tbar.addButton(strHeader + 'new', 0, 'New', 'new.gif', 'new_dis.gif');
objTab._tbar.addButton(strHeader + 'del', 1, 'Delete', 'iconDelete.gif', 'iconDelete_dis.gif');
objTab._tbar.addButton(strHeader + 'save', 2, 'Save', 'save.gif', 'save_dis.gif');
objTab._tbar.addButton(strHeader + 'print', 3, 'Print', 'print.gif', 'print_dis.gif');
objTab._tbar.addSeparator(strHeader + 'sep1',4);
objTab._tbar.addButton(strHeader + 'search', 5, 'Search', 'iconSearch.gif', 'iconSearch_dis.gif');
objTab._tbar.addInput(strHeader + 'filter', 6, '', 150);
objTab._tbar.addButton(strHeader + 'searchclear', 7, 'Clear');
objTab._tbar.addSeparator(strHeader + 'sep2',8);
objTab._tbar.addButton(strHeader + 'undo', 9, 'Undo', 'undo.gif', 'undo_dis.gif');
objTab._tbar.addButton(strHeader + 'redo', 10, 'ReDo', 'redo.gif', 'redo_dis.gif');
objTab._tbar.addText(strHeader + 'msg', 11, '');
objTab._tbar.disableItem(strHeader + 'del');
objTab._tbar.disableItem(strHeader + 'save');
objTab._tbar.disableItem(strHeader + 'print');
objTab._tbar.attachEvent('onClick', function(pstrBtnId) {

ProcessTBClicks(pstrBtnId);
return true;

}

);

objTab._tbar.attachEvent('onEnter', function(pstrBtnId, pstrValue) {

ProcessFilter(pstrBtnId, pstrValue);
return true;

}

);


objTab._grid.attachEvent('onCellChanged', function(strRowID, lngCell, strNewValue) {

objTab._dirtyflag = true;
objTab._tbar.enableItem(strHeader + 'save');
return true;

}

);


objTab._grid.attachEvent('onGridReconstructed', function() {

objTab._dirtyflag = true;
objTab._tbar.enableItem(strHeader + 'save');
return true;

}

);



objTab._grid.attachEvent('onRowCreated', function(strRowID, objRow, strXML) {

if (objTab.isLoaded) {
objTab._dirtyflag = true;
objTab._tbar.enableItem(strHeader + 'save');
objTab._grid.selectRowById(strRowID, null, true);

}

return true;

}

);



objTab._grid.attachEvent('onRowSelect', function(strRowID) {

if (strRowID.substring(0, 1) == 'N')
objTab._tbar.enableItem(strHeader + 'del');
else
objTab._tbar.disableItem(strHeader + 'del');

return true;

}

);



objTab._grid.attachEvent('onDrag', function(src, tgt) {

objTab._dirtyflag = true;
objTab._tbar.enableItem(strHeader + 'save');

if (strHeader == 'bl_') {
var strSType = '';
var strTType = '';

strSType = src.substring(0, 1);
strTType = src.substring(0, 1);

if (strSType == strTType)
objTab._grid.moveRowTo(src, tgt, "move", "sibling");
else
if ((strTType == 'g') && (strSType == 'l'))
objTab._grid.moveRowTo(src, tgt, "move", "child");
else
if ((strTType == 'c') && (strSType == 'g'))
objTab._grid.moveRowTo(src, tgt, "move", "child");


return false;

}

return true;

}

);


}


}

}



function LoadTabInfo(pobjTab, pstrTabID, pstrURL, pfEnableDrag) {

var strWDiv = '_' + pstrTabID + '_wrap';
var strCDiv = '_' + pstrTabID + '_cmd';
var strGDiv = '_' + pstrTabID + '_grid';

var objWDiv = document.getElementById(strWDiv);
if (!objWDiv) {
var objWDiv = document.createElement('div');
objWDiv.id = strWDiv;
objWDiv.style.width = '100%';
objWDiv.style.height = '100%';
objWDiv.style.display = 'block';
document.getElementById('pu_stagearea').appendChild(objWDiv);

var objCDiv = document.createElement('div');
objCDiv.id = strCDiv;
objCDiv.style.width = '100%';
objCDiv.style.height = '25px';
objCDiv.style.display = 'block';
objWDiv.appendChild(objCDiv);
objWDiv._tbar = new dhtmlXToolbarObject(objCDiv, 'standard');
objWDiv._tbar.setIconsPath('img/Toolbar/');
objWDiv._tbdiv = objCDiv;

var objGDiv = document.createElement('div');
objGDiv.id = strGDiv;
objGDiv.style.width = '100%';
objGDiv.style.height = '95%';
objGDiv.style.display = 'block';
objWDiv.appendChild(objGDiv);

pobjTab.setContent(pstrTabID, objWDiv.id);
objWDiv._griddiv = objGDiv;
objWDiv._grid = InitializeGrid(objGDiv.id, pfEnableDrag);
objWDiv._grid.attachEvent('onXLE', function() {objWDiv.isLoaded = true; return true;});
objWDiv._grid.enableMultiselect(false);
objWDiv._grid.setSerializationLevel();
objWDiv._grid.enableUndoRedo();

objWDiv._grid.loadXML(pstrURL);
objWDiv._dirtyflag = false;

return objWDiv;



}

}


function ProcessFilter(pstrButtonID, pstrValue) {

var objWrap = GetContainerByButtonId(pstrButtonID);
if (objWrap.isLoaded) {
objWrap._grid.filterBy(0, pstrValue);
// objWrap._grid.filterBy(1, pstrValue, true);

}

}



function ProcessTBClicks(pstrBtnID) {

var objWrap = GetContainerByButtonId(pstrBtnID);
if (objWrap) {
var strHdr = pstrBtnID.substring(0, 3);
var strCmd = pstrBtnID.substring(3);
var strNewValues = '';

switch (strCmd) {
case 'new':
if (strHdr != 'bl_') {
if (strHdr == 'fa_')
strNewValues = 'New ItemA, ItemA Description';

if (strHdr == 'pt_')
strNewValues = 'New ItemB, ItemB Description, 2100, 1';

if (strHdr == 'bf_')
strNewValues = 'New ItemC, ItemC Description';

if (strHdr == 'bi_')
strNewValues = 'New ItemD, ItemD';

objWrap._grid.addRow('N' + objWrap._grid.getRowsNum(), strNewValues);



}


else {

}

// scrolling doesn't work in row select, so force the scrollbar to move up
objWrap._grid.objBox.scrollTop = 15000;
break;



case 'del':
var strRows = objWrap._grid.getSelectedRowId();
if (strRows) {

if (confirm('Delete Selected Row?')) {

objWrap._grid.deleteSelectedRows();
objWrap._tbar.disableItem(strHdr + 'del');

}
}

break;

case 'save':

var strURL = '';
var strFilter = objWrap._tbar.getValue(strHdr + 'filter')

// Clear the filter first and see if this works..
if (strFilter.length != 0) {
// Clear filter.

objWrap._tbar.setValue(strHdr + 'filter', '');
objWrap._grid.filterBy(0, '');

}



var objHash = new Hash();
var strData = objWrap._grid.serialize();
$('xmlout').value = strData;
objHash.set('xml', encodeURI(strData));

if (strHdr == 'fa_')
strURL = 'ajax_planutilities_itemA.aspx';


if (strHdr == 'pt_')

strURL = 'ajax_planutilities_itemB.aspx';



if (strHdr == 'bi_')

strURL = 'ajax_planutilities_itemC.aspx';



if (strHdr == 'bf_')

strURL = 'ajax_planutilities_itemD.aspx';



if (strHdr == 'bl_')

strURL = 'ajax_planutilities_itemE.aspx';



//post the data to the server and see



new Ajax.Updater('pu_workmsg', strURL, {

method: 'post',
parameters: objHash,
onSuccess: function() {

objWrap_dirtyflag = false;
objWrap_tbar.disableItem(strHdr + 'save');
objWrap_tbar.setItemText(strHdr + 'msg', $('pu_workmsg').innerHTML);

},

onFailure: function () {
$('pu_workmsg').style.height = '120px';
$('pu_workmsg').style.display = 'block';

}


});

break;

case 'search':
if (strHdr != 'bl_') {
objWrap._grid.filterBy(0, objWrap._tbar.getValue(strHdr + 'filter'));
// objWrap._grid.filterBy(1, objWrap._tbar.getValue(strHdr + 'filter'), true);



}

else
{}

break;



case 'searchclear':
objWrap._tbar.setValue(strHdr + 'filter', '');
objWrap._grid.filterBy(0, '');
// objWrap._grid.filterBy(1, '', true);
break;

case 'undo':

objWrap._grid.doUndo();
break;

case 'redo':

objWrap._grid.doRedo();
break;

default:
}

}

}


</pre>
Answer posted by Support on Oct 13, 2008 02:29
>>the rows magically return back to the way they were on the initial load.
Then grid filtered first time, it saves original order, which used when its return back to normal state. 
If you have executed some operation while grid in filtered state ( row adding , deleteing ) - they will not affect original structure and will be revert after you switch off filtering. 

While it possible to use some workaround for simple add|delete operations, it will require a pretty complex code in case of d-n-d to work correctly in filtered state. 
http://dhtmlx.com/docs/products/kb/index.shtml?cat=recent&q=3752
Answer posted by Support on Oct 13, 2008 02:33
>>the onGridReconstruction event does not fire
If you are using d-n-d in plain grid, with default "move" behavior - the grid will use fast row manipulation instead of common routine. ( it will not generate new rows adding, old row deleting, just replace rows in HTML structure of grid )
Bug with not updating order of inner row collection in such scenario and not generating onGridReconstructed event - confirmed and fixed, please contact us directly at support@dhtmlx.com , we will send you fixed version.