This is my view part
Ext.define('A2a.view.act.Job', {
extend: 'Ext.container.Container',
requires: [
'A2a.store.Job',
'A2a.store.SharedData',
],
border: false,
chart: null,
hrer: [],
layout: {type: 'vbox', pack: 'start', align: 'stretch'},
initComponent: function () {
var me = this;
Ext.Ajax.request({
url: utils.createUrl('api', 'dashboard-read'),
async: true,
callback: function(opts, success, response) {
try {
if (success) {
var output = App.decodeHttpResp(response.responseText);
const data = output.data;
var myArr = [];
data.map((date) =>
myArr = Object.keys(date).filter(key => key != 'DATE'));
me.hrer =myArr;
console.log(me.hrer =myArr);
me.loadChart();
//me.loadww();
}
} catch (ex) {
//return ex;
}
}
});
this.loadww();
this.loadData(me.hrer);
me.callParent(arguments);
},
loadData : function () {
console.log("Init Function");
},
loadww: function (hrer) {
var me = this;
//var self = this;
console.log(me.hrer);
me.jobStore = Ext.create('O2a.store.PendingReports');
Ext.apply(me, {
items: [
{
xtype: 'chart',
itemId: 'charid',
name: 'charid',
store : new Ext.create('Ext.data.JsonStore', {
proxy: {
type: 'ajax',
url : utils.createUrl('api', 'dashboard-read'),
reader: {
type: 'json',
root: 'data'
}
},
autoLoad : true,
successProperty : 'success',
fields : [{name: 'DATE', type: 'auto'}].concat(
O2a.store.SharedData.hrer.map(function(companyName) {
console.log(companyName);
return {
name: companyName,
type: 'int'
};
})
)
}),
style: 'background: #fff',
insetPadding: 40,
animate: true,
shadow: false,
flex: 2,
minHeight: 300,
legend: {
position: 'top',
boxStrokeWidth: 0,
labelFont: '12px Helvetica'
},
axes: [{
type: 'Numeric',
position: 'left',
fields: ['1'],
grid: true,
minimum: 0,
}, {
type: 'Category',
position: 'bottom',
fields: ['DATE'],
grid: true,
}],
}]
});
},
loadChart: function (hrer) {
var me = this;
console.log(me.hrer);
var cha = this.down('#charid');
var iii = null;
Ext.Ajax.request({
url: utils.createUrl('api', 'dashboard-read'),
async: true,
callback: function(opts, success, response) {
try {
if (success) {
var output = App.decodeHttpResp(response.responseText);
const data = output.data;
me.hrer
let myArr = [];
data.map((date) =>
myArr = Object.keys(date).filter(key => key != 'DATE'));
cha.series.clear();
for(var i=0;i<myArr.length;i++){
cha.series.add({
type: 'line',
axis: 'left',
xField: 'DATE',
border: false,
flex: 1,
title: myArr[i],
yField: myArr[i],
markerConfig: {
radius: 4
},
highlight: {
fill: '#000',
radius: 5,
'stroke-width': 2,
stroke: '#fff'
},
tips: {
trackMouse: true,
style: 'background: #FFF',
height: 20,
width: 120,
renderer: function (storeItem, item) {
var name = item.series.title[Ext.Array.indexOf(item.series.yField, item.yField)];
this.setTitle(name + ': ' + storeItem.get(item.yField));
}
}
});
}
} else {
//return 'Unknown Reason';
}
} catch (ex) {
//return ex;
}
}
});
}
}
);
I want to pass the hrer inside the loadww method. If I call the loadww inside the callback of initcomponent function I can be able to pass it. But the graph is not loading. If I call it after the ajax request the graph is loading, but can't pass the hrer to outside.
How to pass the hrer array inside the loadww function. Thanks in advance
From the style of the code it looks like this is ExtJS 3.x
In Ext.Ajax.request define the scope with this to stay in the view.
Your code is not in the best shape.
get rid of the try...catch.
try to write success: this.dashboardSuccess
using callback, will run in both cases (success, failure)
If this is ExtJS 4+ you should split your code in MVC
If this is ExtJS 6+ you should split your code in MVVM
write your code declarative
out the stores in VM and use the load-Event
do not use initComponent
use data-binding
Related
When I try to draw a graph, I get an error:echarts.min.js:45 Uncaught TypeError: Bind must be called on a function at bind (<anonymous>) at Bd (echarts.min.js:45:130031)
My echarts-init.js:
let domTemp = document.getElementById("main");
let mytempChart = echarts.init(domTemp, null, {
renderer: 'canvas',
useDirtyRect: false
});
var app = {};
var option;
runDaysDatas(sens_data_result, sens_name_list);
function runDaysDatas(sens_data_result, sens_name_list) {
const sens_names = sens_name_list;
const datasetWithFilters = [];
const seriesList = [];
echarts.util.each(sens_names, function (sens) {
var datasetId = 'dataset_' + sens;
datasetWithFilters.push({
id: datasetId,
fromDatasetId: sens_data_result,
transform: {
type: 'filter',
config: {
and: [
{ dimension: 'Uid', '=': sens }
]
}
}
});
seriesList.push({
type: 'line',
datasetId: datasetId,
showSymbol: false,
name: sens,
endLabel: {
show: true,
formatter: function (params) {
return params.value[3] + ': ' + params.value[0];
}
},
labelLayout: {
moveOverlap: 'shiftY'
},
emphasis: {
focus: 'series'
},
encode: {
x: 'Date',
y: 'Temperature',
label: ['Name', 'Temperature'],
itemName: 'Date',
tooltip: ['Temperature']
}
});
});
option = {
animationDuration: 10000,
dataset: [
{
id: 'dataset_sens_names',
source: sens_data_result
},
...datasetWithFilters
],
title: {
text: 'Temperature for Day'
},
tooltip: {
order: 'valueDesc',
trigger: 'axis'
},
xAxis: {
type: 'category',
nameLocation: 'middle'
},
yAxis: {
name: 'Temperature'
},
grid: {
right: 140
},
series: seriesList
};
mytempChart.setOption(option);
}
In sens_data_result i pass data from api.
In sens_name_list i pass names of the sensors.
The console does not send errors to my script, it swears at the library. I took an example from the official site and remade it for my task, displaying the temperature by time of day with the name of the sensor. There can be N number of graphs on one chart.
Thnx for help!
Okey, i'm a solved the problem, this is decision:
let url = '/api/sensdata';
let domTemp = document.getElementById("main");
let mytempChart = echarts.init(domTemp, null, {
renderer: 'canvas',
useDirtyRect: false
});
var app = {};
var option;
$.get(
url,
sensors_uid,
(_rawData) => {
runDaysDatas(_rawData, sens_name_list);
}
);
function runDaysDatas(_rawData, sens_names) {
const datasetWithFilters = [];
const seriesList = [];
_rawData.unshift(['Name', 'Date', 'Humidity', 'Temperature']);
echarts.util.each(sens_names, function (sens) {
var datasetId = 'dataset_' + sens;
datasetWithFilters.push({
id: datasetId,
fromDatasetId: 'dataset_raw',
transform: {
type: 'filter',
config: {
and: [
{ dimension: 'Name', '=': sens }
]
}
}
});
seriesList.push({
type: 'line',
datasetId: datasetId,
showSymbol: false,
name: sens,
endLabel: {
show: true,
formatter: function (params) {
return 'Uid ' + params.value[0] + ': ' + params.value[3] + '°C';
}
},
labelLayout: {
moveOverlap: 'shiftY'
},
emphasis: {
focus: 'series'
},
encode: {
x: 'Date',
y: 'Temperature',
label: ['Name', 'Temperature'],
itemName: 'Temperature',
tooltip: ['Temperature']
},
});
});
console.log(seriesList);
option = {
toolbox: {
show : true,
feature : {
magicType : {show: true, type: ['line', 'bar']},
restore : {show: true},
saveAsImage : {show: true}
}
},
legend: {},
dataset: [
{
id: 'dataset_raw',
source: _rawData
},
...datasetWithFilters
],
tooltip: {
order: 'valueDesc',
trigger: 'axis'
},
xAxis: {
type: 'time',
nameLocation: 'middle',
axisLabel: {
formatter: (function(value){
moment.locales('RU_ru');
return moment(value).format('MM/DD HH:mm');
})
}
},
yAxis: [
{
type : 'value',
axisLabel : {
formatter: '{value} °C'
}
}
],
grid: {
right: 140
},
series: seriesList
};
mytempChart.clear();
mytempChart.setOption(option);
}
window.addEventListener('resize', mytempChart.resize);
I'm using kogrid to display data as shown below:
My knockout vm makes an ajax call to an MVC controller to retrieve a DTO shaped as follows:
I would like to colour in RED the cell background that have values that failed validation. For example, the 1st element of the data array contains a "CostCentreIsValid" member with a value of "False", so I would like the "Cost Centre (Dim1)" column of the 1st row to be RED. For the same array element, the "AccountIsValid" member contains the value "True", so I would like the "GL Account (Account)" cell of the first row to be GREEN.
Knockout view model:
"use strict";
function ViewModel(interchangeId) {
var edited = function (interchangeId, accountIsValid, costCentreIsValid, supplierIsValid, supplierNo, invoiceNo, costCentre, glAccount, amount, invoiceDesc, originalRec) {
var self = this;
// Properties
self.interchangeId = interchangeId;
self.supplierNo = ko.observable(supplierNo);
self.invoiceNo = ko.observable(invoiceNo);
self.costCentre = ko.observable(costCentre);
self.glAccount = ko.observable(glAccount);
self.amount = ko.observable(amount);
self.invoiceDesc = ko.observable(invoiceDesc);
self.originalRec = originalRec;
}
var editBatchVm = function () {
var self = this;
var $loadingIndicator = $('#loading-indicator');
// Properties
self.recs = ko.observableArray([]);
self.selected = ko.observableArray();
var textEditTemplate = '<div><input type=\"text\" data-bind=\"visible: $parent.selected(), value: $parent.entity[$data.field]" /><span data-bind=\"visible: !$parent.selected(), text: $parent.entity[$data.field]\"></span></div>';
self.columnDefs = [
{ width: 100, field: 'supplierNo', displayName: 'Supplier No', cellTemplate: textEditTemplate },
{ width: 150, field: 'invoiceNo', displayName: 'Invoice No' },
{ width: 150, field: 'costCentre', displayName: 'Cost Centre (Dim1)', cellTemplate: textEditTemplate },
{ width: 200, field: 'glAccount', displayName: 'GL Account (Account)', cellTemplate: textEditTemplate },
{ width: 100, field: 'amount', displayName: 'Amount' },
{ width: 300, field: 'invoiceDesc', displayName: 'Invoice Description' },
];
self.filterOptions = {
filterText: ko.observable(""),
useExternalFilter: false
};
self.pagingOptions = {
currentPage: ko.observable(1),
pageSizes: ko.observableArray([10, 20, 50]),
pageSize: ko.observable(10),
totalServerItems: ko.observable(0)
};
self.sortInfo = ko.observable({ column: { 'field': 'TimeReceived' }, direction: 'desc' });
self.gridOptions = {
data: self.recs,
columnDefs: self.columnDefs,
autogenerateColumns: false,
showGroupPanel: true,
showFilter: true,
filterOptions: self.filterOptions,
enablePaging: true,
pagingOptions: self.pagingOptions,
sortInfo: self.sortInfo,
rowHeight: 35,
selectWithCheckboxOnly: true,
selectedItems: self.selected,
canSelectRows: true,
displaySelectionCheckbox: true,
};
self.batchId = ko.observable();
// Methods
self.get = function () {
$loadingIndicator.show();
$.ajax({
url: BASE_URL + 'EditBatch/GetRecords',
type: 'get',
data: {
'interchangeId': interchangeId
},
contentType: 'application/json; charset=utf-8',
success: function (data) {
var recsArray = [];
$.each(data, function (key, value) {
recsArray.push(
new edited(
interchangeId,
value.AccountIsValid,
value.CostCentreIsValid,
value.SupplierIsValid,
value.Transaction.Voucher[0].Transaction[0].ApArInfo.ApArNo,
value.Transaction.Voucher[0].Transaction[0].ApArInfo.InvoiceNo,
value.Transaction.Voucher[0].Transaction[0].GLAnalysis.Dim1,
value.Transaction.Voucher[0].Transaction[0].GLAnalysis.Account,
value.Transaction.Voucher[0].Transaction[0].Amounts.Amount,
value.Transaction.Voucher[0].Transaction[0].Description,
value.Transaction
)
);
});
self.recs(recsArray);
//batch level info
self.pagingOptions.totalServerItems(data.length);
self.batchId(data[0].BatchId);
}
});
$loadingIndicator.hide();
};
self.resubmit = function () {
var data = { Recs: ko.toJS(this.recs) };
$.ajax({
type: "POST",
url: BASE_URL + 'EditBatch/Resubmit',
data: ko.toJSON(data),
contentType: 'application/json',
async: true,
success: function (data) {
window.location = BASE_URL + 'APInvoicesSummary/Index';
},
error: function (data) {
toastrs(false);
}
});
}
// Subscriptions
self.pagingOptions.pageSize.subscribe(function (data) {
self.pagingOptions.currentPage(1);
self.get();
});
self.pagingOptions.currentPage.subscribe(function (data) {
self.get();
});
self.sortInfo.subscribe(function (data) {
self.pagingOptions.currentPage(1);
self.get();
});
//self.gridOptions.selectedItems.subscribe(function (data) {
// if (data.length > 0) {
// self.date(data[0].date);
// self.voucherNo(data[0].voucherNo);
// self.description(data[0].description);
// self.amount(data[0].amount);
// }
//});
}
/////////////////////////////////////////////////////////////////
// Let's kick it all off
var vm = new editBatchVm();
ko.applyBindings(vm, $("#KoSection")[0]);
vm.get();
};
Has anyone come across examples of how to do this please?
You can bind the style:
<li data-bind="style: { color: !AccountIsValid() ? 'red' }">
Or bind the css:
<li data-bind="css: { failed--account: !AccountIsValid() }">
And then in your stylesheet:
failed--account {
color: red;
}
NOTES
I suposed your data is in a model and AccountIsValid is an observable, if is binded but not observable just remove the parenthesis color: !AccountIsValid.
If your data is not binded you can access it via data[0].AccountIsValid... But I would recommend to bind it.
Here's how I fixed it:
In the site.css
.failed-validation { color: red; }
.passed-validation { color: green; }
and in the knockout js:
var supplierEditTemplate =
`<div><input type=\"text\" data-bind=\"visible: $parent.selected(), value:
$parent.entity[$data.field]" />
<span data-bind=\"visible: !$parent.selected(), text: $parent.entity[$data.field],
css: $parent.entity.supplierIsValid() === 'True' ? \'passed-validation\' : \'failed-validation\'">
</span>
</div>`;
self.columnDefs = [
{ width: 100, field: 'supplierNo', displayName: 'Supplier No', cellTemplate: supplierEditTemplate }];
I have to create the following graph and i have to dynamically load data into it.
Basic Area http://domoticx.com/wp-content/uploads/highcharts-area-basic-standaard.png
Could anyone please help me understanding how can it be done.
Below is where i am able to reach.:
$.ajax({
url: 'EthicsData',
dataType: "json",
type: "GET",
contentType: 'application/json; charset=utf-8',
async: false,
processData: false,
cache: false,
delay: 150,
success: function (data) {
var EthicReg = (data[0].regdet);
var EthicComp = (data[0].compdet);
var EthicsCompletions = new Array();
var EthicsRegistration = new Array();
for (var i in EthicReg) {
var serie = new Array(EthicReg[i].Value, EthicReg[i].year);
EthicsRegistration.push(serie);
}
for (var y in EthicComp) {
var series2 = new Array(EthicComp[y].value,
EthicComp[y].year);
EthicsCompletions.push(series2);
}
DrawEthicsAndCompl(EthicsCompletions, EthicsRegistration)
},
error: function (xhr) {
alert('error');
}
});
};
function DrawEthicsAndCompl(EthicsCompletions, EthicsRegistration) {
debugger;
var chart = new Highcharts.Chart({
chart: {
//plotBackgroundColor: null,
//plotBorderWidth: 1, //null,
//plotShadow: false,
renderTo: 'container1',
type: 'area'
},
title: {
text: 'US and USSR nuclear stockpiles'
},
subtitle: {
text: 'something'
},
xAxis: {
allowDecimals: false,
labels: {
formatter: function () {
return 10; // clean, unformatted number for year
}
}
},
yAxis: {
title: {
text: 'Nuclear weapon states'
},
labels: {
formatter: function () {
return this.value;
}
}
},
tooltip: {
pointFormat: '{series.name} produced <b>{point.y:,.0f}</b><br/>warheads in {point.x}'
},
plotOptions: {
area: {
pointStart: 2010,
marker: {
enabled: false,
symbol: 'circle',
radius: 2,
states: {
hover: {
enabled: true
}
}
}
}
},
series: [{
name: 'Registration',
data: [EthicsRegistration[0]]
}, {
name: 'Completions',
data: [EthicsCompletions[0]]
}]
});
}
Here is the link which demo's same but static data:
(http://jsfiddle.net/gh/get/jquery/1.9.1/highslide-software/highcharts.com/tree/master/samples/highcharts/demo/area-basic/)
Just change the order in which you are pushing items in array , means
Instead
var serie = new Array(EthicReg[i].Value, EthicReg[i].year);
EthicsRegistration.push(serie);
Use
var serie = new Array(EthicReg[i].year, EthicReg[i].Value);
EthicsRegistration.push(serie);
Also , If you are getting year's value don't use pointStart: 2010 instead leave it on the data you are getting from the response above.
Thanks #Nishith for providing the right direction. I modified the code as below:
name: 'Registration',
data: [EthicsRegistration[0][1], EthicsRegistration[1][1], EthicsRegistration[2][1]]
}, {
name: 'Completions',
data: [EthicsCompletions[0][1],EthicsCompletions[1][1],EthicsCompletions[2][1]]
}]
});
I have a pretty simple grid with data source that retrieves data correctly
For that cause I have a schema.parse function defined
The problem is that when I try to update/create new row the schema.parse() called again and the parameter that is passed to it is a string that contains the HTML of my page. cannot really get what the hell is going on there.
thanks
var _dataSource = new kendo.data.DataSource({
transport: {
read: {
dataType: "json",
url: layerDefProvider.getLayerUrlById("surveys") + "/query",
data: {
f: "json",
//token: token,
outFields: "*",
//outSR: 3857,
where: "1=1"
},
type: "POST"
},
create: function (options) {
console.debug("called");//never gets called
},
update: function (options) {
console.debug("called");//never gets called
},
destroy: function (options) {
console.debug("called");//never gets called
}
},
filter: {
field: "OBJECTID", operator: "eq", value: 0
},
schema: {
data:function(response) {
},
parse: function (data) {//on loading it is fine, on updating the data param is a string of my HTML of the page
var rows = [];
var features = data.features;
if (!features) {
return [];
}
for (var i = 0; i < features.length; i++) {
var dataRow = {};
dataRow.OBJECTID = features[i].attributes.OBJECTID;
dataRow.Name = features[i].attributes.Name;
dataRow.Date = features[i].attributes.Date;
dataRow.Comment = features[i].attributes.Comment;
rows.push(dataRow);
}
return rows;
},
model: {
id: "OBJECTID",
fields: {
OBJECTID: { type: "number", editable: false },
Name: { type: "string" },
Date: { type: "string" },
Comment: { type: "string" }
}
}
}
});
var _surveysPicker = $(config.table).kendoGrid({
toolbar: ["create","save"],
editable: true,
dataSource: _dataSource,
height: 300,
sortable: true,
selectable: "multiple",
columnMenu: true,
resizable: true,
columns: [{
field: "OBJECTID",
width: 40
}, {
field: "Name",
width: 40
}, {
field: "Date",
width: 40
}, {
field: "Comment",
width: 100
}]
});
You need to move your parse function inside read event if you need to parse data only on read action.
I am using ajax api calls for getting data from a SQL database as below:
function getJsonData(type, period1, period2, id) {
var dataSource = new kendo.data.DataSource({
transport: {
read: {
type: "GET",
url: createURL(type, period1, period2, id),
dataType: "json",
contentType: "application/json; chartset=utf-8"
}
},
});
return dataSource;
}
Using the above datasource, I am creating a Kendo chart as below:
function stepsChart(container, title, period1, period2) {
var dSource = getJsonData("Summary", period1, period2, "<% = id %>");
$(container).kendoChart({
dataSource: dSource,
seriesColors: ["orangered"],
chartArea: {
background: ""
},
title: {
text:title
},
legend: {
visible: false
},
chartArea: {
background: ""
},
seriesDefaults: {
type: "column",
gap:5
},
series: [{
name: "steps",
field: "steps",
categoryField: "createddate",
aggregate: "sum"
}],
categoryAxis: {
type: "date",
baseUnit: getBaseUnit(period1, period2),
labels: {
rotation: -45,
dateFormats: {
days : getDateFormat(period1, period2),
weeks: getDateFormat(period1, period2),
years: getDateFormat(period1, period2)
},
step: getSteps(period1, period2)
},
majorGridLines: {
visible: false
}
},
valueAxis: {
majorGridLines: {
visible: true
},
labels: {
template: "#= kendo.format('{0}',value/1000)#K"
},
title: {
text: "Steps"
}
}
});
}
I also want to use the data from the above datasource for showing a summary of the information in a div below the chart. But if I add something like
var k = dSource.data;
there will not be any data in k. Is there a way to get the json data in the function which creates the chart?
DataSource.data is a function. I think your code should be:
var k = dSource.data();
That would also return an empty array if the data hasn't already been read, so you might need to do:
dSource.one("change", function () {
var k = dSource.data();
});
dSource.fetch();
because the .fetch() is async.