How to wire Kendo UI Angular Chart to a datasource? - kendo-ui

I have a Kendo UI chart with some series data. When I update the series, the chart data does not change. I see from the documentation that it needs to be wired to a datasource. But the datasource property is not available in Angular tag.
HTML
<kendo-chart
[series]="chartConfig.series"
[valueAxis] ="chartConfig.valueAxes"
[legend]="chartConfig.legend"
[title]="chartConfig.title"
[tooltip]="chartConfig.tooltip"
(seriesClick)="onSeriesClick($event)"
(drag)="onDrag($event)"
(dragStart)="dragStart($event)"
(dragEnd)="dragEnd($event)">
</kendo-chart>
Typescript
public chartConfig = {
title: {
text: 'Insight'
},
legend: {
position: 'bottom'
},
series: [], //Some data
valueAxes: [], //Some data
categoryAxis: {
categories: [],
axisCrossingValues: [24, 24, 0],
justified: true
},
tooltip: {
visible: true,
format: '{0}',
template: '#= category #/03: #= value #'
}
};
When I have an updated value, then I update the series like this.
this.chartConfig.series[seriesIndex].data[xAxisIndex] = parseInt(updatedValue.Value);
But the Chart doesn't get updated.

There is no datasource directive, you don't need anything like that. The problem is Angular not picking up changes to this.chartConfig.series.
Angular change detection checks for reference changes, not simply value changes. The simplest solution for this problem is after whatever updates you perform, change the reference of this.chartConfig.series like so:
this.chartConfig.series[seriesIndex].data[xAxisIndex] = parseInt(updatedValue.Value);
this.chartConfig.series = [...this.chartConfig.series];
That final line basically creates a new array with the same elements as the original and changes the reference of this.chartConfig.series to point to the newly created array. This makes it more likely to be picked up by Angular's change detection.

Related

Aurelia + Kendo - How can I reload a Kendo pie chart after changing data?

I'm attempting to use Aurelia and the Kendo UI Bridge to display data in a pie chart. Due to project requirements, I've got the pie chart widget loading in a custom element. If my data is available before the page loads, everything works fine.
View Model
export class PieChartCustomElement {
chartData = [];
chartSeries = [{
type: 'pie',
startAngle: 150,
field: 'percent',
categoryField: 'languageName'
}];
// other variables
constructor() {
//if I hard-code the data here, all works fine
this.chartData = [
{ languageName: 'English', percent: 62.5 },
{ languageName: 'Spanish', percent: 35 },
{ languageName: 'Esperanto', percent: 2.5 }
];
}
}
View
<template>
<require from="aurelia-kendoui-bridge/chart/chart"></require>
<h4>pie chart custom element</h4>
<ak-chart k-title.bind="title"
k-legend.bind="legend"
k-series-defaults.bind="chartDefaults"
k-series.bind="chartSeries"
k-data-source.bind="chartData"
k-tooltip.bind="tooltip"
k-widget.bind="pieChart"></ak-chart>
</template>
In reality, my data is fetched from a REST API using a promise, so I don't have the data when the page initially loads. Further, I need to pass a parameter to the REST API that comes in via a #bindable attribute on the element, so I cannot populate my data source in the constructor. Hence, something like this:
#bindable({ defaultBindingMode: bindingMode.oneWay }) someArg;
attached() {
// 'api' is injected and is a simple JS class that calls the REST API
this.api.getChartData(this.someArg).then((results) => {
this.chartData = results;
});
}
I'm pretty sure that this is due to the fact that the pie chart widget has already loaded and does not automatically reload when its backing data is changed. If this is actually the case, how do I get the pie chart to reload when I change its data set? If its not, what am I doing wrong?
Working Gist - Comment/uncomment code in the constructor/activate events as indicated to see the behavior.
I believe the method you are looking for is the setDataSource()
In pie-chart.js in the attached() method in your Gist try changing
this.chartData = languageData;
to
this.pieChart.setDataSource(this.chartData);

How to edit OndemandGrid and update to the JSONRest Store

The JsonRest store I created is shown below
var questionBaseURL = "/" + contextName + "/service/questions/" + projectId + "/";
var questionStore = new dojo.store.JsonRest({
target: questionBaseURL,
handleAs: 'json',
idProperty: 'questionId'
});
questionStore = new dojo.store.Observable(questionStore);
var memoryStore = new dojo.store.Memory();
var questionCacheStore = new dojo.store.Cache(questionStore, memoryStore);
Which I use to render into the Grid created as below
var CustomGrid = declare([OnDemandGrid, Keyboard, Selection]);
var questionGrid = new CustomGrid({
store: questionCacheStore,
columns: [
editor({
label: "Questions",
field: "question",
editor: "text",
editOn: "dblclick",
sortable: true,
autoSave:true
})
],
selectionMode: "single",
cellNavigation: false
}, "questions");
questionGrid.startup();
questionGrid.renderArray(questionArray);
The data is properly populated in the grid. Now, since am using "editor", I am able edit the populated data in the grid. I am not sure how exactly to detect if the data has been edited (dirty data ) and which method to call to carry the updated data back to the server. I couldn't find any easy documentation. So any help is appreciated. Thanks in advance
You can use the grid's save method to push all items with dirty data back to the server. There is also a revert method which can be called to discard any dirty data. These are listed in the OnDemandList and OnDemandGrid documentation.
These methods are defined in dgrid/_StoreMixin which is inherited by OnDemandList (and OnDemandGrid). The editor column plugin calls updateDirty (also defined by _StoreMixin) when changes are made, which updates a dirty hash. save will check this hash and call put on the store for each dirty item.

