En este artículo crearemos un cuadro de mandos capaz de mostrar gráficos a partir de datos en tiempo real. Los datos que utilizamos como simulación son la población de una ciudad. Si actualizamos los datos de los residentes, los añadimos o eliminamos, el gráfico cambiará en tiempo real sin necesidad de refrescar desde la página.
Antes de empezar, tenemos que prepararnos:
- Webserver está instalado, consulte Cómo configurar el host virtual XAMPP en Windows 10
. - Yii2 está instalado, véase Cómo instalar Yii2 Advanced a través de Composer
. - Node.js ya está instalado, consulte Crear aplicaciones en tiempo real con Nodes.js
. - Chart.js.
Otros artículos interesantes
Pasos para Crear un Dashboard de Aplicación en Tiempo Real con Yii2, Node.js, MySQL y Chart.js
A. Crear una tabla con MySQL
Cree tablas con el nombre «ciudad» y columnas con los nombres «id» y «población». O es más fácil ejecutar los siguientes scripts sql.
CREATE TABLE 'city' ( 'id' CHAR(16) NOT NULL PRIMARY KEY, 'population' INT(11) NOT NULL DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
B. Crear un servidor Node.js
- Configurar un servidor Node.js como en Crear aplicaciones en tiempo real con Nodes.js.
- En el archivo «server.js», lo que necesitamos crear es una «API» que actualizará los datos en el gráfico que creamos con el Chart.js después de que los datos sean almacenados con éxito por Yii.
- Cuando el usuario abre por primera vez la página del cuadro de mando, comprobamos si los datos iniciales para el gráfico del cuadro de mando están disponibles, si no es así Yii enviará los datos iniciales.
app.post('/status', (req, res) => { res.send(isInitData); }); app.post('/initData', (req, res) => { if(!isInitData){ myData = req.body; isInitData=true; } res.send('success'); });
- A continuación vamos a crear una «API» que actualizará los datos sobre las operaciones crud en Yii.
app.post('/newData', (req, res) => { switch (req.body.actions){ case "create": myData.push({id: req.body.id, population: req.body. population}); break; case "update": let i = myData.findIndex(label => label.id === req.body.id); myData [i] ={id: req.body.id, population: req.body. population}; break; case "delete": let l = myData.findIndex(label => label.id === req.body.id); myData.splice(l,1); break; } io.emit('newData', {id: req.body.id, population: req.body. population, actions:req.body.actions}); res.send('success'); });
- Script completo del archivo server.js
var app = require("express")(); var bodyParser = require('body-parser') var http = require('http'). Server(app); var io = require("socket.io")(http,{cors: {origin:"*"}}); var myData = [] ; var isInitData=false; http.listen(3000, function () { console.log("Listening on 3000"); }); app.use(bodyParser.json({type: 'application/json' })); app.post('/status', (req, res) => { res.send(isInitData); }); app.post('/initData', (req, res) => { if(!isInitData){ myData = req.body; isInitData=true; } res.send('success'); }); app.post('/newData', (req, res) => { switch (req.body.actions){ case "create": myData.push({id: req.body.id, population: req.body. population}); break; case "update": let i = myData.findIndex(label => label.id === req.body.id); myData [i] ={id: req.body.id, population: req.body. population}; break; case "delete": let l = myData.findIndex(label => label.id === req.body.id); myData.splice(l,1); break; } io.emit('newData', {id: req.body.id, population: req.body. population, actions:req.body.actions}); console.log("issuer new data "+req.body.id+" :"+req.body.actions); res.send('success'); }); io.on("connection", (socket) => { console.log("A user is connected"); if(isInitData){ console.log("initial data issuer"); socket.emit('initialData', myData); } });