I am using Kendo UI Multiselect:
http://demos.kendoui.com/web/multiselect/events.html
I have this Data:
var data =
[
{ text: "Shirt-Black", value: "1" },
{ text: "Shirt-Brown", value: "2" },
{ text: "Shirt-Blue", value: "3" },
{ text: "Cap-Green", value: "4" },
{ text: "Cap-Red", value: "5" },
{ text: "Cap-White", value: "6" },
{ text: "Jacket-Denim", value: "7" }
];
Now I want that if I select "Shirt-Brown" then rest entries for shirt i.e. "Shirt-Black" and "Shirt-Blue" should not appear in the list which means that the user should not be able to choose the Shirt of two colors.
Similarly, If a "Cap" of any color has been chosen then user should not be able to choose the "Cap" of any other color.
Is there any way to achieve this?
This is not build-in functionality. You can't even use dataSource filter() method because it will remove selected items from list as well.
However, this code will do what you're asking:
$("#select").kendoMultiSelect({
...
change: function(e) {
var dataItems = e.sender.dataItems();
var categories = [];
for(var i = 0; i < dataItems.length; i++){
var category = dataItems[i].text.substring(0, dataItems[i].text.indexOf('-'));
categories.push(category);
}
e.sender.ul.find('li').each(function(index, value){
var $li = $(value);
var hidden = false;
for(var i = 0; i < categories.length; i++){
var category = categories[i];
if ($li.text().match("^" + category)){
$li.css('display', 'none');
hidden = true;
}
}
if(!hidden){
$li.css('display', 'list-item');
}
});
}
});
Working KendoUi Dojo: http://dojo.telerik.com/AGisi
Related
I'm attempting to use the Grid component's built-in support for exporting to excel, applying custom cell formatting as shown in these Telerik docs:
http://docs.telerik.com/kendo-ui/controls/data-management/grid/how-to/excel/cell-format
The approach using hard-coded row / cell indexes in the export comes with a rather obvious issue when exporting a grid with a prior hidden column displayed - best way to reproduce is to refer to this jsfiddle:
https://jsfiddle.net/3anqpnqt/1/
Run fiddle
Click export to excel - observe custom number formatting
Unhide subcategory column (using column menu)
Click export to excel - observe custom number formatting on column 2 which is now 'subcategory'
With reference to this code in the fiddle:
$("#grid").kendoGrid({
toolbar: ["excel"],
excel: {
fileName: "Grid.xlsx",
filterable: true
},
columns: [
{ field: "productName" },
{ field: "category" },
{ field: "subcategory", hidden: true },
{ field: "unitPrice"}
],
dataSource: [
{ productName: "Tea", category: "Beverages", subcategory: "Bev1", unitPrice: 1.5 },
{ productName: "Coffee", category: "Beverages", subcategory: "Bev2", unitPrice: 5.332 },
{ productName: "Ham", category: "Food", subcategory: "Food1", unitPrice: -2.3455 },
{ productName: "Bread", category: "Food", subcategory: "Food2", unitPrice: 6 }
],
columnMenu: true,
excelExport: function(e) {
var sheet = e.workbook.sheets[0];
for (var rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
var row = sheet.rows[rowIndex];
var numericFormat = "#,##0.00;[Red](#,##0.00);-";
for (var cellIndex = 0; cellIndex < row.cells.length; cellIndex++) {
var cell = row.cells[cellIndex];
if (row.type === "data") {
if (cellIndex == 2) { // how are we able to identify the column without using indexes?
cell.format = numericFormat;
cell.hAlign = "right";
}
}
}
}
}
});
What I need to be able to do is identify the cell as the 'unitPrice' and apply the format, but inspection of the object model within the excelExport handler doesn't give me any way to make this link. In my real application, I have several custom formats to apply (percentages, n0, n2 etc) so it's not as simple as going $.isNumeric(cell.value) or otherwise.
Update
I also need the solution to work with column / row groups, which generate additional header rows / columns in the Excel model.
It looks like row[0] is the header row, so you could try changing
if (cellIndex == 2) {
to
if (sheet.rows[0].cells[cellIndex].value == "unitPrice") {
EDIT:
Seems to work with column group: https://jsfiddle.net/dwosrs0x/
Update:
The object model for worksheet is not the most clear. The first row does seem to be a "master" header row in the various scenarios that I looked at. Here is something that seems to work if unitPrice is not in a grouping. If unitPrice is in a grouping, then something more complicated involving the group header (row[1]) might be possible. The puzzle is to find out what position the desired column will eventually occupy.
var header = sheet.rows[0];
var upIndex = -1;
var upFound = false;
for (var cellIndex = 0; cellIndex < header.cells.length; cellIndex++) {
if ('colSpan' in header.cells[cellIndex])
upIndex = upIndex + header.cells[cellIndex].colSpan;
else
upIndex = upIndex + 1;
if (header.cells[cellIndex].value == "unitPrice") { // wot we want
upFound = true;
break;
}
}
for (var rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
var row = sheet.rows[rowIndex];
if (row.type === "data" && upFound) {
var cell = row.cells[upIndex];
cell.format = numericFormat;
cell.hAlign = "right";
}
}
fiddle with groups - https://jsfiddle.net/dwosrs0x/4/
fiddle with straightforward grid (to prove it still works) - https://jsfiddle.net/gde4nr0y/1/
This definitely has the whiff of "bodge" about it.
I'm working with a Kendo treelist widget, and disappointed to see there's no rowTemplate option as there is on the Kendo grid.
I see a columnTemplate option (i.e. http://docs.telerik.com/kendo-ui/api/javascript/ui/treelist#configuration-columns.template ), but this will affect the entire column.
However, I need to drill into each cell value and set a css color property based on a ratio ( i.e. If value/benchmark < .2, assign <span style='color:red;'> , but my color value is dynamic.
There's a dataBound: and dataBinding: event on the treelist, but I'm still trying to figure out how to intercept each cell value and set the color once I've done my calculation.
var treeOptions = {
dataSource: ds,
columns: colDefs,
selectable: true,
scrollable: true,
resizable: true,
reorderable: true,
height: 320,
change: function (e) {
// push selected dataItem
var selectedRow = this.select();
var row = this.dataItem(selectedRow);
},
dataBound: function (e) {
console.log("dataBinding");
var ds = e.sender.dataSource.data();
var rows = e.sender.table.find("tr");
}
};
and this is where I'm building out the `colDefs' object (column definitions):
function parseHeatMapColumns(data, dimId) {
// Creates the Column Headers of the heatmap treelist.
// typeId=0 is 1st Dimension; typeId=1 is 2nd Dimension
var column = [];
column.push({
"field": "field0",
"title": "Dimension",
headerAttributes: { style: "font-weight:" + 'bold' + ";" },
attributes : { style: "font-weight: bold;" }
});
var colIdx = 1; // start at column 1 to build col headers for the 2nd dimension grouping
_.each(data, function (item) {
if (item.typeId == dimId) {
// Dimension values are duplicated, so push unique values (i.e. trade types may have dupes, whereas a BkgLocation may not).
var found = _.find(column, { field0: item.field0 });
if (found == undefined) {
column.push({
field: "field2",
title: item.field0,
headerAttributes: {
style: "font-weight:" + 'bold'
}
,template: "<span style='color:red;'>#: field2 #</span>"
});
colIdx++;
}
}
});
return column;
}
**** UPDATE ****
In order to embed some logic within the template :
function configureHeatMapColumnDefs(jsonData, cols, model) {
var colDef = '';
var dimId = 0;
var colorProp;
var columns = kendoGridService.parseHeatMapColumns(jsonData, dimId);
// iterate columns and set color property; NB: columns[0] is the left-most "Dimension" column, so we start from i=1.
for (var i = 1; i <= columns.length-1; i++) {
columns[i]['template'] = function (data) {
var color = 'black';
if (data.field2 < 1000) {
color = 'red';
}
else if (data.field2 < 5000) {
color = 'green';
}
return "<span style='color:" + color + ";'>" + data.field2 + "</span>";
};
}
return columns;
}
Advice is appreciated.
Thanks,
Bob
In the databound event you can iterate through the rows. For each row you can get the dataItem associated with it using the dataitem() method (http://docs.telerik.com/kendo-ui/api/javascript/ui/treelist#methods-dataItem)
Once you have the dataitem, calculate your ration and if the row meets the criteria for color, change the cell DOM element:
dataBound: function (e) {
var that = e.sender;
var rows = e.sender.table.find("tr");
rows.each(function(idx, row){
var dataItem = that.dataItem(row);
var ageCell = $(row).find("td").eq(2);
if (dataItem.Age > 30) {
//mark in red
var ageText = ageCell.text();
ageCell.html('<span style="color:red;">' + ageText + '</span>');
}
}
DEMO
UPDATE: you can also do this with a template:
$("#treelist").kendoTreeList({
dataSource: dataSource,
height: 540,
selectable: true,
columns: [
{ field: "Position"},
{ field: "Name" },
{ field: "Age",
template: "# if ( data.Age > 30 ) { #<span style='color:red;'> #= data.Age # </span> #}else{# #= data.Age # #}#"
}
],
});
DEMO
I have a menu with values and I want to add a Key shortcut that will select that item.
I can demonstrate in this fiddle exactly what I am looking for
function onSelect(e) {
var item = $(e.item),
menuElement = item.closest(".k-menu"),
dataItem = this.options.dataSource,
index = item.parentsUntil(menuElement, ".k-item").map(function () {
return $(this).index();
}).get().reverse();
index.push(item.index());
for (var i = -1, len = index.length; ++i < len;) {
dataItem = dataItem[index[i]];
dataItem = i < len-1 ? dataItem.items : dataItem;
}
alert(dataItem.value);
}
$(document).ready(function() {
$("#menu").kendoMenu({
dataSource: [
{
text: "Item 1 (A)",
value: "A",
items: [
{
text: "Sub Item 1 (L)",
value: "L",
items: [
{
text: "Sub Sub Item 1 (D)",
value: "D"
},
{
text: "Sub Sub Item 2 (E)",
value: "E"
}
]
},
{
text: "Sub Item 2 (O)",
value: "O"
}
]
},
{
text: "Item 2 (F)",
value: "F"
},
{
text: "Item 3 (G)",
value: "G"
}
],
select: onSelect
});
$(document.body).keydown(function (e) {
var menu = $("#menu").kendoMenu().data("kendoMenu");
if (e.altKey && e.keyCode == 76) {
alert("select item with value L");
// Pseudocode:
// var item = find item with value L
// menu.select(item); (or trigger)
}
});
});
I couldn't find anywhere any resources that could accomplish that. Also I can't assign ids to the rendered "li" via the datasource which makes it hard to select a node of the menu.
Any ideas?
Not sure if Kendo API supports triggering select item but I was able to achieve click the menu items with keyboard shortcuts using JQuery.
Check this JSFiddle
function clickMenuSpan(keyCode){
var shortcut = String.fromCharCode(keyCode);
$('#menu span.k-link').each(function(){
var txt = $(this).text();
if(txt.substr(-3) === '(' + shortcut + ')')
{
$(this).click();
}
})
}
You can use the above function in your keydown event. And add some filters to call this only for your array of shortcuts.
$(document.body).keydown(function (e) {
var menu = $("#menu").kendoMenu().data("kendoMenu");
if (e.altKey) {
clickMenuSpan(e.keyCode);
}
});
var data = [{"Id":40072,"Id2":40071,"SmDetails":{"Id1":40071,"Id2":40072}}]
I want to display SmDetails.Id1 in a column. How is this possible? I tried:
var columns = [{name:'Personnel',field:SmDetails.id1,id:'detailId'}];
Please help me
Please help me
**My latest code**
var data = [{"Id":40072,"Id2":40071,"allocationDetails":{"Id1":40071,"allocationDetails":{"accommodationId":4007}}}]
var grid;
var columns = [ {name:"Personnel",field:"allocationDetails",fieldIdx:'accommodationId', id:"accommodationId"}];
var options = {
enableCellNavigation: true,
enableColumnReorder: false,
dataItemColumnValueExtractor:
function getValue(item, column) {
var values = item[column.field];
if (column.fieldIdx !== undefined) {
return values && values[column.fieldIdx];
} else {
return values;
}}};
var gridData=$scope.Vo;//This return as json format
grid = new Slick.Grid("#testGrid",gridData, columns);
This is the code tried recently.
You'll need to provide a custom value extractor to tell the grid how to read your object.
var options = {
enableCellNavigation: true,
enableColumnReorder: false,
dataItemColumnValueExtractor:
// Get the item column value using a custom 'fieldIdx' column param
function getValue(item, column) {
var values = item[column.field];
if (column.fieldIdx !== undefined) {
return values && values[column.fieldIdx];
} else {
return values;
}
}
};
The column definitions would look like:
{
id: "field1",
name: "Id1",
field: "SmDetails",
fieldIdx: 'Id1'
}, {
id: "field2",
name: "Id2",
field: "SmDetails",
fieldIdx: 'Id2'
} //... etc
Check out this fiddle for a working example.
try this to convert your data into object of single length values ...
newData = {};
for(key in data[0]){
parentKey = key;
if(typeof(data[0][key]) == "object"){
childData = data[0][key];
for(key in childData){
childKey = key;
newKey = parentKey+childKey;
newData[newKey] = childData[childKey];
}
} else {
newData[key] = data[0][key];
}
}
This will convert your data object like this
newData = {Id: 40072, Id2: 40071, SmDetailsId1: 40071, SmDetailsId2: 40072};
Now use this newData to map your data items in grid
I find this works well for nested properties, eg:
var columns = [
{ id: "someId", name: "Col Name", field: "myRowData.myObj.myProp", width: 40}
..
];
var options {
...
dataItemColumnValueExtractor: function getItemColumnValue(item, column) {
var val = undefined;
try {
val = eval("item." + column.field);
} catch(e) {
// ignore
}
return val;
}
};
I'm firing the databound event but I'm not sure what do do from there.
The links here lead to generic docs:
http://www.kendoui.com/forums/ui/grid/highlight-sorted-column.aspx
Does anyone have a simple example of highlighting the current sorted column?
The idea is as follows:
Handle the dataBound event of the grid.
Get the current sort expression of the data source using its sort method.
Find the grid column which is bound to the sorted field. Iterate over the grid columns field.
Highlight the table cells which correspond to the column index. Use the tbody field of the grid.
Here is a sample implementation:
<div id="grid"></div>
<script>
$("#grid").kendoGrid({
dataSource: [
{ name: "Jane Doe", age: 30 },
{ name: "Jane Doe", age: 33 }
],
sortable: true,
dataBound: function() {
var columns = this.columns;
var sort = this.dataSource.sort()[0];
var sortedIndex = -1;
if (sort) {
for (var i = 0; i < columns.length; i++) {
if (columns[i].field == sort.field) {
sortedIndex = i;
break;
}
}
}
if (sortedIndex >= 0) {
this.tbody
.find("tr")
.find("td:eq(" + sortedIndex + ")")
.css( { background: "#a0b0c0" } );
}
}
});
</script>
And a live demo: http://jsbin.com/ixahid/1/edit