KendoUI - Remote Databinding Fails within "kendoWindow"

I made this topic once, but the information I had was a bit hard to follow and I did not get much help, so I am trying again after spending the day making a JSBIN sample.
I have a situation where I am using KendoUI to make a view model, and also to make some items within it, and when you click on sub-items that are drawn, it opens up a KendoWindow to let you edit them more specifically.
However, there is a problem with the dataSource concept, I think. When I try to bind to a dataSource on my page it works fine; But when I try to bind a kendo control to a remote datasource within a rendered window, it refuses to fetch.
If I bind only to local data, hard coded data, it works; So I know the dropdownlist is working. But I really need to be able to bind to remote data.
I have prepared a JSBIN to show this behavior (or lack thereof)
JSBIN EXAMPLE
Any help would be greatly appreciated. To see the behavior, click on the button to Create Socket Rail, then use the NumericTextBox to increase the size to any number higher than 0, then click on one of the drawn boxes.
You need to create the kendoDropDownList in the kendoWindow.activate event (or at least bind the DataSource there). Adapted from your code, this will work:
kendoWindowWidget = function (options) {
// extend the settings options so that we can take
// explicit configuration from the widget caller.
var settings = $.extend({
resizable: false,
modal: true,
viewable: true,
visible: false,
width: "450px",
height: "450px",
activate: function () {
var myDataSource = new kendo.data.DataSource({
transport: {
read: {
dataType: "json",
url: "http://jsbin.com/UYEbOXi/3/js"
}
}
});
widgets.windows.sockets.type = $('#socket-type').kendoDropDownList({
dataTextField: "Name",
dataValueField: "Id",
dataSource: myDataSource
}).data("kendoDropDownList");
}
}, options);
var $window = $("<div id='kendow-editor-window'/>")
.kendoWindow(settings)
.data("kendoWindow");
$window.databind = function (e) {
kendo.bind($window.element, e);
$window.open().center();
};
// return the created combo box
return $window;
};
Adapted JSBin (I removed a bunch of things to make it easier to manage):
http://jsbin.com/uMuFewI/3/edit

How do I get the row height in a slickgrid formatter?

I'm making a formatter for slickgrid that will display a url as an img tag.
Due to the complexity and performance issues involved slickgrid doesnt support dynamic row heights but it does allow setting the global row height via the options.
var gridOptions = { rowHeight: 64 };
To make the images fit in a reasonable way I want to set the img tag to be the same as, or slightly smaller than the row height.
Neither the columnDef nor dataContext parameters that are passed to the formatter appear to have a reference to the parent grid so I'm not sure how to get the row height set on the grid options.
I'd like to avoid having to hack up the slickgrid scripts to pass through what I need as this makes updating a big PITA!
I could declare the formatter inline I guess and pull in the info via a closure but this isn't as reusable as a standalone formatter implimented in a similar mannor to the default formatters. But this is probably what I'll do for now until a better option presents itself.
Can anyone give me any hints or suggestions?
EDIT:
This does what I want but in a non-reusable mannor. It's not masses of code but it would still be nice to only have to write it once.
var gridOptions = { rowHeight: 64 };
var gridImageFormatter = function ImageFormatter(row, cell, value, columnDef, dataContext) {
return "<img src='" + value + "' style='width:auto;height=" + gridOptions.rowHeight + "' />";
};
var gridColumns = [
{id: "Id", name: "Id", field: "id", width: 250 },
{id: "Name", name: "Name", field: "name", width: 100 },
{id: "Image", name: "Image", field: "image", width: 64, formatter: gridImageFormatter },
{id: "Url", name: "Url", field: "url", width: 250 }
];
EDIT 2:
Using the power of the internet I found a nice little trick for making images autosize if they are bigger that the availible space.
This doesn't work to make smaller images strech to the given space but I can live with that!
How do I auto-resize an image to fit a div container
And this gives us something which works for most cases and is reusable:
function ImageFormatter(row, cell, value, columnDef, dataContext) {
return "<img src='" + value + "' style='max-width:100%;max-height:100%' />";
}

How to customize Ext JS tree nodes properly?

Ext JS 4. I have a tree.Panel where I want to display custom HTML in each node, generated from that node’s model data. I can do this by setting the node’s text when loading the store, but it is not the model’s job to do markup. So I created a custom Column that renders my HTML.
My problem is: unless I derive from Ext.tree.Column, it doesn’t show up properly (no outline, plus/minus icons etc.). If I do, everything is fine, but Ext.tree.Column is marked as private to Ext JS.
Is there some officially supported API to do what I want?
I have written a blog post about how to customize ExtJS 4 tree panel, I hope it will help:
http://hardtouse.com/blog/?p=24
The idea is to use renderer combined with A LOT OF css magic:
columns : [{
xtype : 'treecolumn',
dataIndex : 'name',
renderer : function(value, record){
return Ext.String.format('<div class="tree-font">{0}</div>', value);
}]
Thanks for your answer above. Here is another example showing a few more options for formatting:
columns: [{
xtype: 'treecolumn',
dataIndex: 'text',
flex: 1,
renderer: function (value, metaData, record, rowIndex, colIndex, store, view) {
// see http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.tree.Column-cfg-renderer
var tooltipString = "Hello";
metaData.tdAttr = 'data-qtip="' + tooltipString + '"';
return Ext.String.format('{0} <span style="color:red;">{1}</span>', value, record.data.personname);
}
}]
You might also want to add
hideHeaders : true,
to your tree panel config to remove the "grid" header that appears as a result of using a treecolumn.
Murray

Resources