How to place focus on new grid row?

Hi, I’m using the dhtmlXDataStore to push data entered from a form into a grid, both of which are in the same layout object.

After adding a row, I can’t seem to get the grid control to put the focus on the new row. The ‘doesRowExist’ test on the newly-added row returns false, which seems odd, as it appear in the grid control after the ‘add’ button has been clicked. I’ve tried both the selectRow and selectRowById methods. Here’s the code. ‘contacts’ is the name of the dhtmlXDataStore object. Thanks for any help you might give!

	myGrid.sync(contacts);
	
	myForm.bind(myGrid);
	
	myForm.attachEvent("onButtonClick", function(id){
		if (id=='add'){
			var myuid = (new Date()).valueOf(); 
			myForm.setItemValue("ContactID", myuid); //(new Date()).valueOf());
			obj = myForm.getFormData();
			contacts.add(obj);
			var row = myGrid.doesRowExist(myuid);
			//myGrid.selectRowById(myuid);					//<-- doesn't work.
			myGrid.selectRow(myGrid.getRowIndex(myuid),false,false,true);	//<-- doesn't work.		
		}

Both datastore and grid will expect that you have “id” property on data object, so you need to have

obj = myForm.getFormData(); obj.id = myuid; //added contacts.add(obj);

Splendid, Stanislav, I’ll try it, thank you.

That worked a treat, Stanislav, thank you so very much!

Stanislav, I’m still seeing a problem. Although the new row is now highlighted, if I wish to immediately delete it, using this code:

		else if (id=='delete'){ 							// Deletes the selected row.
			//var selectedItem = myGrid.getSelectedRowId();
			var selectedItem = myGrid.getSelectedId();
			contacts.remove(selectedItem);
		}

The row appears to be deleted, until I hit the browser refresh button - at which point it reappears. So it never really gets physically deleted. Adding this:

			myGrid.deleteRow(selectedItem);

before or after the contracts.remove statement doesn’t seem to help at all, either.

Please advise? Thank you.

Which code you are are using for data saving ? Is it instance of dataprocessor, attached to datastore or some custom code ?

In case of connector usage - can you enable logging on server side and check is “delete” request hits the server.

If situation occurs only for newly created rows it can be problem with new id generation, when record doesn’t get updated id after saving data in database.

Hi Stanislav,

I’m using both a datastore - so that the form and grid may exchange data - and a dataprocessor. The problem seems to occur on only newly-created rows, but looking at the database, there doesn’t seem to be a problem with new ID generation. I’ll try enabling logging to investigate further as you suggested. Here’s all the code - please let me know if anything looks wrong, thank you:

<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
	<title>FRST Datastore test</title>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />	

		<style type="text/css">
			div.marginl {margin-left:20pt;}
		</style>	
	
<!-- Layout -->
	<link rel="stylesheet" type="text/css" href="./dhtmlxLayout/dhtmlxLayout/codebase/dhtmlxlayout.css">
	<link rel="stylesheet" type="text/css" href="./dhtmlxLayout/dhtmlxLayout/codebase/skins/dhtmlxlayout_dhx_skyblue.css">
	<script src="./dhtmlxLayout/dhtmlxLayout/codebase/dhtmlxcommon.js"></script>
	<script src="./dhtmlxLayout/dhtmlxLayout/codebase/dhtmlxlayout.js"></script>  
  
<!-- Tab bar -->
	<link rel="STYLESHEET" type="text/css" href="./dhtmlxTabbar/dhtmlxTabbar/codebase/dhtmlxtabbar.css">
	<script src='./dhtmlxTabbar/dhtmlxTabbar/codebase/dhtmlxcommon.js'></script>
	<script src='./dhtmlxTabbar/dhtmlxTabbar/codebase/dhtmlxtabbar.js'></script>
	<script src='./dhtmlxTabbar/dhtmlxTabbar/codebase/dhtmlxcontainer.js'></script>	
    
<!-- Grid -->
	<link rel='stylesheet' type='text/css' href='./dhtmlxGrid/dhtmlxGrid/codebase/dhtmlxgrid.css'>
	<link rel='stylesheet' type='text/css' href='./dhtmlxGrid/dhtmlxGrid/codebase/skins/dhtmlxgrid_dhx_skyblue.css'>
	<link rel='stylesheet' type="text/css" href='./dhtmlxGrid/dhtmlxGrid/samples/common/css/style.css' media="screen" />
	<script src='./dhtmlxGrid/dhtmlxGrid/codebase/dhtmlxcommon.js'></script>
	<script src='./dhtmlxGrid/dhtmlxGrid/codebase/dhtmlxgrid.js'></script> 
	<script src='./dhtmlxGrid/dhtmlxGrid/codebase/dhtmlxgridcell.js'></script>		
	<script src='./dhtmlxGrid/dhtmlxGrid/codebase/ext/dhtmlxgrid_validation.js' type='text/javascript' charset='utf-8'></script>
	<script src='./dhtmlxGrid/dhtmlxGrid/samples/common/data.js'></script>
	<script src='./dhtmlxGrid/dhtmlxGrid/codebase/ext/dhtmlxgrid_srnd.js'></script>
	<script src='./dhtmlxGrid/dhtmlxGrid/codebase/ext/dhtmlxgrid_filter.js'></script>
	<script src='./dhtmlxGrid/dhtmlxGrid/codebase/ext/dhtmlxgrid_form.js'></script>	
	
<!-- Form -->  
    	<link rel='stylesheet' type='text/css' href='./dhtmlxForm/dhtmlxForm/codebase/skins/dhtmlxForm_dhx_skyblue.css'>
    	<script src='./dhtmlxForm/dhtmlxForm/codebase/dhtmlxcommon.js'></script> <!--Ensure form libraries are placed after tab, grid libraries-->		
    	<script src='./dhtmlxForm/dhtmlxForm/codebase/dhtmlxform.js'></script>	

<!-- Datastore -->
	<script src='./datastore/datastore.js'></script>
	
<!-- Dataprocessor -->
	<script src='./dhtmlxGrid/dhtmlxdataprocessor/sources/dhtmlxdataprocessor.js'></script>
	
<!-- Dataconnector -->
	<script src='./dhtmlxConnector_php_v15_120612/php/codebase/connector.js'></script>
    <style>
    
        div#tabbar {
            position: relative;
            width: 600px;
            height: 400px;
            margin-left: 20px;
            margin-top: 20px;
        }
    </style>
    <script>
    var dhxLayout;    
    var myForm, formData;
    var myGrid;
    var dhxTabbar;
    var obj;
    var myuid;
    
function doOnLoad() {
	
// 	Initialise datastore.
	var contacts = new dhtmlXDataStore({
		url:"connectorFRST2.php",
		datatype:"xml"
	});
	
//	Set default grid data scheme.
	contacts.data.scheme({
	
		LName: 		"Enter new contact",
		FName:		"",
		DOB:		"",
		Moniker:	"",
		Offenses:	"",
		ContactID:	myuid //(new Date()).valueOf(), //"123",		
	});	

        var myDP = new dataProcessor("connectorFRST2.php");
	myDP.init(contacts);
	
//  Set 'Contact' form data.	
    formData = [{
        type: "settings",
        position: "label-left",
        labelWidth: 145,
        inputWidth: 375
    }, {
        type: "block",
        inputWidth: "auto",
        list: [{
            type: "input",
            name: "LName",
            label: "Last Name"
        }, {
            type: "input",
            name: "FName",
            label: "First Name"
        }, {
            type: "input",
            name: "DOB",
            label: "Date of Birth"
        }, {
            type: "input",
            name: "Moniker",
            label: "Moniker"
        }, {
            type: "input",
            name: "Offenses",
            label: "Offenses"
         }, {
            type: "hidden",
            name: "ContactID",
            label: "Contact ID"            
        }, {
            type: "block", list:[{
            	type: "button", offsetTop:8, name:"add", value:"add"
            	}, {
            	type: "newcolumn"
            	}, {
            	type: "button", name:"change", offsetTop:8, value:"change"
            	}, {
            	type: "newcolumn"
            	}, {
            	type: "button", name:"delete", offsetTop:8, value:"delete"
            	}, {
       		type: "newcolumn"
       		}, {
            	type: "button", name:"clear", offsetTop:8, value:"clear"
            }]	
        }]
    }];

// To attach forms and grids to the tab bar, see:        
// http://www.dhtmlx.com/docs/products/dhtmlxForm/samples/05_integration/05_split.html#code         
// http://dhtmlx.com/docs/products/dhtmlxTabbar/samples/05_components/01_grid_inside.html
// To attach layout to tabbar, see:
// http://www.dhtmlx.com/docs/products/dhtmlxLayout/samples/04_components/04_tabbar.html
         
//	Initialise layout.
	dhxLayout = new dhtmlXLayoutObject("parentId", "2U");
	dhxLayout.cells("a").setText("Contact Search");	

//	Attach tab bar to layout and initialise tab bar.
    	//dhxTabbar = new dhtmlXTabBar("tabbar");
    	dhxTabbar = dhxLayout.cells("b").attachTabbar();    	
    	dhxTabbar.setImagePath("./dhtmlxTabbar/dhtmlxTabbar/codebase/imgs/");
    	dhxTabbar.setSkin("dhx_skyblue");
    	dhxTabbar.addTab("a1", "Contact", 70);
    	dhxTabbar.addTab("a2", "Referrals", 70);
    	dhxTabbar.addTab("a3", "Notes", 70);
    	dhxTabbar.addTab("a4", "Reports", 70);
    	dhxTabbar.setTabActive("a1");

//	Attach 'Contact Search' grid to layout and initialise grid.    	
	myGrid = dhxLayout.cells("a").attachGrid();
	myGrid.setImagePath("./dhtmlxGrid/dhtmlxGrid/codebase/imgs/");
	myGrid.setHeader("Last Name,First Name,Date of Birth");
	myGrid.setInitWidths("250,250,90");
	
	myGrid.setColumnIds("LName,FName,DOB");
	
	myGrid.attachHeader("#text_filter,#text_filter,#text_filter");
	myGrid.enableAutoWidth(true);
	myGrid.setColAlign("left,left,right");
	myGrid.setColTypes("ro,ro,ro");
	myGrid.setColSorting("str,str,date");
	myGrid.setSkin("dhx_skyblue");	
	myGrid.init();
	//myGrid.enableStableSorting(true);	
	//myGrid.sortRows(0,"str","asc");	
  	
//	Attach 'Contact' form to tab bar.    
    	myForm = dhxTabbar.cells("a1").attachForm(formData);

//	Attach 'Referrals' grid to tab bar and initialise grid.    

//	2013.01.03 - it appears it will be necessary to create another PHP dataprocessor script to source data from the 'referrals' table, then use an event handler
// 	in the main grid to load data into the second grid. See http://stackoverflow.com/questions/12226273/how-to-refresh-reload-dhtmlx-grid. 

//	myGrid.loadXML("connectorFRST2a.php", function(){myGrid2.sortRows(0);});   <-- will need to pass ContactID value somehow to connectorFRST2a.php. See http://forum.dhtmlx.com/viewtopic.php?f=19&t=14993.
	var myGrid2 = dhxTabbar.cells("a2").attachGrid();
	myGrid2.setImagePath("./dhtmlxGrid/dhtmlxGrid/codebase/imgs/");
	myGrid2.setHeader("Assistance,Referrals,Contract Date,Follow Up");
	//myGrid2.setHeader("Assistance");	
	myGrid2.setInitWidths("100,300,100,100");
	myGrid2.attachHeader("#select_filter,#text_filter,#text_filter,#text_filter");
	myGrid2.enableAutoWidth(true);
	myGrid2.setColAlign("left,left,right,right");
	myGrid2.setColTypes("ro,ro,ro,ro");
	myGrid2.setColSorting("str,str,date,date");
	myGrid2.setSkin("dhx_skyblue");	
	myGrid2.init();
	
	myGrid.attachEvent("onRowSelect", function(){
		//alert('click event!');
		//myGrid2.loadXML("connectorFRST2a.php?id="+myGrid.getSelectedRowId();
		return true;
	});
	//myGrid.loadXML("./dhtmlxGrid/dhtmlxGrid/myGrid1.xml");    	
    	
//	All about data binding and dhtmlxdatastore: 
//	http://docs.dhtmlx.com/doku.php?id=binding.
//	http://docs.dhtmlx.com/doku.php?id=dhtmlxdatastore:binding_components_to_dhtmlxdatastore
//	http://docs.dhtmlx.com/doku.php?id=dhtmlxdatastore:crud_operations_in_bound_components
//	http://docs.dhtmlx.com/doku.php?id=dhtmlxdatastore:step-by-step_example   <-- EXAMPLE
//	http://docs.dhtmlx.com/doku.php?id=dhtmlxdatastore:datastore_example_server-side   <-- BETTER EXAMPLE
//	http://forum.dhtmlx.com/viewtopic.php?f=19&t=24229 <-- How to capture ID after an add.
//	http://forum.dhtmlx.com/viewtopic.php?f=17&t=23096&p=74242&hilit=datastore+add+record#p74242 <-- How to add form data to datastore.

	myGrid.sync(contacts);
	
	myForm.bind(myGrid);
	
	contacts.attachEvent("onXLE", function(){
		contacts.sort("#LName#","asc");							// Sort data by last name upon load.
	});
	
	myForm.attachEvent("onButtonClick", function(id){
		if (id=='add'){
			//myForm.clear();
			var myuid = (new Date()).valueOf(); 
			myForm.setItemValue("ContactID", myuid);
			//contacts.add({}); 							// Creates a new record that uses 'employees.data.scheme'.
			obj = myForm.getFormData();
			obj.id = myuid;								// Both datastore and grid expect the "id" property on the data object.
			contacts.add(obj);
			contacts.sort("#LName#","asc");
			// http://forum.dhtmlx.com/viewtopic.php?f=14&t=9526&start=10 		<-- Get, select row index.
			// http://docs.dhtmlx.com/doku.php?id=dhtmlxgrid:rows_manipulation 	<-- Row manipulation methods.
			myGrid.selectRow(myGrid.getRowIndex(myuid),false,false,true);		
		}
		else if (id=='change'){
			myForm.save(); 								// Saves the form data changes.
		}
		else if (id=='delete'){ 							// Deletes the selected row.
			var selectedItem = myGrid.getSelectedRowId();
			contacts.remove(selectedItem);
		}
		else if (id=='clear'){
			myForm.clear();
		}
	});	
 	
}

</script>

  </head>

	<body onLoad="doOnLoad()">


		<div class="header">
		    <a class="logo" href="http://intranet" title="City of Fontana Intranet"><img src="http://intranet/images/fontana_logo.jpg" height="79%" border="0"/></a> 
		    <div class="tittle-dhtmlx">City of Fontana&nbsp;&nbsp;-&nbsp;&nbsp;FRST Datastore test</div>
		</div>

		<!--div class='marginl' style="display:block;">
			<h3>FRST Contact Manager</h3>
		</div-->		
		
		<div id="parentId" style="position: relative; top: 20px; left: 20px; width: 1225px; height: 425px; aborder: #B5CDE4 1px solid;"></div>
		
   		<!--div id="tabbar"></div-->
   	</body>
    
</html>    

The problem seems to occur on only newly-created rows
Most probably the id is not updated on client side somehow.

Please try to update datastore with latest version ( attached )
datastore_latest.zip (38.6 KB)

Thank you, I’ll try the new library, Stanislav. I appreciate your kind help!

Hi again, Stanislav,

Unfortunately, the new datastore library made no difference. For some reason the new data doesn’t get pushed back to the form when clicking through the grid rows.

Any other ideas, please? Thanks.

Double check the response after inserting new data, does it contain valid sid and tid in response?
What about server side logs, do they contains any suspicious records for data inserting ?

I have created a local sample with same client side code as you have posted - and it works correctly ( i’m using a fake instead of actual server side code, but still ). If server side responds with valid xml on insert operation - the record can be correctly edited|deleted|selected.

After some more tests I was able to find one issue with ID propogation, which may cause issues in your case.

Please try to use the updated js files.
datastore_130109.zip (37.5 KB)

Greetings, Stanislav,

Thank you so much for your help! I’ll try the new library code, and also the diagnostics you recommended.

Hi again, Stanislav,

The new datastore library, datastore_130109.js, causes the entire screen to go blank. So whatever it’s supposed to be doing, it’s not working.

Would you let me have a copy of the client side code you wrote which you said is working, please? I really need to try to figure out this problem. Many thanks!

Stanislav,

The row is added to the server side database table (as well as to the main grid) as soon as the ‘add’ button is clicked. It seems to me the data just isn’t getting propagated within the client-side datastore in such as a way as to make it immediately available to the form.

Please PM me email to which I can send a demo

Hi, Stanislav,

I added this code:

	myGrid.attachEvent("onRowSelect", function(){
	    alert(myGrid.getSelectedRowId()); // <-- This has no value after adding a row via myForm!

and found out that, when adding a row from the form, the grid doesn’t receive the row ID from the form, even though I have

	myForm.bind(myGrid);	

in my app code. Any thoughts, please? Thank you.

Data binding will not change ID of master record.
When form.save() called, grid locates related record BY ID and updates it with new data. If id in form was changed - grid will not be able to locate new record.

Actually in case of server side saving logic is even more complex

  • form.save() called
  • grid updates data
  • dataprocessor triggered
  • data sent to server side, saved in DB, new id sent back
  • grid changes id of record to one from DB
  • grid pushes new data ( with new id ) to the form

( one of updates in datastore.js, posted above, was related to pushing updated id from grid to form after data saving )

If after data saving you still have old id in the grid - it may be caused by invalid server side response during data saving.

Thank you again Stanislav. I’ll see if I can sort out the problem based on your advice.