Made my own VSTS extension that returns a Grid with a list of bugs read using a wiql.
I want the (UI Control) Grid to include the bug title and hyperlink to the bug url so that it is possible to click on the title to jump to the bug. I could not find any possibility to do that, but I do not believe that it is not possible.
This is how I'm building my source to the grid:
var sourceArray = workItems.map(function (w) {
return [
w.id,
w.fields["System.Title"],
w.fields["System.State"],
w.fields["GrundfosScrum.gfSeverity"],
w.fields["GrundfosScrum.gfLikelihood"],
w.fields["System.AssignedTo"]];
});
And later:
var options = {
width: "100%",
height: "500px",
source: sourceArray,
columns: [
{ text: "ID", index: 0, width: 100, headerCss: "mystyle" },
{ text: "Title", index: 1, width: 200, headerCss: "mystyle" },
{ text: "State", index: 2, width: 100, headerCss: "mystyle" },
{ text: "Severity", index: 3, width: 200, headerCss: "mystyle" },
{ text: "Likelihood", index: 4, width: 200, headerCss: "mystyle" },
{ text: "Assigned To", index: 5, width: 300, headerCss: "mystyle" },
]
};
I tried to replace w.fields["System.Title"] with w.fields["System.Title"].link(w.url), the result was html hyperlink in the table instead of a hyperlink inside the grid.
Any ideas?
This is not supported by add link in the grid. But you can call Open row details method to to achieve the feature you want. Get the URL information and open a new window when the openRowDetail method is triggered.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Open Row Sample</title>
<script src="sdk/scripts/VSS.SDK.js"></script>
</head>
<body>
<script type="text/javascript">
VSS.init({
explicitNotifyLoaded: true,
usePlatformScripts: true,
usePlatformStyles: true
});
</script>
<h1>Open Row Sample</h1>
<div id="grid-container"></div>
<script type="text/javascript">
VSS.require(["VSS/Controls", "VSS/Controls/Grids"],
function (Controls, Grids) {
var dataSource = [];
dataSource.push({key: "VisualStudio", value: "https://www.visualstudio.com/"});
dataSource.push({key: "Bing", value: "https://www.bing.com/"});
var grid = Controls.create(Grids.Grid, $("#grid-container"), {
height: "1000px",
columns: [
{ text: "Property key", index: "key", width: 150 },
{ text: "Property value", index: "value", width: 600 }
],
source: dataSource,
openRowDetail: (index) => {
var info = grid.getRowData(index);
window.open(info.value);
}
});
VSS.notifyLoadSucceeded();
});
</script>
</body>
</html>
For anyone else is struggling with this like I was (as the documentation is pretty poor for the more granular stuff), I did it as follows.
Firstly, in the column definition in the later versions you just add a hrefIndex to the field you wish to bind e.g.
{ text: "Path", index: "path", width: 600, hrefIndex:'branchUrl' },
This works for the most part, but there doesn't appear to be (or at least, in the version I'm using) a binding for the target. So instead, I'd override the _drawCell function call as follows:
{ text: "Path", index: "path", width: 600, hrefIndex:'branchUrl', getCellContents : renderHref }
Where renderHref is:
var renderHref = function(rowInfo, dataIndex, expandedState, level, column, indentIndex, columnOrder){
var indent;
var cell = document.createElement('div');
cell.className = 'grid-cell';
var width = column.width || 20;
cell.style.width = isNaN(width) ? width : width + "px";
var jCell = $(cell);
var hrefText = this.getColumnValue(dataIndex,column.hrefIndex,-1);
var text = this.getColumnText(dataIndex,column,columnOrder);
jCell.append($("<a/>").attr("href", hrefText).attr('target','_blank').text(text));
return jCell;
};
Note that in my override I haven't bothered with the same logic as the original _drawCell for the indents etc., as I didn't need it.
This ensures that the hyperlink is rendered within the div container as a grid cell within the grid, and also allows you to set the target.
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 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).
This is my div but it outside kendo grid
<div>
<div id="qrUrl"></div>
</div>
This is my kendo grid field
columns: [
{
field: "Id",
},
{
title: "QrCode",
width: 300,
template: function(dataItem)
{
$(#Qrurl).kendoQRCode({
value: "www.google.com"+ dataItem.Id,
errorCorrection: "M",
size: 120,
border: {
color: "#000000",
width: 5
}
});
}
In this situation my Qrcode generated outside grid with uniq (url+id )
but i want to this all qrcode in my kendo grid.
i tried servel time this and another code but still not reached up to mark.
template: function(dataItem)
{
$('<div></div>')
.kendoQRCode({
value: "www.google.com"+ dataItem.Id,
errorCorrection: "M",
size: 120,
border: {
color: "#000000",
width: 5
}
});
}
If i tried with div id at that time i got qrcodes as per requirement but outside grid here, i want to complete this thing in my grid.
Please help me.
Thank you for advance.
The template function needs to return a string of the HTML that will be used. I would have the template create an empty DIV in the grid cell with a class="QRME" and a data attribute for the id. Then in the dataBound event of the grid, loop through all the QRME divs, get the id and create the QR codes:
$("#grid").kendoGrid({
columns: [ {
field: "Id",
}, {
title: "QrCode",
width: 300,
template: function(dataItem) {
return "<div class='QRME' data-id='" + kendo.htmlEncode(dataItem.Id) + "'></div>";
}
}],
dataSource: [ { Id: "1" }, { Id: "2" }, { Id: "3" } ],
dataBound: function(e) {
$("div.QRME").each(function(idx){
$(this).kendoQRCode({
value: "www.google.com"+ $(this).data("id"),
errorCorrection: "M",
size: 120,
border: {
color: "#000000",
width: 5
}
});
});
}
});
Working DEMO
I can't use dataBound and therefore I was looking for a solution that works with template.
First I make a div instance and put the QR code there and return outerHTML.
template: function(dataItem) {
return jQuery("<div class='qrcode'></div>")
.kendoQRCode({
value: kendo.htmlEncode(dataItem["Id"]),
errorCorrection: "M",
size: 60,
border: {
color: "#000",
width: 1
}
}).html();
}
working DEMO
If I add a button to my panel via a 'renderTo' argument (See 'b' below), it works perfectly :
//create div in javascript
var extJSTest = document.createElement('div');
//append to main
mainPanel.appendChild(extJSTest);
//'get' panel through EXT (just adds a wrapper?)
var myDiv = Ext.get(extJSTest);
var b = Ext.create('Ext.Button', {
text: 'Click me!!!!',
renderTo: myDiv,
handler: function() {
alert('You clicked the button!')
}
});
However, if, I replace the 'b' with the following code (That is, i want to replace the button with a grid, connected up with a SimpleStore and some data)...
var myData = [
['Apple',29.89],
['Ext',83.81]
];
var ds = new Ext.data.SimpleStore({
fields: [
{name: 'company'},
{name: 'price'}
]
});
ds.loadData(myData);
var grid = new Ext.grid.GridPanel({
store: ds,
columns: [
{header: "Company", width: 120, dataIndex: 'company'},
{header: "Price", width: 90, dataIndex: 'price'}
],
renderTo: myDiv,
height: 180,
width: 900,
title: 'List of Packages'
});
I get this error :
Uncaught TypeError: Cannot read property 'dom' of null
Which is found at line 28211 in ext-all-debug. Code looks like this :
if (!me.container) {
me.container = Ext.get(me.el.dom.parentNode);
}
Anyone know what the issue is when i want to add a grid?
Also my index.html looks like this :
<script>
Ext.require([
'Ext.data.*',
'Ext.grid.*',
'Ext.tree.*'
]);
Ext.onReady (function () {
//application is built in here
});
</script>
Here's a fiddle :
https://fiddle.sencha.com/#fiddle/693
If I render to Ext.getBody() it works fine, but if i render to my own myDiv object it seems to have problems.
My solution to my question..
I am confusing renderTo with add.
I should create a panel, and use renderTo to put it somewhere on the DOM, and then later I can create a grid and then the panel can 'add' it.
Ext.onReady (function () {
var myDiv = Ext.create('Ext.Panel',{
renderTo:Ext.getBody(),
})
var myData = [
['Apple',29.89],
['Ext',83.81]
];
var ds = new Ext.data.SimpleStore({
fields: [
{name: 'company'},
{name: 'price'}
]
});
ds.loadData(myData);
var grid = new Ext.grid.GridPanel({
store: ds,
columns: [
{header: "Company", width: 120, dataIndex: 'company'},
{header: "Price", width: 90, dataIndex: 'price'}
],
height: 180,
width: 900,
title: 'List of Packages'
});
myDiv.add(grid);
//document.body.appendChild(myDiv);
});
I want to add buttons in one of columns in the grid. I try this code
listeners: {
render: {
fn: function(kad_tab){
var view = kad_tab.getView();
for (var i = 0; i < store.getCount(); i++) {
var cell = Ext.fly(view.getCell(i, 2));
new Ext.Button({
handler: function(){
alert('Suppression')
},
renderTo: cell.child(".btn"),
text: 'Supprimer'
});
}
},
// delay: 200
}
}
{header: "", width: 70, dataIndex: '', renderer: function(){ return '<div class="btn" style="height: 11px; width: 60px"></div>';}}
But firebug says that he see error here Ext.fly(this.getRow(c)) is null.
if i use delay: 200. There is no errors in firebug but dont see a buttons in column.
What im doing wrong?
I found a simple way...
{
xtype: 'actioncolumn',
width: 50,
items: [{
icon : url_servlet+'externals/gxp/src/theme/img/pencil.png',
tooltip: 'Button click',
handler: function(grid, rowIndex, colIndex) {
alert("DAMACIA!!!!!");
}
}]
}