Kendo Pie Chart to Bar Chart - kendo-ui

I am trying to go from a Kendo Pie chart to a Kendo Bar chart, my issue is the bar chart only returns one piece of data.
cshtml
`
<div id="pieEmployeeContainer">
#(Html.Kendo().Chart<SalesChart>().Name("pieEmployee").HtmlAttributes(new { style = "width: 90%;", #class = "fpos-chart" })
.Title("Top 10")
.Legend(false)
.Theme("bootstrap")
.DataSource(ds => ds.Read("SM_GetSalesByEmployees", "Home"))
.Series(s => s
.Pie(m => m.Total, m => m.Category)
.Padding(0)
)
.Tooltip(t => t
.Visible(true)
.Format("{0:c}")
.Template("#= category # <br /> #= kendo.format('{0:c}', value) # (#= kendo.format('{0:p}', percentage)#)")
)
.Events(e => e.SeriesClick("getByEmployee"))
.Deferred()
)
</div>
`
Controller
public ActionResult SM_GetSalesByEmployees()
{
List<SalesChart> items;
List<SalesChart> salesByEmpl;
using (StreamReader r = new StreamReader("C:\\Development\\Back Office Web\\Sandbox\\BackOffice.Web\\BackOffice.Web\\Content\\Data\\SalesByEmployee.json"))
{
string json = r.ReadToEnd();
items = JsonConvert.DeserializeObject<List<SalesChart>>(json);
salesByEmpl = items.GroupBy(l => l.EmployeeName)
.Select(lg =>
new SalesChart
{
Category = lg.Key,
Total = lg.Sum(w => w.Total)
}).ToList();
}
return new CustomJsonResult
{
Data = salesByEmpl
};
}
script
function getByEmployee(e)
{
var categorySelected = e.category;
var chart = $("#pieEmployee").data("kendoChart");
$.post("Home/GetSalesByEmployee?EmpName=" + categorySelected, function (results) {
chart.setDataSource(new kendo.data.DataSource({ data: results }));
});
chart.options.series[0].type = "bar";
chart.options.series[0].ValueAxis = "${Total}";
chart.options.series[0].categoryAxis = "{Category}";
chart.options.categoryAxis.baseUnit = "months";
chart.refresh();
}
I dont have a good enough reputation to post images, sorry about that.
The bar chart is only getting one data point and displaying that, rather than showing all data.
Any help is greatly appreciated.

I can't build out any test stuff but from quickly looking at it, the data format for the pie chart needs to be changed. It needs to be in percentages (the whole series needs to = 100) so you'll need to convert the data either in the view or the controller.

Related

Pie chart not updating properly when using brush in series chart

