I have a problem with setting default values of kendo multiselect. On the site I've been developing, I'm trying to keep selected values on multiselect. When someone select a value(s), I send the values to database. When the user refresh the site, I want to get value from db and set multiselect's default values(I mean values will be on multiselect's input.) I did it with this way :
$(function () {
$.get('Home/GetAppsJson/', function (data) {
if (data[0] != null) {
for (var i = 0; i < data.length; i++) {
if (data[i] == null)
break;
$('<li class="k-button" unselectable="on"></li>').appendTo('.k-multiselect-wrap ul');
$('<span></span>', {
text: data[i],
unselectable: "on"
}).appendTo($('.k-multiselect-wrap ul li.k-button').eq(i));
}
$('<span unselectable="on" class="k-icon k-delete">delete</span>').appendTo('.k-multiselect-wrap ul li.k-button');
}
});
});
but this time when I remove the value from multiselect, onChange event doesn't work. It seems multiselect can't detect the values on input. How can I achieve this?
(Answered by the OP in a question edit. Converted to a community wiki answer. See Question with no answers, but issue solved in the comments (or extended in chat) )
The OP wrote:
I solved problem by using "value()" function.
$.get('Home/GetAppsJson/', function (data) {
var values = new Array();
if (data[0] != null) {
for (var i = 0; i < data.length; i++) {
if (data[i] == null)
break;
values[i]=data[i];
}
}
var multiselect = $('#applications').data("kendoMultiSelect");
multiselect.value(values);
});
Related
Here I have a code to update a cell contet when pressing a button.
It works fine, but it doesn't set the flag, that indicates, that the cell has been changed.
It should look like this with the litle red triangle:
The code:
<a id="button" href="#">Click me</a>
<div id="grid"></div>
<script>
var dataSource, grid;
$(document).ready(function () {
dataSource = new kendo.data.DataSource({
data: [
{ category: "Beverages", name: "Chai", price: 18},
{ category: "Seafood", name: "Konbu", price: 6}
],
})
grid = $("#grid").kendoGrid({
dataSource: dataSource,
editable: true,
}).data("kendoGrid");
$('#button').click(function (e) {
var data = grid.dataItem("tr:eq(1)");
data.set('category', 'Merchandice');
});
});
</script>
Update:
Here is the update based on #tstancin: Kendo example.
Thank you for the answer - I had thought of it to.
I am wondering if it's possible to do the update in a more clean way with some binding through som MVVM perhaps?
Kind regards from Kenneth
If that's all you want then you should expand your button click code with the following:
$('#button').click(function (e) {
var data = grid.dataItem("tr:eq(1)");
data.set('category', 'Merchandice');
$("#grid tr:eq(1) td:eq(1)").addClass("k-dirty-cell");
$("#grid tr:eq(1) td:eq(0)").prepend("<span class='k-dirty'></span>");
});
But if you, for instance, manually change the value of name column from Chai to something else, and then click the click me button, the dirty marker in the name column will disappear.
You should use flags for every cell and set them before data.set(). Then, in the grid's dataBound event you should inspect every cell's value and assign the dirty marker if it's needed. For manual changes you should handle the save event and set flags there.
I wrote a script that makes it posible to use a call like this:
SetCellData(id, columnName, value);
So with an id, a columnName and a value, I can update a value in a grid and the flag will be set on the cell.
function SetCellData(id, columnName, value) {
var dataItem = grid.dataSource.get(id);
dataItem.set(columnName, value);
var columnIndex = GetColumnIndex(columnName);
if (columnIndex > -1) {
var cell = $('tr[data-uid*="' + dataItem.uid + '"] td:eq(' + columnIndex + ')')
if (!cell.hasClass("k-dirty-cell")){
cell.prepend("<span class='k-dirty'></span>");
cell.addClass("k-dirty-cell");
}
}
}
function GetColumnIndex(columnName) {
var columns = grid.columns;
for (var i = 0; i < columns.length; i++)
if (columns[i].field == columnName)
return i;
return -1;
};
I have the code here : example
I'm new with Kendo UI PanelBar. I would like to expand the panelbar using javacript when the user click on a button. Thanks for your help.
#(Html.Kendo().PanelBar()
.Name("TestBar")
.Items(panelbar =>
{
panelbar.Add().Text("Additional Information")
.Content(#<text>#Html.Partial("Req") </text>);
})
)
Please try with the below code snippet. Call below funciton in your button click event.
<script>
function ExpandItemInPanelBar(){
var panelBar = $("#TestBar").data("kendoPanelBar");
// I have set 0 in 'eq(0)' so it will expand first item you can change it as per your code
panelBar.select(panelBar.element.children("li").eq(0));
var item = panelBar.select();
panelBar.expand(item);
}
</script>
Let me know if any concern.
Update 1:
//Check any item is expanded in panelbar
if(panelBar.element.children("li").hasClass("k-state-active") == true)
{
alert('items(s) expanded');
}
//Check every item is expanded or not in panelbar
items = panelBar.element.children("li");
for(var i = 0 ; i < items.Length; i++)
{
if($(items[i].hasClass('k-state-active'))
{
alert('this item is expanded');
}
}
I have checkbox in Kendo grid. Once i click on Checkbox it always focus the top cell in Kendo Grid. Below is code for Kendo grid that I am binding to checkbox value on checkbox click event in Kendo Grid
$("#contactgrid").on('click', '.chkbx', function () {
var checked = $(this).is(':checked');
var grid = $('#contactgrid').data().kendoGrid;
var rowIdx = $("tr", grid.tbody).index(row);
var colIdx = $("td", row).index(this);
// grid.tbody.find("tr").eq(rowIndex).foucs(); This doesn't work
var dataItem = grid.dataItem($(this).closest('tr'));
dataItem.set('IsSelected', checked);
});
I can get the row index and cell Index in click event but I was not able to figure out to focus the specific cell.
Thanks!
When you want to edit Grid with checkbox then I would suggest you to use the approach from this code library. No matter it uses the MVC extensions open Views/Home/Index.cshtml and see how the template is defined and the javascript used after initializing the Grid.
Here it is
Column template:
columns.Template(#<text></text>).ClientTemplate("<input type='checkbox' #= IsAdmin ? checked='checked':'' # class='chkbx' />")
.HeaderTemplate("<input type='checkbox' id='masterCheckBox' onclick='checkAll(this)'/>").Width(200);
<script type="text/javascript">
$(function () {
$('#persons').on('click', '.chkbx', function () {
var checked = $(this).is(':checked');
var grid = $('#persons').data().kendoGrid;
var dataItem = grid.dataItem($(this).closest('tr'));
dataItem.set('IsAdmin', checked);
})
})
function checkAll(ele) {
var state = $(ele).is(':checked');
var grid = $('#persons').data().kendoGrid;
$.each(grid.dataSource.view(), function () {
if (this['IsAdmin'] != state)
this.dirty=true;
this['IsAdmin'] = state;
});
grid.refresh();
}
</script>
I struggled with this. I essential refocused the cell as shown below. There's plenty of room for improvement in the Kendo grid client-side API. Hopefully my helper methods below will help people out.
var $row = getRowForDataItem(this);
var $current = getCurrentCell($row);
var currentCellIndex = $row.find(">td").index($current);
this.set('PriceFromDateTime', resultFromDate);
$row = getRowForDataItem(this);
var grid = getContainingGrid($row);
//select the previously selected cell by it's index(offset) within the td tags
if (currentCellIndex >= 0) {
grid.current($row.find(">td").eq(currentCellIndex));
}
//Kendo grid helpers
function getColumn(grid, columnName) {
return $.grep(grid.columns, function (item) {
return item.field === columnName;
})[0];
}
function getRowForDataItem(dataItem) {
return $("tr[data-uid='" + dataItem.uid + "']");
}
function getCurrentCell($elem) {
return getContainingGrid($elem).current();
}
function getContainingDataItem($elem) {
return getDataItemForRow(getContainingRow($elem));
}
function getContainingCell($elem) {
return $elem.closest("td[role='gridcell']");
}
function getContainingRow($elem) {
return $elem.closest("tr[role='row']");
}
function getContainingGrid($elem) {
return $elem.closest("div[data-role='grid']").data("kendoGrid");
}
function getGridForDataItem(dataItem) {
return getContainingGrid(getRowForDataItem(dataItem));
}
function getDataItemForRow($row, $grid) {
if (!$grid) $grid = getContainingGrid($row);
return $grid.dataItem($row);
}
function getMasterRow($element) {
return $element.closest("tr.k-detail-row").prev();
}
function getChildGridForDataItem(dataItem) {
return getRowForDataItem(dataItem).next().find("div.k-grid").data("kendoGrid");
}
function getMasterRowDataItem($element) {
var $row = getMasterRow($element);
return getDataItemForRow($row);
}
I have a scenario with grid within grid implemented using the detailInit method. Here when user makes edit, i do some calculations that will change the data in the both parent and child. and then to refresh data, i will call the datasource.read to render data. this works and the data is displayed, however any detail grid which are expanded will be collapsed, is there any way i can prevent this from happening.
To answer this and another question:
"I figured out how to set the data in the master from the child BUT, the
whole table collapses the child grids when anything is updated, this is a
very annoying behavior, is there anyway I can just update a field in
the master table without it collapsing all the child elements?
(basically, update the column, no mass table update)"
in another thread at: telerik
This is extremely annoying behavior of the Kendo Grid and a major bug. Since when does a person want the sub-grid to disappear and hide a change that was just made! But this isn't the only problem; the change function gets called a Fibonacci number of times, which will freeze the browser after a significant number of clicks. That being said, here is the solution that I have come up with:
In the main grid
$('#' + grid_id).kendoGrid({
width: 800,
...
detailExpand: function (e) {
var grid = $('#' + grid_id).data("kendoGrid");
var selItem = grid.select();
var eid = $(selItem).closest("tr.k-master-row").attr('data-uid')
if (contains(expandedItemIDs, eid) == false)
expandedItemIDs.push(eid);
},
detailCollapse: function (e) {
var grid = $('#' + grid_id).data("kendoGrid");
var selItem = grid.select();
var eid = $(selItem).closest("tr.k-master-row").attr('data-uid')
for (var i = 0; i < expandedItemIDs.length; i++)
if (expandedItemIDs[i] == eid)
gridDataMap.expandedItemIDs.splice(i, 1);
},
Unfortunately globally we have:
function subgridChange() {
var grid = $('#' + grid_id).data("kendoGrid");
for (var i = 0; i < expandedItemIDs.length; i++)
grid.expandRow("tr[data-uid='" + expandedItemIDs[i] + "']");
}
function contains(a, obj) {
for (var i = 0; i < a.length; i++)
if (a[i] === obj) return true;
return false;
}
expandedItemIDs = [];
Now the 'subgridChange()' function needs to be called every time a change is made to the subgrid.
The problem is that the number of times the change function in the subgrid gets called increases exponentially on each change call. The Kendo grid should be able to call a stop propagation function to prevent this, or at least give the programmer access to the event object so that the programmer can prevent the propagation. After being completely annoyed, all we have to do is to place the 'subgridChange()' function in the subgrid 'datasource' like so:
dataSource: function (e) {
var ds = new kendo.data.DataSource({
...
create: false,
schema: {
model: {
...
}
},
change: function (e) {
subgridChange();
}
});
return ds;
}
I also had to place the 'subgridChange()' function in the Add button function using something like this
$('<div id="' + gridID + '" data-bind="source: prodRegs" />').appendTo(e.detailCell).kendoGrid({
selectable: true,
...
toolbar: [{ template: "<a class='k-button addBtn' href='javascript://'><span class='k-icon k-add' ></span> Add Product and Region</a>" }]
});
$('.addBtn').click(function (event) {
...
subgridChange();
});
When a user selects a row, record the index of the selected row. Then after your data refresh, use the following code to expand a row
// get a reference to the grid widget
var grid = $("#grid").data("kendoGrid");
// expands first master row
grid.expandRow(grid.tbody.find(">tr.k-master-row:nth-child(1)"));
To expand different rows, just change the number in the nth-child() selector to the index of the row you wish to expand.
Actually all that is needed is the 'subgridChange()' function in the main grid 'dataBound' function:
$('#' + grid_id).kendoGrid({
...
dataBound: function (e) {
gridDataMap.subgridChange();
}
});
Different but similar solution that i used for same problem:
expandedItemIDs = [];
function onDataBound() {
//expand rows
for (var i = 0; i < expandedItemIDs.length; i++) {
var row = $(this.tbody).find("tr.k-master-row:eq(" + expandedItemIDs[i] + ")");
this.expandRow(row);
}
}
function onDetailExpand(e) {
//refresh the child grid when click expand
var grid = e.detailRow.find("[data-role=grid]").data("kendoGrid");
grid.dataSource.read();
//get index of expanded row
$(e.detailCell).text("inner content");
var row = $(e.masterRow).index(".k-master-row");
if (contains(expandedItemIDs, row) == false)
expandedItemIDs.push(row);
}
function onDetailCollapse(e) {
//on collapse minus this row from array
$(e.detailCell).text("inner content");
var row = $(e.masterRow).index(".k-master-row");
for (var i = 0; i < expandedItemIDs.length; i++)
if (expandedItemIDs[i] == row)
expandedItemIDs.splice(i, 1);
}
function contains(a, obj) {
for (var i = 0; i < a.length; i++)
if (a[i] === obj) return true;
return false;
}
I've a jqGrid-based application, and I use loadonce: true in the grid option and sortable: true, sorttype: 'text in the colModel to allow client-side sorting on the data grid. However, I found that, once the data grid is re-sorted, the last selected row will no longer be highlighted. My question is, how to keep the selected row being highlighted across data resorting?
I prepared for you the small demo which keeps the row selection. In the demo I rewrote the code of selectionPreserver used in case of reloadGrid usage having additional parameters: $("#list").trigger("reloadGrid", [{current:true}]);. See the answer for details.
The demo saves the current selection inside of the onSortCol event handler and restore it inside of the loadComplete:
onSortCol: function () {
saveSelection.call(this);
},
loadComplete: function () {
restoreSelection.call(this);
}
How you see the usage is very simple and you can integrate it in your code. The implementation of the saveSelection and restoreSelection is the following:
var lastSelArrRow = [],
lastScrollLeft = 0,
lastSelRow = null,
saveSelection = function () {
var $grid = $(this);
lastSelRow = $grid.jqGrid('getGridParam', 'selrow');
lastSelArrRow = $grid.jqGrid('getGridParam', 'selrow');
lastSelArrRow = lastSelArrRow ? $.makeArray(lastSelArrRow) : null;
lastScrollLeft = this.grid.bDiv.scrollLeft;
},
restoreSelection = function () {
var p = this.p,
$grid = $(this);
p.selrow = null;
p.selarrrow = [];
if (p.multiselect && lastSelArrRow && lastSelArrRow.length > 0) {
for (i = 0; i < lastSelArrRow.length; i++) {
if (lastSelArrRow[i] !== lastSelRow) {
$grid.jqGrid("setSelection", lastSelArrRow[i], false);
}
}
lastSelArrRow = [];
}
if (lastSelRow) {
$grid.jqGrid("setSelection", lastSelRow, false);
lastSelRow = null;
}
this.grid.bDiv.scrollLeft = lastScrollLeft;
};