{"id":729,"date":"2018-06-05T11:13:00","date_gmt":"2018-06-05T11:13:00","guid":{"rendered":"https:\/\/staging.infragistics.com\/blogs\/?p=729"},"modified":"2025-02-25T15:27:01","modified_gmt":"2025-02-25T15:27:01","slug":"angular-grid-with-web-sockets","status":"publish","type":"post","link":"https:\/\/www.infragistics.com\/blogs\/angular-grid-with-web-sockets","title":{"rendered":"High Performance Angular Grid with Web Sockets"},"content":{"rendered":"\n<p>You may have come across the requirement to push data in real time to an Angular Grid. To push data to the browser, you need a technology called WebSocket. You can implement that using NodeJS or ASP.NET SignalR. For the purpose of this article, we will use Web Sockets with NodeJS.&nbsp;<\/p>\n\n\n\n<p>In the first half of this article, we will create an API which will use Web Sockets to push data to the client, and, in second half of the article, we will create an Angular application to consume that. In the Angular application, we will use Ignite UI for Angular Grid. \u00a0However, you can also use a simple HTML table to consume data in real time from web socket. In this article, we will learn to consume data in real time from NodeJS Web Socket in a HTML table as well as Ignite UI\u00a0<a href=\"\/products\/ignite-ui-angular\/angular\/components\/grid\/grid\">Angular Data Grid<\/a>. We will witness difference in performance in these two approaches.<\/p>\n\n\n\n<p>You can learn more about <a href=\"\/products\/ignite-ui-angular\">Ignite UI for Angular<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"nodejs-api\">NodeJS API<\/h2>\n\n\n\n<p>Let us start with creating NodeJS API. Create a blank folder and add a file called <strong>package.json<\/strong>. In package.json, add dependencies of<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Core-js<\/li>\n\n\n\n<li>Express<\/li>\n\n\n\n<li>io<\/li>\n<\/ul>\n\n\n\n<p>&nbsp;More or less your package.json file should look like below:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{\n\u00a0\u00a0\"name\":\u00a0\"demo1\",\n\u00a0\u00a0\"version\":\u00a0\"1.0.0\",\n\u00a0\u00a0\"description\":\u00a0\"nodejs\u00a0web\u00a0socket\u00a0demo\",\n\u00a0\u00a0\"main\":\u00a0\"server.js\",\n\u00a0\u00a0\"dependencies\":\u00a0{\n\u00a0\u00a0\u00a0\u00a0\"core-js\":\u00a0\"^2.4.1\",\n\u00a0\u00a0\u00a0\u00a0\"express\":\u00a0\"^4.16.2\",\n\u00a0\u00a0\u00a0\u00a0\"socket.io\":\u00a0\"^2.0.4\"\n\u00a0\u00a0},\n\u00a0\u00a0\"scripts\":\u00a0{\n\u00a0\u00a0\u00a0\u00a0\"test\":\u00a0\"echo\u00a0\\\"Error:\u00a0no\u00a0test\u00a0specified\\\"\u00a0&amp;&amp;\u00a0exit\u00a01\"\n\u00a0\u00a0},\n\u00a0\u00a0\"author\":\u00a0\"Dhananjay\u00a0Kumar\",\n\u00a0\u00a0\"license\":\u00a0\"ISC\"\n}<\/pre>\n\n\n\n<p>You can pull data from any type of database such as relational data base, No SQL database, etc. However, for purpose of this post, I am going to keep it simple and have hardcoded data in the data.js file. This file will export a JSON array, which we will push using web socket and timer.<\/p>\n\n\n\n<p>Add a file in folder called data.js and add the following code in it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"data-js\">data.js<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">module.exports\u00a0=\u00a0{\n\u00a0\u00a0\u00a0\u00a0data:\u00a0TradeBlotterCDS()\n};\n \nfunction\u00a0TradeBlotterCDS()\u00a0{\n\u00a0\u00a0\u00a0\u00a0return\u00a0[\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"TradeId\":\u00a0\"1\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"TradeDate\":\u00a0\"11\/02\/2016\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"BuySell\":\u00a0\"Sell\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"Notional\":\u00a0\"50000000\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"Coupon\":\u00a0\"500\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"Currency\":\u00a0\"EUR\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"ReferenceEntity\":\u00a0\"Linde\u00a0Aktiengesellschaft\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"Ticker\":\u00a0\"LINDE\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"ShortName\":\u00a0\"Linde\u00a0AG\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"Counterparty\":\u00a0\"MUFJ\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"MaturityDate\":\u00a0\"20\/03\/2023\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"EffectiveDate\":\u00a0\"12\/02\/2016\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"Tenor\":\u00a0\"7\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"RedEntityCode\":\u00a0\"DI537C\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"EntityCusip\":\u00a0\"D50348\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"EntityType\":\u00a0\"Corp\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"Jurisdiction\":\u00a0\"Germany\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"Sector\":\u00a0\"Basic\u00a0Materials\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"Trader\":\u00a0\"Yael\u00a0Rich\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"Status\":\u00a0\"Pending\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\u00a0...\u00a0other\u00a0rows\u00a0of\u00a0data\u00a0\n\u00a0\u00a0\u00a0\u00a0]\n}<\/pre>\n\n\n\n<p>You can find data with 1200 rows <a href=\"https:\/\/gist.github.com\/debugmodedotnet\/50d663fc9d8f825cff31d1d3cf898f42\" rel=\"noopener\">here<\/a>.<\/p>\n\n\n\n<p>&nbsp;From data.js file, we are returning TradeBlotter data. Now in your project folder, you should have two files: package.json and data.js<\/p>\n\n\n\n<p>At this point in time, run the command, <strong>npm install,<\/strong> to install all dependencies mentioned in package.json file. After running command, you will have the <strong>node_modules<\/strong> folder in your project folder. &nbsp;Also, add <strong>server.js<\/strong> file in the project. &nbsp;After all these steps, your project structure should have following files and folders.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>js<\/li>\n\n\n\n<li>js<\/li>\n\n\n\n<li>Node_modules folder<\/li>\n<\/ul>\n\n\n\n<p>&nbsp;In server.js, we will start with first importing required modules,<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">const\u00a0express\u00a0=\u00a0require('express'),\n\u00a0\u00a0\u00a0\u00a0app\u00a0=\u00a0express(),\n\u00a0\u00a0\u00a0\u00a0server\u00a0=\u00a0require('http').createServer(app);\nio\u00a0=\u00a0require('socket.io')(server);\nlet\u00a0timerId\u00a0=\u00a0null,\n\u00a0\u00a0\u00a0\u00a0sockets\u00a0=\u00a0new\u00a0Set();\nvar\u00a0tradedata\u00a0=\u00a0require('.\/data');<\/pre>\n\n\n\n<p>Once required modules are imported, add route-using express as below:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">app.use(express.static(__dirname\u00a0+\u00a0'\/dist'));<\/pre>\n\n\n\n<p>On connecting the socket, we are performing following tasks:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Fetching data<\/li>\n\n\n\n<li>Starting timer(We will talk about this function later in the post)<\/li>\n\n\n\n<li>On disconnect event deleting the socket<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">io.on('connection',\u00a0socket\u00a0=>\u00a0{\n \n\u00a0\u00a0\u00a0\u00a0console.log(`Socket\u00a0${socket.id}\u00a0added`);\n\u00a0\u00a0\u00a0\u00a0localdata\u00a0=\u00a0tradedata.data;\n\u00a0\u00a0\u00a0\u00a0sockets.add(socket);\n\u00a0\u00a0\u00a0\u00a0if\u00a0(!timerId)\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0startTimer();\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0socket.on('clientdata',\u00a0data\u00a0=>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0console.log(data);\n\u00a0\u00a0\u00a0\u00a0});\n\u00a0\u00a0\u00a0\u00a0socket.on('disconnect',\u00a0()\u00a0=>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0console.log(`Deleting\u00a0socket:\u00a0${socket.id}`);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0sockets.delete(socket);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0console.log(`Remaining\u00a0sockets:\u00a0${sockets.size}`);\n\u00a0\u00a0\u00a0\u00a0});\n \n});<\/pre>\n\n\n\n<p>Next we have to implement, <strong>startTimer()<\/strong> function. In this function, we are using JavaScript <strong>setInterval()<\/strong> function and emitting data in each 10 millisecond time frame.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">function\u00a0startTimer()\u00a0{\n\u00a0\u00a0\u00a0\u00a0timerId\u00a0=\u00a0setInterval(()\u00a0=>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0(!sockets.size)\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0clearInterval(timerId);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timerId\u00a0=\u00a0null;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0console.log(`Timer\u00a0stopped`);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0updateData();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for\u00a0(const\u00a0s\u00a0of\u00a0sockets)\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0s.emit('data',\u00a0{\u00a0data:\u00a0localdata\u00a0});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n \n\u00a0\u00a0\u00a0\u00a0},\u00a010);\n}<\/pre>\n\n\n\n<p>We are calling a function updateData() which will update data. In this function, we are looping through local data and updating two properties, Coupon and Notional, with random number between ranges.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">function\u00a0updateData()\u00a0{\n\u00a0\u00a0\u00a0\u00a0localdata.forEach(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0(a)\u00a0=>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0a.Coupon\u00a0=\u00a0getRandomInt(10,\u00a0500);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0a.Notional\u00a0=\u00a0getRandomInt(1000000,\u00a07000000);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\n}<\/pre>\n\n\n\n<p>We have implemented getRandomInit function as shown below:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">function\u00a0getRandomInt(min,\u00a0max)\u00a0{\n\u00a0\u00a0\u00a0\u00a0min\u00a0=\u00a0Math.ceil(min);\n\u00a0\u00a0\u00a0\u00a0max\u00a0=\u00a0Math.floor(max);\n\u00a0\u00a0\u00a0\u00a0return\u00a0Math.floor(Math.random()\u00a0*\u00a0(max\u00a0-\u00a0min))\u00a0+\u00a0min;\n}<\/pre>\n\n\n\n<p>By putting everything together, sever.js should have following code<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"server-js\">Server.js <\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">const\u00a0express\u00a0=\u00a0require('express'),\n\u00a0\u00a0\u00a0\u00a0app\u00a0=\u00a0express(),\n\u00a0\u00a0\u00a0\u00a0server\u00a0=\u00a0require('http').createServer(app);\nio\u00a0=\u00a0require('socket.io')(server);\nlet\u00a0timerId\u00a0=\u00a0null,\n\u00a0\u00a0\u00a0\u00a0sockets\u00a0=\u00a0new\u00a0Set();\nvar\u00a0tradedata\u00a0=\u00a0require('.\/data');\n \nvar\u00a0localdata;\n \napp.use(express.static(__dirname\u00a0+\u00a0'\/dist'));\n \nio.on('connection',\u00a0socket\u00a0=>\u00a0{\n \n\u00a0\u00a0\u00a0\u00a0console.log(`Socket\u00a0${socket.id}\u00a0added`);\n\u00a0\u00a0\u00a0\u00a0localdata\u00a0=\u00a0tradedata.data;\n\u00a0\u00a0\u00a0\u00a0sockets.add(socket);\n\u00a0\u00a0\u00a0\u00a0if\u00a0(!timerId)\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0startTimer();\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0socket.on('clientdata',\u00a0data\u00a0=>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0console.log(data);\n\u00a0\u00a0\u00a0\u00a0});\n\u00a0\u00a0\u00a0\u00a0socket.on('disconnect',\u00a0()\u00a0=>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0console.log(`Deleting\u00a0socket:\u00a0${socket.id}`);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0sockets.delete(socket);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0console.log(`Remaining\u00a0sockets:\u00a0${sockets.size}`);\n\u00a0\u00a0\u00a0\u00a0});\n \n});\n \nfunction\u00a0startTimer()\u00a0{\n\u00a0\u00a0\u00a0\u00a0timerId\u00a0=\u00a0setInterval(()\u00a0=>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0(!sockets.size)\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0clearInterval(timerId);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timerId\u00a0=\u00a0null;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0console.log(`Timer\u00a0stopped`);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0updateData();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for\u00a0(const\u00a0s\u00a0of\u00a0sockets)\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0s.emit('data',\u00a0{\u00a0data:\u00a0localdata\u00a0});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n \n\u00a0\u00a0\u00a0\u00a0},\u00a010);\n}\n \nfunction\u00a0getRandomInt(min,\u00a0max)\u00a0{\n\u00a0\u00a0\u00a0\u00a0min\u00a0=\u00a0Math.ceil(min);\n\u00a0\u00a0\u00a0\u00a0max\u00a0=\u00a0Math.floor(max);\n\u00a0\u00a0\u00a0\u00a0return\u00a0Math.floor(Math.random()\u00a0*\u00a0(max\u00a0-\u00a0min))\u00a0+\u00a0min;\n}\n \nfunction\u00a0updateData()\u00a0{\n\u00a0\u00a0\u00a0\u00a0localdata.forEach(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0(a)\u00a0=>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0a.Coupon\u00a0=\u00a0getRandomInt(10,\u00a0500);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0a.Notional\u00a0=\u00a0getRandomInt(1000000,\u00a07000000);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\n}\n \nserver.listen(8080);\nconsole.log('Visit\u00a0http:\/\/localhost:8080\u00a0in\u00a0your\u00a0browser');<\/pre>\n\n\n\n<p>We have created Web Sockets in NodeJS, which is returning data chunk each 10 milliseconds.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"creating-angular-application\">Creating Angular Application<\/h2>\n\n\n\n<p>In this step, let us create Angular application. We are going to use Angular CLI to create an application and then add Ignite UI for Angular Grid. Follow the below article to create an Angular application and add Ignite UI for Angular Grid in the application.<\/p>\n\n\n\n<p>If you are following above article, you need &nbsp;changes in step three in which we are creating Angular service to consume API.<\/p>\n\n\n\n<p>Let us start with installing socket.io-client in Angular project. To do that run npm install,<\/p>\n\n\n\n<p><strong>npm i&nbsp;socket.io-client<\/strong><\/p>\n\n\n\n<p>We will write an Angular service to create the connection with NodeJS Web Socket. In app.service.ts, let us start with importing.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import\u00a0{\u00a0Injectable\u00a0}\u00a0from\u00a0'@angular\/core';\nimport\u00a0{\u00a0Observable\u00a0}\u00a0from\u00a0'rxjs\/Observable';\nimport\u00a0{\u00a0Observer\u00a0}\u00a0from\u00a0'rxjs\/Observer';\nimport\u00a0{\u00a0map,\u00a0catchError\u00a0}\u00a0from\u00a0'rxjs\/operators';\nimport\u00a0*\u00a0as\u00a0socketIo\u00a0from\u00a0'socket.io-client';\nimport\u00a0{\u00a0Socket\u00a0}\u00a0from\u00a0'.\/interfaces';<\/pre>\n\n\n\n<p>We have imported required modules. Later we will see how socket type is defined inside interface.ts file. Next, let us create make connection to Web Socket and fetch next data from the response. Before returning the next data chunk from the web socket, we are converting that to an Observable.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">getQuotes():\u00a0Observable\u00a0&lt;\u00a0any\u00a0>\u00a0{\n\u00a0\u00a0\u00a0\u00a0this.socket\u00a0=\u00a0socketIo('http:\/\/localhost:8080');\n\u00a0\u00a0\u00a0\u00a0this.socket.on('data',\u00a0(res)\u00a0=>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.observer.next(res.data);\n\u00a0\u00a0\u00a0\u00a0});\n\u00a0\u00a0\u00a0\u00a0return\u00a0this.createObservable();\n}\n \ncreateObservable():\u00a0Observable\u00a0&lt;\u00a0any\u00a0>\u00a0{\n\u00a0\u00a0\u00a0\u00a0return\u00a0new\u00a0Observable&lt;any>(observer\u00a0=>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.observer\u00a0=\u00a0observer;\n\u00a0\u00a0\u00a0\u00a0});\n}<\/pre>\n\n\n\n<p>The above two functions, will make connection to web socket, fetch data chunk, and convert that to observable. Putting everything together, app.service.ts will look like the below:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import\u00a0{\u00a0Injectable\u00a0}\u00a0from\u00a0'@angular\/core';\nimport\u00a0{\u00a0Observable\u00a0}\u00a0from\u00a0'rxjs\/Observable';\nimport\u00a0{\u00a0Observer\u00a0}\u00a0from\u00a0'rxjs\/Observer';\nimport\u00a0{\u00a0map,\u00a0catchError\u00a0}\u00a0from\u00a0'rxjs\/operators';\nimport\u00a0*\u00a0as\u00a0socketIo\u00a0from\u00a0'socket.io-client';\nimport\u00a0{\u00a0Socket\u00a0}\u00a0from\u00a0'.\/interfaces';\n \n@Injectable()\nexport\u00a0class\u00a0AppService\u00a0{\n \n\u00a0\u00a0\u00a0\u00a0socket:\u00a0Socket;\n\u00a0\u00a0\u00a0\u00a0observer:\u00a0Observer&lt;any>;\n \n\u00a0\u00a0\u00a0\u00a0getQuotes():\u00a0Observable&lt;any>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.socket\u00a0=\u00a0socketIo('http:\/\/localhost:8080');\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.socket.on('data',\u00a0(res)\u00a0=>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.observer.next(res.data);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0this.createObservable();\n\u00a0\u00a0\u00a0\u00a0}\n \n\u00a0\u00a0\u00a0\u00a0createObservable():\u00a0Observable&lt;any>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0new\u00a0Observable&lt;any>(observer\u00a0=>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.observer\u00a0=\u00a0observer;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\n\u00a0\u00a0\u00a0\u00a0}\n \n\u00a0\u00a0\u00a0\u00a0private\u00a0handleError(error)\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0console.error('server\u00a0error:',\u00a0error);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0(error.error\u00a0instanceof\u00a0Error)\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0let\u00a0errMessage\u00a0=\u00a0error.error.message;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0Observable.throw(errMessage);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0Observable.throw(error\u00a0||\u00a0'Socket.io\u00a0server\u00a0error');\n\u00a0\u00a0\u00a0\u00a0}\n \n}<\/pre>\n\n\n\n<p>In the service, we are using a type called Socket. We created this type in file <strong>interfaces.ts<\/strong> as below:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">export\u00a0interface\u00a0Socket\u00a0{\n\u00a0\u00a0\u00a0\u00a0on(event:\u00a0string,\u00a0callback:\u00a0(data:\u00a0any)\u00a0=>\u00a0void);\n\u00a0\u00a0\u00a0\u00a0emit(event:\u00a0string,\u00a0data:\u00a0any);\n}<\/pre>\n\n\n\n<p>Now Angular service is ready which will make connection to NodeJS Web socket and fetch data from the API as observable.<\/p>\n\n\n\n<p>This is normal Angular service and can be consumed in a component in the usual way. Start with importin that in the module and then injecting that in component constructor as shown below:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">constructor(private\u00a0dataService:\u00a0AppService)\u00a0{\u00a0}<\/pre>\n\n\n\n<p>we can call service method to fetch data in OnInit life cycle,<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ngOnInit()\u00a0{\n\u00a0\u00a0\u00a0\u00a0this.sub\u00a0=\u00a0this.dataService.getQuotes()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.subscribe(quote\u00a0=>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.stockQuote\u00a0=\u00a0quote;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0console.log(this.stockQuote);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\n}<\/pre>\n\n\n\n<p>Putting everything together, component class will look like the below.&nbsp;&nbsp;&nbsp;<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import\u00a0{\u00a0Component,\u00a0OnInit,\u00a0OnDestroy\u00a0}\u00a0from\u00a0'@angular\/core';\nimport\u00a0{\u00a0AppService\u00a0}\u00a0from\u00a0'.\/app.service';\nimport\u00a0{\u00a0Subscription\u00a0}\u00a0from\u00a0'rxjs\/Subscription';\n \n@Component({\n\u00a0\u00a0\u00a0\u00a0selector:\u00a0'app-root',\n\u00a0\u00a0\u00a0\u00a0templateUrl:\u00a0'.\/app.component.html'\n})\nexport\u00a0class\u00a0AppComponent\u00a0implements\u00a0OnInit,\u00a0OnDestroy\u00a0{\n \n\u00a0\u00a0\u00a0\u00a0stockQuote:\u00a0number;\n\u00a0\u00a0\u00a0\u00a0sub:\u00a0Subscription;\n\u00a0\u00a0\u00a0\u00a0columns:\u00a0number;\n\u00a0\u00a0\u00a0\u00a0rows:\u00a0number;\n\u00a0\u00a0\u00a0\u00a0selectedTicker:\u00a0string;\n \n\u00a0\u00a0\u00a0\u00a0constructor(private\u00a0dataService:\u00a0AppService)\u00a0{\u00a0}\n \n\u00a0\u00a0\u00a0\u00a0ngOnInit()\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.sub\u00a0=\u00a0this.dataService.getQuotes()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.subscribe(quote\u00a0=>\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.stockQuote\u00a0=\u00a0quote;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0console.log(this.stockQuote);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0ngOnDestroy()\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.sub.unsubscribe();\n\u00a0\u00a0\u00a0\u00a0}\n}<\/pre>\n\n\n\n<p>One important thing you may want to notice is that we are unsubscribing the observable returned in OnDestroy life cycle hook of the component. &nbsp;On the template, simply render data in table as below:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;table>\n\u00a0\u00a0\u00a0\u00a0&lt;tr\u00a0*ngFor=\"let\u00a0f\u00a0of\u00a0stockQuote\">\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;td>{{f.TradeId}}&lt;\/td>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;td>{{f.TradeDate}}&lt;\/td>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;td>{{f.BuySell}}&lt;\/td>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;td>{{f.Notional}}&lt;\/td>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;td>{{f.Coupon}}&lt;\/td>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;td>{{f.Currency}}&lt;\/td>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;td>{{f.ReferenceEntity}}&lt;\/td>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;td>{{f.Ticker}}&lt;\/td>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;td>{{f.ShortName}}&lt;\/td>\n\u00a0\u00a0\u00a0\u00a0&lt;\/tr>\n&lt;\/table><\/pre>\n\n\n\n<p>&nbsp;Since we are rendering data in real time in a normal HTML table, you may experience flickering and some performance issue. Let us replace HTML table with Ignite UI for Angular grid.<\/p>\n\n\n\n<p>Learn more about Ignite UI for Angular Grid here: <a href=\"\/products\/ignite-ui-angular\/angular\/components\/grid.html\">https:\/\/www.infragistics.com\/products\/ignite-ui-angular\/angular\/components\/grid.html<\/a>.<\/p>\n\n\n\n<p>You can add Ignite UI Grid in Angular application as shown below. We have set data source of the igxGrid using data property binding and then manually adding columns to the grid.<br><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;igx-grid\u00a0[width]=\"'1172px'\"\u00a0#grid1\u00a0id=\"grid1\"\u00a0[rowHeight]=\"30\"\u00a0[data]=\"stockQuote\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[height]=\"'600px'\"\u00a0[autoGenerate]=\"false\">\n\u00a0\u00a0\u00a0\u00a0&lt;igx-column\u00a0[pinned]=\"true\"\u00a0[sortable]=\"true\"\u00a0width=\"50px\"\u00a0field=\"TradeId\"\u00a0header=\"Trade\u00a0Id\"\u00a0[dataType]=\"'number'\">\u00a0&lt;\/igx-column>\n\u00a0\u00a0\u00a0\u00a0&lt;igx-column\u00a0[sortable]=\"true\"\u00a0width=\"120px\"\u00a0field=\"TradeDate\"\u00a0header=\"Trade\u00a0Date\"\u00a0dataType=\"string\">&lt;\/igx-column>\n\u00a0\u00a0\u00a0\u00a0&lt;igx-column\u00a0width=\"70px\"\u00a0field=\"BuySell\"\u00a0header=\"Buy\u00a0Sell\"\u00a0dataType=\"string\">&lt;\/igx-column>\n\u00a0\u00a0\u00a0\u00a0&lt;igx-column\u00a0[sortable]=\"true\"\u00a0[dataType]=\"'number'\"\u00a0width=\"110px\"\u00a0field=\"Notional\"\u00a0header=\"Notional\">\n\u00a0\u00a0\u00a0\u00a0&lt;\/igx-column>\n\u00a0\u00a0\u00a0\u00a0&lt;igx-column\u00a0width=\"120px\"\u00a0[sortable]=\"true\"\u00a0field=\"Coupon\"\u00a0header=\"Coupon\"\u00a0dataType=\"number\">&lt;\/igx-column>\n\u00a0\u00a0\u00a0\u00a0&lt;igx-column\u00a0[sortable]=\"true\"\u00a0width=\"100px\"\u00a0field=\"Price\"\u00a0header=\"Price\"\u00a0dataType=\"number\">\n\u00a0\u00a0\u00a0\u00a0&lt;\/igx-column>\n\u00a0\u00a0\u00a0\u00a0&lt;igx-column\u00a0width=\"100px\"\u00a0field=\"Currency\"\u00a0header=\"Currency\"\u00a0dataType=\"string\">&lt;\/igx-column>\n\u00a0\u00a0\u00a0\u00a0&lt;igx-column\u00a0width=\"350px\"\u00a0field=\"ReferenceEntity\"\u00a0header=\"Reference\u00a0Entity\"\u00a0dataType=\"string\">&lt;\/igx-column>\n\u00a0\u00a0\u00a0\u00a0&lt;igx-column\u00a0[sortable]=\"true\"\u00a0[pinned]=\"true\"\u00a0width=\"130px\"\u00a0field=\"Ticker\"\u00a0header=\"Ticker\"\u00a0dataType=\"string\">&lt;\/igx-column>\n\u00a0\u00a0\u00a0\u00a0&lt;igx-column\u00a0width=\"350px\"\u00a0field=\"ShortName\"\u00a0header=\"Short\u00a0Name\"\u00a0dataType=\"string\">&lt;\/igx-column>\n&lt;\/igx-grid><\/pre>\n\n\n\n<p>Few points you should focus on in the grid we created:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>By&nbsp;default&nbsp;virtualization is enabled on the Ignite UI for Angular grid.<\/li>\n\n\n\n<li>By setting sortable property, you can enable sorting on the particular column.<\/li>\n\n\n\n<li>By setting pinned property, you can pin a column to the left of the grid.<\/li>\n\n\n\n<li>By setting data property, you can set data source of the grid.<\/li>\n\n\n\n<li>You can add columns manually by using &lt;igx-column\/&gt;.<\/li>\n\n\n\n<li>Field and header of &lt;igx-column\/&gt; is used to set field property and header of the column.<\/li>\n<\/ol>\n\n\n\n<p>Now when you run the application, you will find grid is updating in real time with data and also not flickering. You will find grid is updating every 10 milliseconds. You should have grid running with data getting updated in real time as shown below:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/static.infragistics.com\/marketing\/Blogs\/Migration\/00\/00\/00\/09\/43\/High-Perfmance-Grid.gif\" alt=\"  grid running with data getting updated in real time as shown\" title=\" grid running with data getting updated in real time as shown\"\/><\/figure>\n\n\n\n<p>In this way, you can push data in real time using NodeJS Web Socket API in Angular application. I hope you find this article useful. If you like this post, please share it. Also, if you have not checked out&nbsp;<a href=\"\/products\/ignite-ui-angular\">Infragistics Ignite UI for Angular Components<\/a>, be sure to do so! They have 50+ Material-based Angular components to help you code web apps faster.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You may have come across the requirement to push data in real time to an Angular Grid. To push data to the browser, you need a technology called WebSocket. You can implement that using NodeJS or ASP.NET SignalR. For the purpose of this article, we will use Web Sockets with NodeJS.\u00a0<\/p>\n","protected":false},"author":65,"featured_media":1424,"comment_status":"publish","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[],"class_list":["post-729","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-angular"],"_links":{"self":[{"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/posts\/729","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/users\/65"}],"replies":[{"embeddable":true,"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/comments?post=729"}],"version-history":[{"count":2,"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/posts\/729\/revisions"}],"predecessor-version":[{"id":2201,"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/posts\/729\/revisions\/2201"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/media\/1424"}],"wp:attachment":[{"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/media?parent=729"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/categories?post=729"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/tags?post=729"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}