I have 1 pie chart and 1 series line chart with brush. Currently when I brushing the pie chart updates, but shows the same result regardless of the selected range. How to make brush work correctly?
const pieChart = dc.pieChart('#piechart');
const chart = dc.seriesChart('#chart');
const groupParameter = 'markdown';
const data = d3.csvParse(d3.select('pre#data').text());
data.forEach(d => {
d.week = +d.week;
d.markdown = +d.markdown;
});
const ndx = crossfilter(data);
const pieDimension = ndx.dimension(d => d.itemCategory);
const dimension = ndx.dimension(d => [d.itemCategory, d.week]);
const pieGroup = pieDimension.group().reduceSum(d => d[groupParameter]);
const group = dimension.group().reduceSum(d => d[groupParameter]);
pieChart
.width(768)
.height(480)
.dimension(pieDimension)
.group(pieGroup)
.legend(dc.legend());
chart
.width(768)
.height(480)
.chart(c => dc.lineChart(c).curve(d3.curveCardinal))
.x(d3.scaleLinear().domain([27, 38]))
.brushOn(true)
.yAxisLabel(groupParameter)
.yAxisPadding('5%')
.xAxisLabel('Week')
.elasticY(true)
.dimension(dimension)
.group(group)
.mouseZoomable(true)
.seriesAccessor(d => d.key[0])
.keyAccessor(d => d.key[1])
.valueAccessor(d => d.value)
.legend(
dc
.legend()
.itemHeight(13)
.gap(5)
.horizontal(1)
.legendWidth(140)
.itemWidth(70)
);
chart.margins().left += 100;
dc.renderAll();
https://jsfiddle.net/qwertypomy/L37d01e5/#&togetherjs=HF15j0M5pH
It doesn't look like brushing was ever properly implemented for series charts.
The issue is that the dimension key for series chart is a 2-dimensional array, but a normal RangedFilter is applied, which doesn't understand these keys.
You can manually apply a filter handler which looks at the right part of the key:
chart.filterHandler(function(dimensions, filters) {
if (filters.length === 0) {
dimension.filter(null);
} else {
var filter = dc.filters.RangedFilter(filters[0][0], filters[0][1]);
dimension.filterFunction(function(k) {
return filter.isFiltered(k[1]);
});
}
return filters;
});
Actually, I'm not sure if there is an elegant way to fix this. I've started an issue to track it: https://github.com/dc-js/dc.js/issues/1471
EDIT: This doesn't work unless it's applied to both the series chart and all of its children. Horribly inefficient, but like so:
function filterHandler(dimensions, filters) {
if (filters.length === 0) {
dimension.filter(null);
} else {
var filter = dc.filters.RangedFilter(filters[0][0], filters[0][1]);
dimension.filterFunction(function(k) {
return filter.isFiltered(k[1]);
});
console.log('all',all.value());
}
return filters;
}
chart
.chart(c => dc.lineChart(c).curve(d3.curveCardinal).filterHandler(filterHandler))
.filterHandler(filterHandler);
New version of fiddle, with dataCount to show it's working now: https://jsfiddle.net/gordonwoodhull/qga6z1yu/39/
We really need a generalized version of https://github.com/dc-js/dc.js/pull/682 to apply filters only once, in a cooperative way between multiple charts which share the same dimension.
Right now, this will apply the filter four times every time the brush changes!

how to insert value into the kendo combo box

If I have a kendo combobox that contains more than 1 value I would like to insert "-ALL- as the DataTextField and "9999" as the DataValueField. Currently, if I have only a single record I use the DataBound event to test for that and if it = 1 then I load a grid based on this value, but if the length > 1 then I would like to add the -All-. I don't understand the insert as described by telerik.
#(Html.Kendo().ComboBox()
.Name("FAList")
.Placeholder("Select Fiscal Agency...")
.DataTextField("Text")
.DataValueField("Value")
.HtmlAttributes(new { style = "width:50%;" })
.Filter("startswith")
.AutoBind(true)
.MinLength(3)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetUserAgencyList", "Entities");
})
.ServerFiltering(true);
})
.Events(e => e
.Change("onFAChange")
.DataBound("onFADataBound")
)
)
and then the function for binding the data
function onFADataBound(e) {
// the agency list dropdown
var combobox = $("#FAList").data("kendoComboBox");
// if there is only a single record then set that in the combobox and load the grid based on that
if (e.sender.dataSource.view().length == 1) {
e.sender.select(0);
var filter = this.value();
$.get('/City/CityGrid_Read', { id: filter }, function (data) {
var grid = $("#FollowUpGrid").data("kendoGrid");
grid.dataSource.read();
})
}
if (e.sender.dataSource.view().length > 1) {
}
}
Answered at: Adding an item dynamically in kendo combobox
Combining that with your code:
if (e.sender.dataSource.view().length > 1) {
$("#FAList").data("kendoComboBox").dataSource.add({ Text: "-All-",
Value: "0" });
}
Something like that! I hope you get this implemented :)
An alternative could be to change the Placeholder text in this event method where length > 1
as per example on: http://www.telerik.com/forums/placeholder-text
$("#FAList").data("kendoComboBox").input.attr("placeholder", "-All-");

How to prevent deleting items in KendoUI multiselect?

