$(function(){
$.connection.hub.url = "https://js.devexpress.com/Demos/Mvc/signalr";
var hub = $.connection.liveUpdateSignalRHub;
var store = new DevExpress.data.CustomStore({
load: function() {
return hub.server.getAllStocks();
},
key: "Symbol"
});
hub.client.updateStockPrice = function (data) {
store.push([{ type: "update", key: data.Symbol, data: data }]);
};
$.connection.hub.start({ waitForPageLoad: false }).done(function () {
$("#gridContainer").dxDataGrid({
dataSource: store,
showBorders: true,
repaintChangesOnly: true,
highlightChanges: true,
columns: [{
dataField: "LastUpdate",
dataType: "date",
width: 115,
format: "longTime"
}, {
dataField: "Symbol"
}, {
dataField: "Price",
dataType: "number",
format: "#0.####",
cellTemplate: function (container, options) {
container.addClass((options.data.Change > 0) ? "inc" : "dec");
container.html(options.text);
}
}, {
dataField: "Change",
dataType: "number",
width: 140,
format: "#0.####",
cellTemplate: function (container, options) {
var fieldData = options.data;
container.addClass(fieldData.Change > 0 ? "inc" : "dec");
$("<span>")
.addClass("current-value")
.text(options.text)
.appendTo(container);
container.append(" ");
$("<span>")
.addClass("arrow")
.appendTo(container);
container.append(" ");
$("<span>")
.addClass("diff")
.text(fieldData.PercentChange.toFixed(2) + "%")
.appendTo(container);
}
}, {
dataField: "DayOpen",
dataType: "number",
format: "#0.####"
}, {
dataField: "DayMin",
dataType: "number",
format: "#0.####"
}, {
dataField: "DayMax",
dataType: "number",
format: "#0.####"
}]
});
});
});
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>DevExtreme Demo</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>window.jQuery || document.write(decodeURIComponent('%3Cscript src="js/jquery.min.js"%3E%3C/script%3E'))</script>
<script src="https://unpkg.com/signalr/jquery.signalR.js"></script>
<script src="../signalr-hub.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/20.2.4/css/dx.common.css" />
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/20.2.4/css/dx.light.css" />
<script src="https://cdn3.devexpress.com/jslib/20.2.4/js/dx.all.js"></script>
<link rel="stylesheet" type="text/css" href="styles.css" />
<script src="index.js"></script>
</head>
<body class="dx-viewport">
<div class="demo-container">
<div id="gridContainer"></div>
</div>
</body>
</html>
#gridContainer span.current-value {
display: inline-block;
margin-right: 5px;
}
#gridContainer span.diff {
width: 50px;
display: inline-block;
}
#gridContainer .inc {
color: #2ab71b;
}
#gridContainer .dec {
color: #f00;
}
#gridContainer .inc .arrow,
#gridContainer .dec .arrow {
display: inline-block;
height: 10px;
width: 10px;
background-repeat: no-repeat;
background-size: 10px 10px;
}
#gridContainer .inc .arrow {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADKSURBVHjaYtTaLs1ABEiG0nPRJa56PEHhsxBhmCUQT4OyrwHxcXyKmQgYJgHE64CYDYrXQcXIMhCbAcgWkGzgNKh38QUB0QamIUUErkhKI9ZAGyCeTERkTYaqxWsgKA2txhdG6GGsvUNGGpeBRMUiGhCFGsqGzUBQQJsxkA5AemaiG5hDIBIIgQSgK0FmMDACs549kN5FZLjhA7+A2A2U9YSAOBeLAk4gnoBDczoOcSFGPIUDPxB/wCHHiKtwYGKgMhg1cBAaCBBgAJTUIL3ToPZfAAAAAElFTkSuQmCC');
}
#gridContainer .dec .arrow {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADJSURBVHjaYvzPgBfgkhYA4o8QFahKmBioDEYNHIQGsgBxIBCLkqgvAYi/g1mMjMjir0EJzR6If/6HpChKMMgMe3DKBeIcKhiY8x/MYoDj+RQYNgdkGLqBbEB8kgzDToL1YjEQhKWB+BUJhj0H64Eahs1AELYhMpJ+gtUiGYbLQBBOI8LANLBaIg1kAAc0vkiAqSPBQFAkHcNi2DGoHMkGgrAENOCRI0ECRQ2JBoKwJTQCfkLZDPgMZPxPXN5NhtJzMSsJVBMAAgwAyWSY2svfmrwAAAAASUVORK5CYII=');
}