{"id":2016,"date":"2013-10-03T17:05:04","date_gmt":"2013-10-03T13:05:04","guid":{"rendered":"http:\/\/www.dhtmlx.com\/blog\/?p=2016"},"modified":"2026-01-26T13:22:07","modified_gmt":"2026-01-26T10:22:07","slug":"using-dhtmlxgrid-with-node-js","status":"publish","type":"post","link":"https:\/\/dhtmlx.com\/blog\/using-dhtmlxgrid-with-node-js\/","title":{"rendered":"Creating an Editable Grid with DHTMLX and Node.js"},"content":{"rendered":"<p>Node.js is a flexible JavaScript platform that&#8217;s becoming more and more popular these days. In <a href=\"https:\/\/www.dhtmlx.com\/blog\/?p=1975\">the previous article<\/a>, we have described how it can be used with MongoDB. However, you can use Node.js with relational databases as well. It may require a bit more coding but it still results in a quick and flexible solution. Let\u2019s see how to create an online grid with the help of dhtmlxGrid, <a href=\"\/\/dhtmlx.com\/docs\/products\/dhtmlxGrid\/\">JavaScript sortable grid<\/a> component, Node.js, and MySQL database.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/.dhtmlx.com\/blog\/wp-content\/uploads\/2013\/09\/grid-nodejs.png\" alt=\"Grid with Node.js - Demo\" title=\"Grid with Node.js - Demo\" width=\"600\" height=\"178\" class=\"aligncenter size-full wp-image-2020\" srcset=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2013\/09\/grid-nodejs.png 600w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2013\/09\/grid-nodejs-300x89.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>Download the final demo <a href=\"https:\/\/github.com\/DHTMLX\/node-grid-demo\">from GitHub<\/a> or continue reading this tutorial to get the details.<\/p>\n<h3>Creating a Node.js Site<\/h3>\n<p>&nbsp;<br \/>\nJust like in the previous tutorial, we start from creating a simple Node.js site. We use the <a href=\"https:\/\/expressjs.com\/\">Express<\/a> framework and <a href=\"https:\/\/github.com\/mysqljs\/mysql\">node-mysql<\/a>, an open source Node.js driver for MySQL.<\/p>\n<p>First, we create a directory called, for example, <b>&#8216;grid-node&#8217;<\/b>, and install the necessary libraries into this directory by running the following command:<\/p>\n<div class=\"codecolorer-container html4strict default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"html4strict codecolorer\">mkdir grid-node<br \/>\ncd grid-node<br \/>\nnpm install express<br \/>\nnpm install mysql@2.0.0-alpha9<\/div><\/div>\n<p>Then we need to create the base of our demo application. It will be <strong>&#8216;app.js&#8217;<\/strong> file in the <strong>&#8216;grid-node&#8217;<\/strong> directory with the following content:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">var<\/span> express <span class=\"sy0\">=<\/span> require<span class=\"br0\">&#40;<\/span><span class=\"st0\">'express'<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">var<\/span> path <span class=\"sy0\">=<\/span> require<span class=\"br0\">&#40;<\/span><span class=\"st0\">'path'<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"co1\">\/\/connect to the MySQL<\/span><br \/>\n<span class=\"kw1\">var<\/span> mysql &nbsp; &nbsp; &nbsp;<span class=\"sy0\">=<\/span> require<span class=\"br0\">&#40;<\/span><span class=\"st0\">'mysql'<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">var<\/span> db <span class=\"sy0\">=<\/span> mysql.<span class=\"me1\">createConnection<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; host &nbsp; &nbsp; <span class=\"sy0\">:<\/span> <span class=\"st0\">'localhost'<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; user &nbsp; &nbsp; <span class=\"sy0\">:<\/span> <span class=\"st0\">'sampleDB'<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; password <span class=\"sy0\">:<\/span> <span class=\"st0\">'sampleDB'<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; database <span class=\"sy0\">:<\/span> <span class=\"st0\">'sampleDB'<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"co1\">\/\/create express app, use public folder for static files<\/span><br \/>\n<span class=\"kw1\">var<\/span> app <span class=\"sy0\">=<\/span> express<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\napp.<span class=\"me1\">use<\/span><span class=\"br0\">&#40;<\/span>express.<span class=\"kw1\">static<\/span><span class=\"br0\">&#40;<\/span>path.<span class=\"me1\">join<\/span><span class=\"br0\">&#40;<\/span>__dirname<span class=\"sy0\">,<\/span> <span class=\"st0\">'public'<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"co1\">\/\/is necessary for parsing POST request<\/span><br \/>\napp.<span class=\"me1\">use<\/span><span class=\"br0\">&#40;<\/span>express.<span class=\"me1\">bodyParser<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\napp.<span class=\"me1\">listen<\/span><span class=\"br0\">&#40;<\/span><span class=\"nu0\">3000<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>With the Express framework, our demo app is created with a few lines of code. It doesn&#8217;t execute any complex functionality, just serves static files from the <strong>&#8216;public&#8217;<\/strong> directory.<\/p>\n<p><!--more-->Then we create a <strong>&#8216;public&#8217;<\/strong> directory. <a href=\"https:\/\/dhtmlx.com\/x\/download\/grid\/grid_gpl.zip\">Download dhtmlxGrid Standard<\/a> (open source, GPL) and unpack the folder <strong>&#8216;codebase&#8217;<\/strong> from the Grid\u2019s package into the <strong>&#8216;public&#8217;<\/strong> directory. After that, the whole files structure will look like this:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2013\/09\/grid-nodejs-files.png\" alt=\"Grid with Node.js - File Structure\" title=\"Grid with Node.js - File Structure\" width=\"600\" height=\"262\" class=\"aligncenter size-full wp-image-2021\" srcset=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2013\/09\/grid-nodejs-files.png 600w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2013\/09\/grid-nodejs-files-300x131.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>Next, we create an <strong>index.html<\/strong> file in the <strong>&#8216;public&#8217;<\/strong> directory. It will be the main page of our demo app that will contain a grid. The content of the <strong>index.html<\/strong>:<\/p>\n<div class=\"codecolorer-container html4strict default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"html4strict codecolorer\"><span class=\"sc2\">&lt;!doctype html&gt;<\/span><br \/>\n<span class=\"sc2\">&lt;<span class=\"kw2\">head<\/span>&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">meta<\/span> <span class=\"kw3\">http-equiv<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;Content-type&quot;<\/span> <span class=\"kw3\">content<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;text\/html; charset=utf-8&quot;<\/span>&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">title<\/span>&gt;<\/span>Basic initialization<span class=\"sc2\">&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">title<\/span>&gt;<\/span><br \/>\n<span class=\"sc2\">&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">head<\/span>&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">script<\/span> <span class=\"kw3\">src<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;codebase\/dhtmlxcommon.js&quot;<\/span> <span class=\"kw3\">type<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;text\/javascript&quot;<\/span> <span class=\"kw3\">charset<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;utf-8&quot;<\/span>&gt;&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">script<\/span>&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">script<\/span> <span class=\"kw3\">src<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;codebase\/dhtmlxgrid.js&quot;<\/span> <span class=\"kw3\">type<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;text\/javascript&quot;<\/span> <span class=\"kw3\">charset<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;utf-8&quot;<\/span>&gt;&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">script<\/span>&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">script<\/span> <span class=\"kw3\">src<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;codebase\/dhtmlxgridcell.js&quot;<\/span> <span class=\"kw3\">type<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;text\/javascript&quot;<\/span> <span class=\"kw3\">charset<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;utf-8&quot;<\/span>&gt;&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">script<\/span>&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">script<\/span> <span class=\"kw3\">src<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;codebase\/dhtmlxdataprocessor.js&quot;<\/span> <span class=\"kw3\">type<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;text\/javascript&quot;<\/span> <span class=\"kw3\">charset<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;utf-8&quot;<\/span>&gt;&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">script<\/span>&gt;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">link<\/span> <span class=\"kw3\">rel<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;stylesheet&quot;<\/span> <span class=\"kw3\">href<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;codebase\/dhtmlxgrid.css&quot;<\/span> <span class=\"kw3\">type<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;text\/css&quot;<\/span> <span class=\"kw3\">media<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;screen&quot;<\/span> <span class=\"kw3\">title<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;no title&quot;<\/span> <span class=\"kw3\">charset<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;utf-8&quot;<\/span>&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">link<\/span> <span class=\"kw3\">rel<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;stylesheet&quot;<\/span> <span class=\"kw3\">href<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;codebase\/skins\/dhtmlxgrid_dhx_skyblue.css&quot;<\/span> <span class=\"kw3\">type<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;text\/css&quot;<\/span> <span class=\"kw3\">media<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;screen&quot;<\/span> <span class=\"kw3\">title<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;no title&quot;<\/span> <span class=\"kw3\">charset<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;utf-8&quot;<\/span>&gt;<\/span><br \/>\n<br \/>\n<span class=\"sc2\">&lt;<span class=\"kw2\">script<\/span> <span class=\"kw3\">type<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;text\/javascript&quot;<\/span> <span class=\"kw3\">charset<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;utf-8&quot;<\/span>&gt;<\/span><br \/>\n&nbsp; &nbsp; function init() {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; mygrid = new dhtmlXGridObject(&quot;grid_here&quot;);<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; mygrid.setImagePath(&quot;..\/..\/codebase\/imgs\/&quot;);<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; mygrid.setHeader(&quot;Sales, Author, Title, Price&quot;);<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; mygrid.setColumnIds(&quot;sales,author,title,price&quot;);<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; mygrid.setInitWidths(&quot;70,150,*,70&quot;);<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; mygrid.setColTypes(&quot;dyn,ed,ed,ed&quot;);<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; mygrid.setColSorting(&quot;int,str,str,int&quot;);<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; mygrid.setSkin(&quot;dhx_skyblue&quot;);<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; mygrid.init();<br \/>\n&nbsp; &nbsp; }<br \/>\n<span class=\"sc2\">&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">script<\/span>&gt;<\/span> &nbsp; <br \/>\n<br \/>\n<span class=\"sc2\">&lt;<span class=\"kw2\">body<\/span> <span class=\"kw3\">onload<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;init();&quot;<\/span>&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">div<\/span> <span class=\"kw3\">id<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;grid_here&quot;<\/span> <span class=\"kw3\">style<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;width:550px; height:150px;&quot;<\/span>&gt;&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">div<\/span>&gt;<\/span><br \/>\n<span class=\"sc2\">&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">body<\/span>&gt;<\/span><\/div><\/div>\n<p>This is the minimum HTML code needed for working with dhtmlxGrid. The JavaScript files included at the top of the code contain dhtmlxdataprocessor.js, which is not required for basic grid initialization but will be used later for data saving.<\/p>\n<p>If you would like to check what we&#8217;ve got, you can start the nodejs server and open http:\/\/localhost:3000 address in a browser (to start nodejs server, run &#8220;nodejs app.js&#8221; command). If everything is done correctly, you will see an empty grid. <\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2013\/09\/grid-nodejs-empty.png\" alt=\"Grid with Node.js - Empty Grid\" title=\"Grid with Node.js - Empty Grid\" width=\"600\" height=\"206\" class=\"aligncenter size-full wp-image-2024\" srcset=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2013\/09\/grid-nodejs-empty.png 600w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2013\/09\/grid-nodejs-empty-300x103.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<h3>Loading Data in Grid<\/h3>\n<p>&nbsp;<br \/>\nNow we need to fill our grid with data and add some records in it. First, we load data dump in the database:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">CREATE TABLE IF NOT EXISTS `books` <span class=\"br0\">&#40;<\/span><br \/>\n&nbsp; `id` <span class=\"kw5\">int<\/span><span class=\"br0\">&#40;<\/span><span class=\"nu0\">11<\/span><span class=\"br0\">&#41;<\/span> NOT NULL AUTO_INCREMENT<span class=\"sy0\">,<\/span><br \/>\n&nbsp; `sales` <span class=\"kw5\">int<\/span><span class=\"br0\">&#40;<\/span><span class=\"nu0\">11<\/span><span class=\"br0\">&#41;<\/span> NOT NULL<span class=\"sy0\">,<\/span><br \/>\n&nbsp; `author` varchar<span class=\"br0\">&#40;<\/span><span class=\"nu0\">255<\/span><span class=\"br0\">&#41;<\/span> CHARACTER SET utf8 COLLATE utf8_bin NOT NULL<span class=\"sy0\">,<\/span><br \/>\n&nbsp; `title` varchar<span class=\"br0\">&#40;<\/span><span class=\"nu0\">255<\/span><span class=\"br0\">&#41;<\/span> CHARACTER SET utf8 COLLATE utf8_bin NOT NULL<span class=\"sy0\">,<\/span><br \/>\n&nbsp; `price` decimal<span class=\"br0\">&#40;<\/span><span class=\"nu0\">8<\/span><span class=\"sy0\">,<\/span><span class=\"nu0\">2<\/span><span class=\"br0\">&#41;<\/span> NOT NULL<span class=\"sy0\">,<\/span><br \/>\n&nbsp; PRIMARY KEY <span class=\"br0\">&#40;<\/span>`id`<span class=\"br0\">&#41;<\/span><br \/>\n<span class=\"br0\">&#41;<\/span> ENGINE<span class=\"sy0\">=<\/span>InnoDB AUTO_INCREMENT<span class=\"sy0\">=<\/span><span class=\"nu0\">9<\/span> <span class=\"sy0\">;<\/span><br \/>\n<br \/>\nINSERT INTO `books` <span class=\"br0\">&#40;<\/span>`id`<span class=\"sy0\">,<\/span> `sales`<span class=\"sy0\">,<\/span> `author`<span class=\"sy0\">,<\/span> `title`<span class=\"sy0\">,<\/span> `price`<span class=\"br0\">&#41;<\/span> VALUES<br \/>\n<span class=\"br0\">&#40;<\/span><span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">450<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'Jon Duckett'<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'HTML and CSS: Design and Build Websites'<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">16.79<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span><br \/>\n<span class=\"br0\">&#40;<\/span><span class=\"nu0\">3<\/span><span class=\"sy0\">,<\/span> <span class=\"sy0\">-<\/span><span class=\"nu0\">800<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'Steve Krug'<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'Don'<\/span><span class=\"st0\">'t Make Me Think'<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">40.95<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span><br \/>\n<span class=\"br0\">&#40;<\/span><span class=\"nu0\">4<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">800<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'Douglas Crockford'<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'JavaScript: The Good Parts'<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">15.59<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span><br \/>\n<span class=\"br0\">&#40;<\/span><span class=\"nu0\">5<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">1250<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'John Resig'<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'Secrets of the JavaScript Ninja'<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">23.99<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>After that, we add one more handler to <b>app.js<\/b>:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">app.<span class=\"kw1\">get<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'\/data'<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span><span class=\"br0\">&#40;<\/span>req<span class=\"sy0\">,<\/span> res<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; db.<span class=\"me1\">query<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;SELECT * FROM books&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span><span class=\"br0\">&#40;<\/span>err<span class=\"sy0\">,<\/span> rows<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>err<span class=\"br0\">&#41;<\/span> console.<span class=\"me1\">log<\/span><span class=\"br0\">&#40;<\/span>err<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; res.<span class=\"me1\">send<\/span><span class=\"br0\">&#40;<\/span>rows<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>This new handler will be used to load data in the grid. Here we choose all records from the database and send them to the client-side as JSON structure. The code is quite straight and simple. As our table has ID field called &#8220;id&#8221;, we don&#8217;t need to apply any transformations to the data.<\/p>\n<p>There are also some changes required in the <strong>index.html<\/strong> file:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">mygrid.<span class=\"me1\">init<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\nmygrid.<span class=\"me1\">load<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;\/data&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">&quot;js&quot;<\/span><span class=\"br0\">&#41;<\/span><\/div><\/div>\n<p>We have added one more line that initiates data loading using the url described above. &#8220;Load&#8221; command defines data format (the second parameter) as &#8220;js&#8221;. It allows loading data in unified JSON format. The grid will map data from JSON to columns depending on column IDs (we&#8217;ve set IDs earlier with setColumnIds command).<\/p>\n<p>If we now restart the server and open http:\/\/localhost:3000 in a browser, we will see our grid with a few rows loaded from the database.<\/p>\n<h3>Add, Delete, Edit Records in Grid<\/h3>\n<p>&nbsp;<br \/>\nNow we need to make the grid editable, which means the end users will be able to add\/delete\/edit grid records and these changes will be automatically saved to the database. <\/p>\n<p>First, we add UI for data operations in the client-side code of <strong>index.html<\/strong>. The following code will add two buttons to create\/remove rows:<\/p>\n<div class=\"codecolorer-container html4strict default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"html4strict codecolorer\"><span class=\"sc2\">&lt;<span class=\"kw2\">body<\/span> <span class=\"kw3\">onload<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;init();&quot;<\/span>&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">div<\/span> <span class=\"kw3\">id<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;grid_here&quot;<\/span> <span class=\"kw3\">style<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;width:550px; height:150px;&quot;<\/span>&gt;&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">div<\/span>&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">br<\/span>&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">input<\/span> <span class=\"kw3\">style<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;padding:6px;&quot;<\/span> <span class=\"kw3\">type<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;button&quot;<\/span> <span class=\"kw3\">value<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;Add a new record&quot;<\/span> <span class=\"kw3\">onclick<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;addrow()&quot;<\/span>&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sc2\">&lt;<span class=\"kw2\">input<\/span> <span class=\"kw3\">style<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;padding:6px;&quot;<\/span> <span class=\"kw3\">type<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;button&quot;<\/span> <span class=\"kw3\">value<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;Delete the selected record&quot;<\/span> <span class=\"kw3\">onclick<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;deleterow()&quot;<\/span>&gt;<\/span><br \/>\n<span class=\"sc2\">&lt;<span class=\"sy0\">\/<\/span><span class=\"kw2\">body<\/span>&gt;<\/span><\/div><\/div>\n<p>Then, we add the code that initializes dataprocessor in the same <strong>index.html<\/strong> file:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">&nbsp;<span class=\"kw1\">function<\/span> init<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"coMULTI\">\/* ... skipping the previously added code ... *\/<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">var<\/span> dp <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> dataProcessor<span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;\/data&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; dp.<span class=\"me1\">init<\/span><span class=\"br0\">&#40;<\/span>mygrid<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; dp.<span class=\"me1\">enableDataNames<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw2\">true<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; dp.<span class=\"me1\">setTransactionMode<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;POST&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw2\">false<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">function<\/span> addrow<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">var<\/span> id <span class=\"sy0\">=<\/span> mygrid.<span class=\"me1\">uid<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; mygrid.<span class=\"me1\">setActive<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw2\">true<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; mygrid.<span class=\"me1\">addRow<\/span><span class=\"br0\">&#40;<\/span>id<span class=\"sy0\">,<\/span> <span class=\"st0\">&quot;100,New Author,New Book&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">function<\/span> deleterow<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; mygrid.<span class=\"me1\">deleteSelectedRows<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>As you can see, after initialization of the dataprocessor, we have issued a couple of extra commands:<\/p>\n<ul>\n<li><strong>enableDataNames<\/strong> &#8211; enables the mode, in which the dataprocessor uses columns&#8217; IDs as names of parameters<\/li>\n<li><b>setTransactionMode<\/b> &#8211; switches dataprocessor to the mode of simple POST sending<\/li>\n<\/ul>\n<p>&nbsp;<br \/>\nFrom now on, each time when the grid data is changed, the dataprocessor will call &#8220;\/data&#8221; url and will pass the properties of the changed event to the server side.<\/p>\n<p>&#8220;addrow&#8221; and &#8220;deleterow&#8221; functions, combined with related user interface, will allow the end users to add and delete rows in the grid. They are using common grid&#8217;s API.<\/p>\n<p>Now, we&#8217;ll go over to the server code and will add one more handler to the <strong>app.js<\/strong>:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">app.<span class=\"me1\">post<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'\/data'<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span><span class=\"br0\">&#40;<\/span>req<span class=\"sy0\">,<\/span> res<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">var<\/span> data <span class=\"sy0\">=<\/span> req.<span class=\"me1\">body<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">var<\/span> mode <span class=\"sy0\">=<\/span> data<span class=\"br0\">&#91;<\/span><span class=\"st0\">&quot;!nativeeditor_status&quot;<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">var<\/span> sid <span class=\"sy0\">=<\/span> data.<span class=\"me1\">gr_id<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">var<\/span> tid <span class=\"sy0\">=<\/span> sid<span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">var<\/span> sales &nbsp;<span class=\"sy0\">=<\/span> data.<span class=\"me1\">sales<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">var<\/span> author <span class=\"sy0\">=<\/span> data.<span class=\"me1\">author<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">var<\/span> title &nbsp;<span class=\"sy0\">=<\/span> data.<span class=\"me1\">title<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">var<\/span> price &nbsp;<span class=\"sy0\">=<\/span> data.<span class=\"me1\">price<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">function<\/span> update_response<span class=\"br0\">&#40;<\/span>err<span class=\"sy0\">,<\/span> result<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>err<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.<span class=\"me1\">log<\/span><span class=\"br0\">&#40;<\/span>err<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mode <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;error&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">else<\/span> <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>mode <span class=\"sy0\">==<\/span> <span class=\"st0\">&quot;inserted&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tid <span class=\"sy0\">=<\/span> result.<span class=\"me1\">insertId<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; res.<span class=\"me1\">setHeader<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Content-Type&quot;<\/span><span class=\"sy0\">,<\/span><span class=\"st0\">&quot;text\/xml&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; res.<span class=\"me1\">send<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;&lt;data&gt;&lt;action type='&quot;<\/span><span class=\"sy0\">+<\/span>mode<span class=\"sy0\">+<\/span><span class=\"st0\">&quot;' sid='&quot;<\/span><span class=\"sy0\">+<\/span>sid<span class=\"sy0\">+<\/span><span class=\"st0\">&quot;' tid='&quot;<\/span><span class=\"sy0\">+<\/span>tid<span class=\"sy0\">+<\/span><span class=\"st0\">&quot;'\/&gt;&lt;\/data&gt;&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>mode <span class=\"sy0\">==<\/span> <span class=\"st0\">&quot;updated&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; db.<span class=\"me1\">query<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;UPDATE books SET sales = ?, author = ?, title = ?, price = ? WHERE id = ?&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#91;<\/span>sales<span class=\"sy0\">,<\/span> author<span class=\"sy0\">,<\/span> title<span class=\"sy0\">,<\/span> price<span class=\"sy0\">,<\/span> sid<span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; update_response<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">else<\/span> <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>mode <span class=\"sy0\">==<\/span> <span class=\"st0\">&quot;inserted&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; db.<span class=\"me1\">query<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;INSERT INTO books(sales, author, title, price) VALUES (?,?,?,?)&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#91;<\/span>sales<span class=\"sy0\">,<\/span> author<span class=\"sy0\">,<\/span> title<span class=\"sy0\">,<\/span> price<span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; update_response<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">else<\/span> <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>mode <span class=\"sy0\">==<\/span> <span class=\"st0\">&quot;deleted&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; db.<span class=\"me1\">query<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;DELETE FROM books WHERE id = ?&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#91;<\/span>sid<span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span> update_response<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">else<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; res.<span class=\"me1\">send<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Not supported operation&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>Here we use <strong>&#8220;app.post&#8221;<\/strong> because all saving operations use POST queries. The first part of the code defines the type of the operation and gets the data fields from the incoming request. <strong>Important note<\/strong>: in case of grid, the ID of the record is contained in the <strong>data.gr_id<\/strong> property (not <strong>data.id<\/strong> as it might be expected).<\/p>\n<p>Next, depending on the type of the operation, we execute the necessary SQL query. Each type of operation (adding\/saving\/deleting) has its own query text. <\/p>\n<p>As the operations with database are asynchronous, we pass the specified earlier callback function <strong>&#8220;update_response&#8221;<\/strong> as the last parameter. The client side expects to get the confirmation of saving operation or an error message. This is what the <strong>&#8220;update_response&#8221;<\/strong> function is responsible for. It generates an XML response in the necessary format and sends it to the client side (details of the format <a href=\"https:\/\/docs.dhtmlx.com\/index.html\">can be found in the documentation<\/a>). <\/p>\n<p>In case of adding a new record, this the <strong>&#8220;update_response&#8221;<\/strong> function also includes ID generated by MySQL for the new record into the response to update the element\u2019s ID on the client side, too.<\/p>\n<p>If we restart the server and open http:\/\/localhost:3000 in browser again, we\u2019ll get a grid with a few rows. By clicking on the &#8220;Add record&#8221; button, we can add new rows to the grid. Using the &#8220;Delete record&#8221; button, we can delete the selected record in the grid. What&#8217;s more, all the changes are automatically saved in the database and will be available after reloading the page.<\/p>\n<h3>What is the Result?<\/h3>\n<p>&nbsp;<br \/>\nMaybe this server solution is not as flexible as in case of MongoDB, but it is still quite simple to add extra fields or change the logic of data update. It all can be done by tweaking SQL commands. It also won\u2019t be difficult to add data validation or to format data before loading, if needed.<\/p>\n<p>We hope this tutorial helped you to understand how to create an editable datagrid that loads data from MySQL and manages client-server data connection using the Node.js layer. By slightly customizing this code, you can get a solution that allows several users to edit the grid simultaneously (update the data on the client-side without reloading pages). It can be described in a separate tutorial. Leave a comment and tell us if you are interested in such a tutorial.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Node.js is a flexible JavaScript platform that&#8217;s becoming more and more popular these days. In the previous article, we have described how it can be used with MongoDB. However, &#8230;<\/p>\n","protected":false},"author":2,"featured_media":3800,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[71,1,38],"tags":[33,6,14,39],"class_list":["post-2016","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","category-uncategorized","category-visible","tag-all-posts","tag-dhtmlxgrid","tag-tips","tag-nodejs"],"_links":{"self":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/2016","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/comments?post=2016"}],"version-history":[{"count":4,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/2016\/revisions"}],"predecessor-version":[{"id":14989,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/2016\/revisions\/14989"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media\/3800"}],"wp:attachment":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media?parent=2016"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/categories?post=2016"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/tags?post=2016"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}