I use a Kendo.UI MultiSelect in MVC
#(Html.Kendo().MultiSelect()
.Name("ADGroups")
.DataTextField("Name")
.DataValueField("Value")
.MinLength(3)
.Value(Model.SelectedADGroups)
.HtmlAttributes(new { style = "width:auto", id="ADGroupsList" })
.Filter(FilterType.Contains)
.DataSource(source => source.Read(read => read.Action("GetADGroups", "Edit"))
.ServerFiltering(true))
.Events(e => e.Change("onChange").DataBound("onDataBound"))
)
And now I would like to prevent from deleting some Items.
So I save the current values on DataBound-Event
function saveCurrent(multi)
{
multi._savedValues = multi.value().slice(0);
multi._savedItems = multi._dataItems.slice(0);
}
function onDataBound()
{
saveCurrent(this);
}
And OnChange I detect the difference between before and after.
function onChange()
{
var previous = this._savedValues;
var current = this.value();
if (current.length < previous.length)
{
var diff = $(previous).not(current).get(0);
if (confirm('Sure?'))
{
// do nothing value already deleted
}
else
{
// reset
this.value(previous);
}
}
saveCurrent(this);
}
This works perfectly. But If I type a new phrase so the widget calls the Read-Action to add some Items all works fine and NOW when I delete an item and cancel this action, however items will be removed.
What is wrong?

How can i highlight the Kendo grid cell by color change after update

