I create a similar demo relate with my situation. What I want to achieve when checked on the master grid, the details grid will expand and all the checkbox inside it will be checked and also the child grid is selected.
It's possible to do like this without using column template for the checkbox.
DEMO IN DOJO
Example like this screen shot. (this one manually checked)
p/s: I found a similar demo, but this one using column.template for the checkbox.
This example code (which is based on your sample code) answers your requirement, which is...
What I want to achieve when checked on the master grid, the details grid will expand and all the checkbox inside it will be checked and also the child grid is selected.
Try this in the Telerik DOJO. We need to wait for Kendo to finish expanding the detail row (making sure all HTML elements are fully built), hence the setTimeout in detailExpand. Change the delay depending on your needs.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Kendo Grid Master Detail Checkbox</title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.3.1118/styles/kendo.default-v2.min.css"/>
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2021.2.616/js/kendo.all.min.js"></script></head>
<body>
<div id="example">
<div id="grid"></div>
<script>
$(document).ready(function() {
var grid = $("#grid").kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Employees"
},
pageSize: 6,
serverPaging: true,
serverSorting: true
},
height: 600,
sortable: true,
pageable: true,
detailInit: detailInit,
detailExpand: function(e) {
var $checkbox = $(e.masterRow.context);
if ($checkbox.is(":checked")) {
setTimeout(function() {
e.detailRow.find("tbody tr").each(function() {
var $row = $(this);
$row.find(".k-checkbox").each(function() {
var $checkbox = $(this);
$checkbox.attr("checked", true);
});
$(this).addClass("k-state-selected");
});
}, 250);
}
},
columns: [
{ selectable: true, width: 50 },
{
field: "FirstName",
title: "First Name",
width: "110px"
},
{
field: "LastName",
title: "Last Name",
width: "110px"
},
{
field: "Country",
width: "110px"
},
{
field: "City",
width: "110px"
},
{
field: "Title"
}
]
}).data("kendoGrid");
grid.tbody.on("click", ".k-master-row .k-checkbox", function(e) {
var $checkbox = $(this);
if ($checkbox.is(":checked")) {
var $tr = $checkbox.closest("tr");
var $a = $tr.find(".k-hierarchy-cell a.k-icon");
if ($a.length) {
if ($a.hasClass("k-i-expand")) {
grid.expandRow($tr);
}
}
}
});
});
function detailInit(e) {
var detailgrid = $("<div/>").appendTo(e.detailCell).kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Orders"
},
serverPaging: true,
serverSorting: true,
serverFiltering: true,
pageSize: 10,
filter: {
field: "EmployeeID",
operator: "eq",
value: e.data.EmployeeID
}
},
scrollable: false,
sortable: true,
pageable: true,
columns: [
{ selectable: true, width: 50, headerTemplate: ' '},
{
field: "OrderID",
width: "110px"
},
{
field: "ShipCountry",
title: "Ship Country",
width: "110px"
},
{
field: "ShipAddress",
title: "Ship Address"
},
{
field: "ShipName",
title: "Ship Name",
width: "300px"
}
]
}).data("kendoGrid");
}
</script>
</div>
</body>
</html>
I adapted your first snippet based on the second one that you provided. Check out this revised demo.
Basically, you need to call getKendoGrid() and assign its return value (the actual grid) to the grid variable.
After that, add the change event listener as shown in the second demo snippet that you provided.
grid.tbody.on("change", ".k-checkbox", function() {
var checkbox = $(this);
var nextRow = checkbox.closest("tr").next();
// Note: the row should be expanded at least once as otherwhise there will be no child grid loaded
if (nextRow.hasClass("k-detail-row")) {
// And toggle the checkboxes
nextRow.find(":checkbox")
.prop("checked", checkbox.is(":checked"));
}
});
Also note that it's not .master as in the second demo, but .k-checkbox, as you are not providing a template in the first column (which the second demo does and the checkbox there has the master class).
Related
I'm using KendoUI Grid to display some data, the grid is pageable and scrollable, right now I'm able to select and scroll to a specific row, but now when I'm there I also should be able to navigate and select a specific cell (td) of that row. This is what I've so far.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Kendo UI Snippet</title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2021.3.1207/styles/kendo.default-v2.min.css"/>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2021.3.1207/js/kendo.all.min.js"></script>
</head>
<body>
Select row with ID = <input id="numeric" /> (1-78)
<button id="searchBtn" class="k-button">Go</button>
<div id="grid"></div>
<script>
function selectGridRow(searchedId, grid, idField){
var dataSource = grid.dataSource;
var filters = dataSource.filter() || {};
var sort = dataSource.sort() || {};
var models = dataSource.data();
// We are using a Query object to get a sorted and filtered representation of the data, without paging applied, so we can search for the row on all pages
var query = new kendo.data.Query(models);
var rowNum = 0;
var modelToSelect = null;
models = query.filter(filters).sort(sort).data;
// Now that we have an accurate representation of data, let's get the item position
for (var i = 0; i < models.length; ++i) {
var model = models[i];
if (model[idField] == searchedId) {
modelToSelect = model;
rowNum = i;
break;
}
}
// If you have persistSelection = true and want to clear all existing selections first, uncomment the next line
// grid._selectedIds = {};
// Now go to the page holding the record and select the row
var currentPageSize = grid.dataSource.pageSize();
var pageWithRow = parseInt((rowNum / currentPageSize)) + 1; // pages are one-based
grid.dataSource.page(pageWithRow);
var row = grid.element.find("tr[data-uid='" + modelToSelect.uid + "']");
if (row.length > 0) {
grid.select(row);
// Scroll to the item to ensure it is visible
grid.content.scrollTop(grid.select().position().top);
}
}
$(document).ready(function () {
$("#searchBtn").click(function(){
var grid = $("#grid").data("kendoGrid");
var searchedId = $("#numeric").data("kendoNumericTextBox").value();
selectGridRow(searchedId, grid, "ProductID");
});
$("#numeric").kendoNumericTextBox({
min: 1,
max: 78,
format: "n0"
});
$("#grid").kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Products"
},
schema: {
model: {
id: "ProductID",
fields: {
ProductID: { type: "number" },
UnitPrice: { type: "number" },
UnitsInStock: { type: "number" }
}
}
},
pageSize: 10
},
height: 350,
sortable: true,
filterable: true,
selectable: "row",
pageable: {
refresh: true,
pageSizes: true
},
columns: [
{
field: "ProductID",
title: "ID",
width: 100
},{
field: "ProductName",
title: "Product Name",
width: 180
},{
field: "ProductName",
title: "Product Name 2",
width: 230
},{
field: "ProductName",
title: "Product Name 3",
width: 230
},{
field: "ProductName",
title: "Product Name 4",
width: 230
},{
field: "ProductName",
title: "Product Name 5",
width: 230
},{
field: "UnitPrice",
title: "Unit Price",
width: 150
}, {
field: "UnitsInStock",
title: "Units in Stock",
width: 150
}, {
field: "Discontinued",
width: 150
}]
});
});
</script>
</body>
</html>
For example what I want to do is to navigate to row 4 (this is working) but also navigate to column Discontinued and select that cell of that row.
Is there any way to do it? Using JavaScript or jQuery or a native function from KendoUI?
Here is a Dojo to play with.
Add a class to your Discontinued column definition:
{
field: "Discontinued",
width: 150,
attributes: {
class: "discontinued"
}
}
Change the selector you're using to select the row to the following:
var row = grid.element.find("tr[data-uid='" + modelToSelect.uid + "'] td.discontinued");
Replace grid.content.scrollTop(grid.select().position().top); with row[0].scrollIntoView();.
I have Kendo grid id = AddressID. when page load how can i click the first row automatically?
i tried the code below but no luck
var grid = $("#AddressGrid").data("kendoGrid");
grid.select("tr:eq(1)");
i tried this it selects the row but i want to trigger click
$(document).ready(function () {
var grid = $("#AddressGrid").data("kendoGrid");
grid.select(grid.tbody.find("tr:eq(1)").click());
});
If your data hasn't been loaded yet, there is nothing to select. You will have to specify the dataBound event and add you own handler.
Update: The change event fires whenever a row is selected either programatically or by the user's mouse.
$("#grid").kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Customers"
},
pageSize: 20
},
height: 550,
sortable: true,
selectable: "row",
pageable: { refresh: true, pageSizes: true, buttonCount: 5 },
columns: [
{ field: "ContactName", title: "Contact Name" },
{ field: "ContactTitle", title: "Contact Title" },
{ field: "CompanyName", title: "Company Name" },
{ field: "Country" }
],
change: onChange,
dataBound: onDataBind // Callback handler
});
function onDataBind(e) {
this.select("tr:eq(0)"); // this === $("#grid").data("kendoGrid")
}
function onChange(arg) {
const selected = [...this.select()].pop(); // multi-select is off
const record = this.dataItem(selected);
console.log(record.ContactName);
}
.as-console-wrapper { max-height: 4em !important; }
.as-console .as-console-row .as-console-row-code,
.as-console-row-code, .as-console-row:after { font-size: smaller; }
.k-grid { font-size: 0.667rem; }
.k-grid td { line-height: 1.667rem; }
<link href="https://kendo.cdn.telerik.com/2020.3.915/styles/kendo.common-material.min.css" rel="stylesheet">
<link href="https://kendo.cdn.telerik.com/2020.3.915/styles/kendo.materialblack.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.3.915/js/kendo.all.min.js"></script>
<div id="grid"></div>
We have selections persisting, maybe just a bit too much. :D
For example, if you have a multipage kendo grid with client side data, do this with a client side kendo grid:
Select a row on Page 1
Go to Page 2
Select a row on Page 2 THEN deselect it and select another row
Go back to Page 1 (row selection persists)
Go back to Page 2
Row selection persists, but also the row that was previously deselected is also selected.
Is there a solution to this? Something we can use in the change event:
http://dojo.telerik.com/#crunchfactory/uhEZe/7
Thank you,
j
Please try with the below code snippet.
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2015.2.902/styles/kendo.common-material.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2015.2.902/styles/kendo.material.min.css" />
<script src="https://kendo.cdn.telerik.com/2015.2.902/js/jquery.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2015.2.902/js/kendo.all.min.js"></script>
</head>
<body>
<script src="http://demos.telerik.com/kendo-ui/content/shared/js/products.js"></script>
<div id="example">
<div id="grid"></div>
<script>
$(document).ready(function () {
var selectedOrders = [];
var idField = "ProductID";
$("#grid").kendoGrid({
dataSource: {
data: products,
schema: {
model: {
fields: {
ProductName: { type: "string" },
UnitPrice: { type: "number" },
UnitsInStock: { type: "number" },
Discontinued: { type: "boolean" }
}
}
},
pageSize: 20
},
height: 550,
scrollable: true,
sortable: true,
selectable: "multiple, row",
pageable: {
input: true,
numeric: false
},
columns: [
"ProductName",
{ field: "UnitPrice", title: "Unit Price", format: "{0:c}", width: "130px" },
{ field: "UnitsInStock", title: "Units In Stock", width: "130px" },
{ field: "Discontinued", width: "130px" }
],
change: function (e, args) {
var grid = e.sender;
var items = grid.items();
items.each(function (idx, row) {
var idValue = grid.dataItem(row).get(idField);
if (row.className.indexOf("k-state-selected") >= 0) {
selectedOrders[idValue] = true;
} else if (selectedOrders[idValue]) {
delete selectedOrders[idValue];
}
});
},
dataBound: function (e) {
var grid = e.sender;
var items = grid.items();
var itemsToSelect = [];
items.each(function (idx, row) {
var dataItem = grid.dataItem(row);
if (selectedOrders[dataItem[idField]]) {
itemsToSelect.push(row);
}
});
e.sender.select(itemsToSelect);
}
});
});
</script>
</div>
</body>
</html>
Let me know if any concern.
I have a page with a Kendo Grid. When the user selects a row in the Grid I update a template and another grid with dependent information. I'm doing this by creating two new DataSources and binding them (see the code below).
To support live updates I want to attach, in the init() of the DataSource, an event handler to a websocket to detect changes in the backend for this DataSource (basically a subscription model). My problem is that in this page since every time the user selects an item I would get two more DataSources and so I would end up with lots of event handlers triggering for DataSources that are no longer used. I would like to clean them up somehow.
I can see a number of ways to handle this:
Have some event that triggers when the DataSource is no longer used so I can unregister the handler and unsubscribe.
Instead of creating a new DataSource each time just change the url in the transport each time. But then I'd like some event that triggers when the transport is changed so the event handler knows the subscription needs to be changed.
What I currently do: add a custom method to the DataSource called nuke() which I call just before creating the new DataSource. Error prone, but functional.
Or am I going about this completely the wrong way? Perhaps there is some general way to trigger on changes in Kendo objects?
Below is code that demonstrates the naive approach that causes the problem. It's also available here: http://dojo.telerik.com/OKaDu
Note the example code uses filters but in my actual code it's the URL that changes. Though if there is a way to trigger on changing filters that would be cool too.
<html>
<head>
<meta charset="utf-8">
<title>Kendo UI Snippet</title>
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.2.624/styles/kendo.common.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.2.624/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.2.624/styles/kendo.default.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.2.624/styles/kendo.dataviz.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.2.624/styles/kendo.dataviz.default.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.2.624/styles/kendo.mobile.all.min.css">
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2015.2.624/js/kendo.all.min.js"></script>
</head>
<body>
<div id="grid"></div>
<div id="detail">
Employee ID: <span data-bind="text: EmployeeID"></span><br>
FirstName: <span data-bind="text: FirstName"></span><br>
LastName: <span data-bind="text: LastName"></span><br>
</div>
<div id="orders"></div>
<script>
var element = $("#grid").kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "http://demos.kendoui.com/service/Northwind.svc/Employees"
},
pageSize: 6,
serverPaging: true,
serverSorting: true
},
height: 450,
selectable: "row",
sortable: true,
pageable: true,
columns: [
{
field: "FirstName",
title: "First Name"
},
{
field: "LastName",
title: "Last Name"
},
{
field: "Country"
},
{
field: "City"
},
{
field: "Title"
}
],
change: function(e) {
var selectedRows = this.select();
var dataItem = this.dataItem(selectedRows[0]);
var remoteDataSource = new kendo.data.DataSource({
type: "odata",
transport: {
read: "http://demos.kendoui.com/service/Northwind.svc/Employees"
},
serverPaging: true,
serverSorting: true,
serverFiltering: true,
pageSize:6,
filter: { field: "EmployeeID", operator: "eq", value: dataItem.EmployeeID }
});
remoteDataSource.fetch(function(){
kendo.bind("#detail", remoteDataSource.view()[0]);
});
$("#orders").kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "http://demos.kendoui.com/service/Northwind.svc/Orders"
},
serverPaging: true,
serverSorting: true,
serverFiltering: true,
pageSize:6,
filter: { field: "EmployeeID", operator: "eq", value: dataItem.EmployeeID }
},
scrollable: false,
sortable: true,
pageable: true,
columns: [
{ field: "OrderID", width: 70 },
{ field: "ShipCountry", title:"Ship Country", width: 100 },
{ field: "ShipAddress", title:"Ship Address" },
{ field: "ShipName", title: "Ship Name", width: 200 }
]
});
}
});
</script>
</body>
</html>
I have an angularjs - kendo UI grid-based solution. In the controller for the grid I have placed the following code:
$scope.customClick = function(e) {
$scope.$apply(
function() {
e.preventDefault();
alert('customClick');
});
};
$scope.gridOptions = {
dataSource: $scope.gridData,
pageable: {
refresh: true,
pageSizes: true,
buttonCount: 5
},
scrollable: true,
sortable: true,
filterable: true,
selectable: true,
editable: "inline",
columns: [
{
command :[ {text: "", template: '<input type="checkbox" id="check-all" />', click: $scope.customClick} ]
},
{field: "DocumentKey", title: "Document Key"},
{field: "Sender", title: "Sender"},
{field: "Recipient", title: "Recipient"},
{field: "ChangeDate", title: "ReceivedBy Time"},
{field: "FlowComment", title: "Comment"},
{field: "Location", title: "Location"}
]
};
});
Added checkbox is displayed fine, but I don't know how to handle the click event. $scope.customClick is not triggered after clicking on check box.
A fairly old question, the user had probably found a solution long ago, but in case google search gets someone to this question, it's good to have an answer. JavaScript combined with libraries like KendoUI and AngularJS usually allow us to solve problems by using several different approaches, but here is one of them:
Say you have a grid defined like this:
<div kendo-grid="kendo.myGrid" k-options="gridOptions"></div>
Your JavaScript code to define this grid might look like this:
$scope.gridOptions = {
dataSource: new kendo.data.DataSource({
data: dataFromSomeLocalVariableMaybe,
pageSize: 10
}),
sortable: true,
pageable: {
pageSizes: [10, 20, 50]
},
columns: [{
field: "column1",
title: "Column 1",
width: "100px"
}, {
field: "column2",
title: "Column 2",
width: "120px"
}, {
command: [{
template: "<span class='k-button' ng-click='doSomething($event)'> Do something</span>"
}, {
template: "<span class='k-button' ng-click='doSomethingElse($event)'> Do something else</span>"
}],
title: " ",
width: "100px"
}]
};
Notice the $event that is passed to ng-click call to a function. That $event contains the actual click event data.
If it would be like this, then you would need to have these two functions defined:
$scope.doSomething = function($event) {
// Get the element which was clicked
var sender = $event.currentTarget;
// Get the Kendo grid row which contains the clicked element
var row = angular.element(sender).closest("tr");
// Get the data bound item for that row
var dataItem = $scope.kendo.myGrid.dataItem(row);
console.log(dataItem);
};
$scope.doSomethingElse = function($event) {
// Do something else
};
And that's it.
Omit $scope.
It should as follows:
{ command : {text: "", click:customClick}, template: '<input type="checkbox" id="check-all"/>}
Your command template should include ng directive, in your case ng-change for the checkbox input, which would point to your target function:
{
command :[{
text: "",
template: '<input type="checkbox" id="check-all" ng-change="customClick"/>'
}]
}