Show multiple labels on kendoUI chart category axis - angularjs

Is there any possibility of showing more than one label in the category axis?
I need to show two fields from my data source in my category axis(And,yes there is no multi category axis. I need to show multiple fields on the same category axis. Please help if I'm missing out searching for any related topic.
Thanks in advance.

You can use label templates on the categoryAxis labels:
categoryAxis: {
field: 'submitTime',
majorGridLines: {
visible: false
},
labels: {
visible: true,
template: ' #= FormatLabel(dataItem) # '
}
},
In this example the template is passing the dataItem to a function which builds the desired string:
function FormatLabel(dataItem){
var tg = dataItem.TargetGroup;
var st = dataItem.submitTime.replace(" ", "\n");
return tg + "\n" + st;
}
DEMO

In your series, you can define the template on the label to display pretty much anything you want from the item it is bound to.
series: [
{
field: 'totalVisits',
name: 'Total Visits',
labels: {
visible: true,
template: ' #= dataItem.month # \n Total Visits : #= dataItem.totalVisits # \n Unique Visitors : #= dataItem.uniqueVisitors # '
}
}
],
See working sample at Kendo Dojo
If you need a bit more functionality, you can set that template to a function, and return whatever you want from it.
series: [
{
field: 'totalVisits',
name: 'Total Visits',
labels: {
visible: true,
template: chartSeriesTemplate
}
}
],
function chartSeriesTemplate(e) {
return kendo.format("{0} \n Total Visits:{1}\n Unique Visitors:{2} \n Ratio :{3}", e.dataItem.month, e.dataItem.totalVisits, e.dataItem.uniqueVisitors, (parseInt(e.dataItem.uniqueVisitors) / parseInt(e.dataItem.totalVisits)).toFixed(2));
}
See working sample at Kendo Dojo
Documentation for series template at Kendo Docs

Related

Angular Ui-Grid Multi Level Nesting

I am using Angular Ui-grid.Trying to achieve multi level nesting in that. Some one have already raised the issue in uiGrid github. But that solution doesn't seems working.
I have changed the JSON like this. I am trying to form nested sub grid.
Below is my code
$scope.gridOptions = {
expandableRowTemplate: 'expandableRowTemplate.html',
enableGridMenu: true,
expandableRowHeight: 150,
paginationPageSizes: [5, 10, 15],
paginationPageSize: 5,
//subGridVariable will be available in subGrid scope
expandableRowScope: {
subGridVariable: 'subGridScopeVariable'
}
}
$scope.gridOptions.columnDefs = [
{ name: 'id', enableHiding: false },
{ name: 'name' },
{ name: 'age' },
{ name: 'address.city' }
];
$http.get('http://private-7a7085-getfriends1.apiary-mock.com/getfriends')
.success(function (data) {
for (i = 0; i < data.length; i++) {
//for(i = 0; i < 50; i++){
data[i].subGridOptions = {
columnDefs: [{ name: "Id", field: "id" }, { name: "Name", field: "name" }, { name: "Age", field: "id" }, { name: "Address", field: "name" }],
data: data[i].friends,
expandableRowTemplate: 'expandableRowTemplate1.html',
enableGridMenu: true,
expandableRowHeight: 150
}
for (j = 0; j < data[i].friends.length; j++) {
data[i].subNestedGridOptions = {
columnDefs: [{ name: "Id", field: "id" }, { name: "Name", field: "name" }, { name: "Age", field: "id" }, { name: "Address", field: "name" }],
data: data[i].friends[j].friends
}
}
}
$scope.gridOptions.data = data;
});
and second level nested html(expandableRowTemplate1.html) looks like
<div ui-grid="row.entity.subNestedGridOptions" style="height:150px;"></div>
When I pass data to ui-grid for second level nested grid, it throws undefined.
Does any one have success till now to implement Expandable UI Grid with more then 2 or 3 levels. If yes please share plunker or fiddle or detailed explanation would be really helpful!
I have this working now. I assume you have constructed the proper data to bind at 3 levels. I assume that you have a 2 level grid working as well (parent grid's rows expand to show child grids). Here are the key few pieces I added to get this to work:
The top level grid has the directive ui-grid-expandable in the div tag that defines it. This is located in my html view.
<div ui-grid="gridThreeLayer" ui-grid-expandable></div>
The top level grid defines an expandableRowTemplate in its gridOptions (angularJS) .
$scope.gridThreeLayer = { ........
expandableRowTemplate: '..your path.../expandableRowTemplate.html' }
The top level grid's expandableRowTemplate will contain a div tag that defines another "ui-grid" and has the directive "ui-grid-expandable".
<div ui-grid="row.entity.subGridOptions" ui-grid-expandable></div>
The 2nd level grid has its subGridOptions and columnDefs built on the fly when the data is being bound in the angularJS (off an $http.get() for me). At this time, you need to specify an expandableRowTemplate property on that 2nd level grid which tells it to expand and show the 3rd level grid.
for (i = 0; i < response.data.length; i++) {
response.data[i].subGridOptions = { .....
columnDefs: [ ............],
data: response.data[i].IP, // note that this is my 2nd level of data objects - yours will differ
expandableRowTemplate: 'AngularApp/Templates/MultiLevelTemplate.html
The expandableRowTemplate of the 2nd level grid needs to define a div tag with a "ui-grid", instructing the grid to render a nested grid for each row. It does NOT need a directive for expanding (but you could add one to go 4 levels deep). Mine is called MultiLevelTemplate .
<div ui-grid="row.entity.subGridOptions"></div>
Now in the same angularJS block, where you are building each row's gridOptions and columnDefs on the fly, you need to go to another level of iterations through that level of the data. This will allow you to define the subGridOptions and columnDefs fo the 3rd level grid. So you are in the "i" loop, and starting an "x" loop within it. Note that in setting the data source, it is using my own 3 levels of data objects. You need to use your own there.
for (x = 0; x < response.data[i].IP.length; x++) {
response.data[i].IP[x].subGridOptions = {
columnDefs: [........],
response.data[i].IP[x].subGridOptions.data = response.data[i].IP[x].BOM; // my data
If you do all of the above, it should work correctly if your data is set up correctly.

Kendo grid export to excel header title shows html characters

When I export my grid to excel,headers are like: Product Name,{{'unitsOrder'| translate}} in excel. My grid supports 2 languages and I am showing it with angularjs translate way. Any offer?
<script>
$("#grid").kendoGrid({
toolbar: ["excel"],
excel: {
fileName: "Kendo UI Grid Export.xlsx"
},
dataSource: {
type: "odata",
transport: {
read: "http://demos.telerik.com/kendo-ui/service/Northwind.svc/Products"
},
pageSize: 7
},
sortable: true,
pageable: true,
columns: [
{ width: 300, field: "ProductName", title: "<b>Product Name</b>" },
{ field: "UnitsOnOrder", title: "{{'unitsOrder'| translate}}" },
{ field: "UnitsInStock", title: "Units In Stock" }
]
});
</script>
I had a similar problem but I use i18next translation instead of angular but maybe it helps you find a solution to your case:
I use the 'excelExport' event to manually update the generated worksheet. Within the worksheet object I search for the header cells and manually trigger the translation for the text it contains:
excelExport: function(e) {
// First I loop through all rows in the worksheet
e.workbook.sheets[0].rows.forEach(function(row){
// Ignore 'data' rows (only use 'header' and 'footer')
if(row.type != 'data'){
// Loop through all cells of the row
row.cells.forEach(function(cell){
// Here I overwrite the cell value with its translation
// You have to implement translate() so it works with angular
cell.value = translate(cell.value)
});
}
});
},
You now have to write your own translate function which can handle your angular translation. As I use i18next for translations my solution won't help here (I use jquery to generate a jquery html object on which I can trigger the translation)

Kendo UI grid dropdown and angular

I try to setup custom dropdown in Kendo UI.
I have a reference to my issue.
http://dojo.telerik.com/aFIZa/13
My issue is that I do not know how I can setup the selected text in the template attribute? I want to show the text field but save the id as a value. And I do not want to use external datasource. I would like it as inline in the json.
The code is below:
$scope.mainGridOptions = {
dataSource: $scope.dataSource,
pageable: true,
height: 550,
toolbar: ["create"],
columns: [
{ field: "Category", title: "Category", width: "180px",
editor: function(container, options) {
var editor = $('<input kendo-drop-down-list required k-data-text-field="\'cat\'" k-data-value-field="\'id\'" k-data-source="{data:[{id: 1, cat: \'test\'}, {id: 2, cat: \'test2\'}]}" data-bind="value:Category"/>')
.appendTo(container);
$compile(editor)($scope);
editor.css("visibility", "visible");
}
, template:"selected text in the combo "
}
], editable: true
}
Ok, this was a tough one, but I think I could achieve what you want, or at least I got closer:
$scope.mainGridOptions =
{
dataSource: $scope.dataSource,
pageable: true,
height: 550,
toolbar: ["create"],
columns: [
{
field: "Category", title: "Category", width: "180px",
editor: function(container, options)
{
// #1
var editor = $('<input kendo-drop-down-list required k-data-text-field="\'cat\'" k-data-value-field="\'id\'" k-data-source="{data:[{id: 1, cat: \'test\'}, {id: 2, cat: \'test2\'}]}" data-bind="value:Category,events:{ change: onChange }"/>')
.appendTo(container);
$compile(editor)($scope);
editor.css("visibility", "visible");
},
// #2
template:kendo.template($("#column-template").html())
}],
editable: true,
// #3
edit: function(e)
{
var ko = kendo.observable(
{
onChange: function(e)
{
var el = $(e.sender.element);
var ddl = el.data("kendoDropDownList");
var ds = $scope.dataSource.getByUid(el.closest("tr").data("uid"));
ds.OptionText = ddl.text();
},
});
var widget = $(e.container).find("input");
kendo.bind(widget, ko);
}
}});
Demo.
In the code you can notice 3 changes:
data-bind="value:Category,events:{ change: onChange }" Look that I have added an events object in the bind, which I declare onChange as the change event handler. We'll talk about this in the 3rd item below;
For a complex template(with javascript code and logic) I created a script content and rendered it at the template property. The template is this:
<script id="column-template" type="text/x-kendo-template">
# if (data.hasOwnProperty('OptionText')) { #
#: OptionText #
# } else { #
#: "selected text in the combo" #
# } #
</script>
In the template I simply check for the property OptionText in the model(dataSource's current item) and: if it exists, use it; else, use the default text. We'll talk about OptionText in the 3rd item, below;
Now, here I have added an edit event to the grid. In that event I created an observable object, where I define the onChange function handler. In that function I seek for the current dataSource(ds) and I add text of the selected item in the dropdownlist in it, as the property OptionText, which I use in the template above explained.
I hope this explains how it works(in fact I hate working with those binders and observables, but sometimes they are needed).
Good luck.

Kendo grid with dropdown action command

I have a KendoUI Grid bound using Angular and I'd like to implement a custom action dropdown command or template column on each row. I need to track the dropdown change event for any of the rows when the grid is in display mode, not edit mode. The dropdown is effectively just a list of all of the name properties of the grid rows that I want to user to be able to select to move the row after another existing row.
For instance, say I have this data:
Id Name Position
A Red 1
B Blue 2
C White 3
I'd like each row to display a dropdown column while in display mode (so it acts like a row command). The dropdown would contain the names Red,Blue,White with corresponding values. When a user picks one of those colors, I will change the position of that row to the row position after the color selected. It's basically a row reorder dropdown instead of using drag and drop.
My other option is to show a couple of template columns with a move up/move down metaphor to do the switch but that gets a little cumbersome when you want to move a row more than a couple of positions.
Any ideas?
Ok, I did some more searching and found out a way to do this although it's not 100% of the way there yet. I also found a way to bind the dropdown to the data that populates the grid
The other thing I found when doing it this way is it is painfully slow in rendering the grid now.
<div id="mainGrid" kendo-grid="mainGrid" k-options="mainGridOptions"></div>
//grid columns
$scope.mainGridOptions = {
dataSource: {
transport: {
read: function (e) {
gridcolumnService.getGridColumns().success(function (data) {
e.success(data);
});
},
},
},
columns: [
{ field: "Name" },
{ field: "ColumnSettings.Type", title: "Type" },
{ field: "ColumnSettings.PrimaryKey", title: "Primary Key", template: '<input type="checkbox" #= ColumnSettings.PrimaryKey ? "checked=checked" : "" # disabled="disabled" ></input>' },
{ field: "ColumnSettings.Title", title: "Title" },
{ field: "ColumnSettings.Editable", title: "Editable", template: '<input type="checkbox" #= ColumnSettings.Editable ? "checked=checked" : "" # disabled="disabled" ></input>' },
{ field: "ColumnSettings.Visible", title: "Visible", template: '<input type="checkbox" #= ColumnSettings.Visible ? "checked=checked" : "" # disabled="disabled" ></input>' },
{ field: "LookupDataCommandId", title: "Lookup", template: '#= LookupDataCommandId ? "Yes" : "" #' },
{ template: '<select id="reorder-dropdown" kendo-drop-down-list k-on-change="exchangeRows(dataItem, kendoEvent)" k-data-source="reorderData()" k-data-text-field="\'Name\'" k-data-value-field="\'GridColumnId\'"></select>' },
{ template: '<a kendo-button k-icon="\'pencil\'" ng-click="editGridColumn(dataItem.GridColumnId)">Edit</a>', width: 100 }
]
};
$scope.reorderData = function() {
return $scope.mainGrid.dataSource.data();
};
$scope.exchangeRows = function (fromRow, e) {
$log.log(fromRow.GridColumnId, e.sender.dataItem().GridColumnId);
};

UI Grid - Formatting Data

I'm using the new Angular UI Grid (that is planned to replace ng-grid).
My data needs some formatting before it's displayed in the table. For instance, my server returns an attribute named "status" as a number, but I want to display it as a nice name.
If status=1 display "Todo", if status=2 display "Doing" etc.
How can this be done in UI Grid?
The preferred method now is to use a cellFilter, rather than a custom template. Custom templates are OK, but they impose more workload on upgrade - you have to check whether new features require modifications to your template.
There is a reasonable example of filters in the tutorials: http://ui-grid.info/docs/#/tutorial/201_editable
Note the cellFilter: 'mapGender' on the gender column, and the filter itself defined further below in the tutorial:
.filter('mapGender', function() {
var genderHash = {
1: 'male',
2: 'female'
};
return function(input) {
if (!input){
return '';
} else {
return genderHash[input];
}
};
})
First step, add a cellTemplate to the column:
$scope.gridOptions.columnDefs = [
{field:'status', displayName: 'Status',cellTemplate: 'statusTemplate.html'}
];
The Template-File should look like this (COL_FIELD is the actual field):
<div style="text-align: center">{{COL_FIELD==1 ? 'Todo' : 'Doing'"}}</div>
Hope, you got the idea! :)
The shortest way is use CellTemplate with appScopeProvider:
vm.gridOptions = {
columnDefs: [
{
field: 'status',
cellTemplate: '<div>{{grid.appScope.formatStatus(row)}</div>'
}
],
appScopeProvider: {
formatStatus: function (row) {
return row.entity.status === 1 ? 'Todo' : 'Doing';
},
}
}

Resources