I am using Kendo Ui Grid with MVC and SignalR. I can successfully perform the CRUD operations on grid using SignalR. I would like to notify clients by highlighting(By changing cell color) the updated cell. How can I achieve this with the following code:
#(Html.Kendo().Grid<Webapplication1.Models.ShipViewModel>()
.Name("ShipGrid")
.Columns(c =>{
c.Bound(m => m.Id).Hidden();
c.Bound(m => m.LocationViewModel)
.Title("Location1");
c.Bound(m => m.Location2ViewModel)
.Title("Location2");
c.Bound(m => m.boxSent);
c.Command(p =>
{
p.Edit().Text(" ").UpdateText(" ").CancelText(" ");
p.Destroy().Text(" ").HtmlAttributes(new { #title = "Cancel" });
});
})
.ToolBar(toolbar =>
{
toolbar.Create().Text("").HtmlAttributes(new { #title = "Add" });
})
.Editable(editable => editable
.DisplayDeleteConfirmation("DELETE.")
.Mode(Kendo.Mvc.UI.GridEditMode.PopUp)
.TemplateName("abcEditor")
)
.Events(events =>
{
events.Edit("edit");
})
.DataSource(dataSource => dataSource
.SignalR()
.Transport(tr => tr
.Promise("hubStart")
.Hub("mainHub")
.Client(c => c.Read("abc_Read").Create("abc_Insert").Update("abc_Update").Destroy("abc_Delete"))
.Server(s => s.Read("abc_Read").Create("abc_Insert").Update("abc_Update").Destroy("abc_Delete")))
.Schema(schema => schema
.Model(m => {
m.Id(p => p.Id);
m.Field(p => p.Location1ViewModel).DefaultValue(ViewData["DefaultLocation1"] as Webapplication1.Models.Location1ViewModel);
m.Field(p => p.Location2ViewModel).DefaultValue(ViewData["DefaultLocation2"] as Webapplication1.Models.DeliveryLocationViewModel);
})
)
)
)
I would like to Highlight the cell that is being updating here. Something like stock market data flashing. How can I achieve this?
I've done similar kind of thing. I don't know if that helps you. In your default view model add a extra property, say "Updated" as a boolean. Now every time you have update a row, put "Updated" as a true.
And in kendo grid add a new dataBound event.
.Events(events => events.DataBound("onDataBound"))
Now on JS use something like the following;
function onDataBound(arg) {
var itemsInActivityGrid = $("#ShippingGrid").data().kendoGrid.dataSource.data().length;
for (i = 0; i < itemsInActivityGrid; i++) {
if ($("#ShippingGrid").data().kendoGrid.dataSource.data()[i].Updated == true) {
$("#ShippingGrid .k-grid-content tr[data-uid='" + $("#ShippingGrid").data().kendoGrid.dataSource.data()[i].uid + "']").css("background-color", "orange");
}
}
}
Update: I don't know your logic. As far as you put on comments, you want to do something like online share dealing sites. Anyway, as far as I could, if you want to highlight individual cell in a row, add another extra field say "Column" along with "Updated"; it could be a string. Here you mark which cell you want to put the back ground colour from the backend. Say we've got it's value as "2".
for (i = 0; i < itemsInActivityGrid; i++)
{
var TableUID = $("#ShippingGrid").data().kendoGrid.dataSource.data()[i].uid;
var TableToColour = $("#ShippingGrid .k-grid-content tr[data-uid='" + TableUID + "']").parent().parent()[0];
var ColumnToColor = $("#ShippingGrid").data().kendoGrid.dataSource.data()[i].Column;
$(TableToColour.rows[0].cells[" + ColumnToColor + "]).select().attr("style","background-color:blue")
}
In case, you need to highlight multiple cells on the same row, in Column send something like "1,2,3,5"; where 1, 2, 3 and 5 represents the column numbers on the same row. And after ColumnToColor do some string parsing, put it into a for loop or something and colour;
Hope this helps. Thank you.
I have achieved this as below and its working fine:
in my .cshtml page
myHub.client.highlightRow = function (id) {
var data = $("#MyGrid").data("kendoGrid").dataSource.data();
for (var i = 0; i < data.length; i++) {
var dataItem = data[i];
if (dataItem.id == id) {
//alert(dataItem.uid);
$("#MyGrid").data("kendoGrid").tbody.find("tr[data-uid=" + dataItem.uid + "]").effect("highlight", { color: "#f35800" }, 3000);
}
}
};
And in my update/insert method in my SignalR Hub class:
Clients.Others.highlightRow(mygridViewModel.Id);

Kendo UI DropDownList as Multi Select with CheckBox

I'm Using Kendo UI MVC wrapper. I need a DropDownList with checkbox for each item to allow me select multiple of items.
I found this jsfiddle doing what I want to achieve, but it is not with MVC wrapper.Would you please show how I can implement the same thing with MVC wrapper?
#(Html.Kendo().DropDownList()
.Name("StructureCompany")
.HtmlAttributes(new { style = "width:180px" })
.OptionLabel("-- Select --")
.DataTextField("Title")
.DataValueField("Id")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCascadeCompany", "Company");
});
}))
Here's a way you can do it:
View
#(Html.Kendo().DropDownList()
.Name("StructureCompany")
.HtmlAttributes(new { style = "width:180px" })
.DataTextField("Title")
.DataValueField("Id")
.Template("<input type='checkbox' name='cb' value='#:data.Title#' /> #:data.Title#")
.Events(e => e.Select("onSelect"))
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCascadeCompany", "Company");
});
}))
I removed your OptionLabelbecause it doesn't flow well with this style. But I found an alternative as you will see below
Script
//This extendes the base Widget class
(function ($) {
var MultiSelectBox = window.kendo.ui.DropDownList.extend({
_select: function (li) { },//Prevents highlighting
_blur: function () { },//Prevents auto close
});
window.kendo.ui.plugin(MultiSelectBox);
})(jQuery);
//Sets up your optional label
$(document).ready(function () {
$("#StructureCompany").data("kendoDropDownList").text("-- Select --");
})
//Does all the functionality
function onSelect(e) {
var dataItem = this.dataItem(e.item);
var ddl = $("#StructureCompany").data("kendoDropDownList");
var cbs = document.getElementsByName("cb");
var display;
var list = [];
for (var i = 0; i < cbs.length; i++) {
if (cbs[i].checked) {
list.push(cbs[i].value);
}
}
if (list.length == 0) {
display = "-- Select --";
}
else {
display = list.join(", ");
}
ddl.text(display);
}
Here is the tricky part, I'm not a real connoisseur when it comes to javascript so forgive my terminology if it is wrong. The first blob where you have the new scope function allows you to inherit from the kendo.ui namespace so that you are able to change the base level stuff. Such as the auto close and highlighting functionality
That next blob is just my alternative to having your 'OptionLabel'(you can do it however you want)
The last part is the selection which as you can see just creates a comma value then shoves it in as the display in the drop down list via 'ddl.text()' method. You can do this however you want. Hope this helps!

Resources