Confused about viewmodel creation where I have to add a computed field - ajax

My json call returns an object array:
[
{
Table: 1,
FirstName: "Bert",
LastName: "Smith",
Place: 1
},
{
Table: 1,
FirstName: "Suzanne",
LastName: "Smith",
Place: 2
},
{
Table: 1,
FirstName: "Matthew",
LastName: "Stewart",
Place: 3
},
{
Table: 1,
FirstName: "Brian",
LastName: "Robinson",
Place: 4
},
{
Table: 1,
FirstName: "Jennifer",
LastName: "Robinson",
Place: 5
},
{
Table: 1,
FirstName: "Andrew",
LastName: "Caygill",
Place: 6
},
{
Table: 1,
FirstName: "Susan",
LastName: "Caygill",
Place: 7
},
{
Table: 1,
FirstName: "John",
LastName: "Spreadbury",
Place: 8
},
{
Table: 1,
FirstName: "Anne-Marie",
LastName: "Nevin",
Place: 9
}]
I have a template in my HTML:
<script type="text/html" id="dataLine">
<div class="itemLine">
<div class="Name">
<span class="fixtureBoxLine" data-bind="text: fullName"></span>
</div>
<div class="TableNo">
<span class="fixtureBoxLine" data-bind="text: Table"></span>
</div>
</div>
</script>
and the binding is:
<div data-bind="template: { name: 'dataLine', foreach: pageCol1 }"></div>
My viewmodel is:
var viewModel = {
fields: ko.observableArray([]),
pageSize: ko.observable(1),
pageIndex: ko.observable(0)
};
viewModel.pageCol1 = ko.computed(function() {
var size = Number(this.pageSize());
var start = this.pageIndex() * size * 2; //2 cols per page
var end = start + size;
return this.fields.slice(start, end);
}, viewModel);
All works fine except I can't get a "fullname" property. If I try adding it to the viewmodel in the same way as I did with "pageCol1" above, then as my json success property just does:
viewModel.fields(xlData);
it doesn't work as there is no "fullName" property on the data returned.
I feel I've tried every possible combination today and have now given myself a headache! Please would someone point me in the right direction?
Thanks!

Try extending your pageCol1 by adding new field (concatenated from another two) to your response array like:
viewModel.pageCol1 = ko.computed(function() {
var size = Number(this.pageSize());
var start = this.pageIndex() * size * 2; //2 cols per page
var end = start + size;
for( var i = 0, len = this.fields.length; i < len; i++ ) {
this.fields[ i ].fullName = this.fields[ i ].FirstName + ' ' + this.fields[ i ].LastName;
}
return this.fields.slice(start, end);
}, viewModel);
so in final result before you're iterating over your array it will be like:
[
{
Table: 1,
FirstName: "Bert",
LastName: "Smith",
fullName: "Bert Smith",
Place: 1
},
{
Table: 1,
FirstName: "Suzanne",
LastName: "Smith",
fullName: "Suzanne Smith",
Place: 2
},
{
Table: 1,
FirstName: "Matthew",
LastName: "Stewart",
fullName: "Matthew Stewart",
Place: 3
},
...

Related

Showing tooltip for the frozen row in Kendo Grid

I have a kendo grid with a one frozen row on the top. I wanted to show a tool tip when user hover mouse over the grid row. I was able to show tooltip for all the rows except for the top frozen row. The top frozen row still shows data from the second row.
$(document).ready(function () {
$("#grid").kendoGrid({
autoBind: false,
height: 300,
columns: [{ field: "Source", title: "Source" },
{ field: "FirstName", title: "First Name" },
{ field: "LastName", title: "Last Name" }],
dataSource: {
data: [
{ Source: "Master", FirstName: "Foo", LastName: "Bar" },
{ Source: "2", FirstName: "FirstName 2", LastName: "Last Name 2" },
{ Source: "3", FirstName: "FirstName 3", LastName: "Last Name 3" },
{ Source: "4", FirstName: "FirstName 4", LastName: "Last Name 4" },
{ Source: "5", FirstName: "FirstName 5", LastName: "Last Name 5" },
{ Source: "6", FirstName: "FirstName 6", LastName: "Last Name 6" },
{ Source: "7", FirstName: "FirstName 7", LastName: "Last Name 7" },
{ Source: "8", FirstName: "FirstName 8", LastName: "Last Name 8" },
{ Source: "9", FirstName: "FirstName 9", LastName: "Last Name 9" },
{ Source: "10", FirstName: "FirstName 10", LastName: "Last Name 10" },
{ Source: "11", FirstName: "FirstName 11", LastName: "Last Name 11" },
{ Source: "12", FirstName: "FirstName 12", LastName: "Last Name 12" }
]
}
});
var kGrid = $("#grid").data("kendoGrid");
kGrid.bind("dataBound", function (e) {
console.log("dataBound");
var frozenRow;
var items = e.sender.items();
items.each(function () {
var row = $(this);
var dataItem = e.sender.dataItem(row);
if (dataItem.Source == "Master") {
frozenRow = row;
}
})
if (frozenRow) {
var cloned = frozenRow.clone();
cloned.addClass("im-frozen-row");
var thead = kGrid.element.find(".k-grid-header table thead");
thead.append(cloned);
frozenRow.hide();
}
});
kGrid.dataSource.fetch();
$("#grid").kendoTooltip({
filter: ".k-master-row", //this filter selects the second column's cells and the second column header
position: "top",
width: 250,
content: function (e) {
// If the element is the header, return the text of the cell.
if (e.target.is("th")) {
return e.target.text();
}
var dataItem = $("#grid").data("kendoGrid").dataItem(e.target);
return "Source: " + dataItem.Source + "<br/>" + dataItem.FirstName + "," + dataItem.LastName;
}
}).data("kendoTooltip");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2022.1.412/styles/kendo.common.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2022.1.412/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2022.1.412/styles/kendo.default.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2022.1.412/styles/kendo.mobile.all.min.css">
<script src="https://kendo.cdn.telerik.com/2022.1.412/js/kendo.all.min.js"></script></head>
<div id="grid"></div>
Try this, I am using your custom class that you are adding to the row that you clone into header section "im-frozen-row" to identify your frozen row when you are adding tooltips.
Your if condition is not able to identify your row since it is not a "th" type element. And since you are already having a class that you add in your clone, it is easier to find the element you're looking for.
$("#grid").kendoTooltip({
filter: ".k-master-row", //this filter selects the second column's cells and the second column header
position: "top",
width: 250,
content: function (e) {
if(e.target.hasClass("im-frozen-row")) { //Note this will allow to identify your frozen row
let arr = e.target.text().match(/[A-Z][a-z]+/g); // Here your returned response is for your data here "MasterFooBar", because this is hardcoded data I can break the words into 3 words, but if you'd like to have exact same tooltips as other rows with some other type of data it will not work.
let str = `Source: ${arr[0]}, First Name: ${arr[1]}, Last Name: ${arr[2]}`; // I am concatenating string to show exactly the type of tooltip other rows have.
return str;
}
var dataItem = $("#grid").data("kendoGrid").dataItem(e.target);
return "Source: " + dataItem.Source + "<br/>" + dataItem.FirstName + "," + dataItem.LastName;
}
}).data("kendoTooltip");
Please note that you can also print your tooltip as is what is returned from "e.target.text()".

free jqGrid with Caption and without column headers

I want to display the caption, but not the column headers. When the grid is first displayed only the caption should be visible. When the grid is expanded, the column headers are visible. Please see jsFiddle
var $grid = $("#grid");
$grid.closest("div.ui-jqgrid-view")
.children("div.ui-jqgrid-hdiv")
.hide();
Here you go with a solution https://jsfiddle.net/7v70640y/5/
$("#grid").jqGrid({
colModel: [
{ name: "firstName" },
{ name: "lastName" }
],
caption: "The caption",
hiddengrid: true,
data: [
{ id: 10, firstName: "Angela", lastName: "Merkel" },
{ id: 20, firstName: "Vladimir", lastName: "Putin" },
{ id: 30, firstName: "David", lastName: "Cameron" },
{ id: 40, firstName: "Barack", lastName: "Obama" },
{ id: 50, firstName: "François", lastName: "Hollande" }
]
});
$('div[role="columnheader"]').parent().hide();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.14.1/css/ui.jqgrid.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.14.1/jquery.jqgrid.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/themes/redmond/jquery-ui.min.css" rel="stylesheet"/>
<table id="grid"></table>
Just hide the div & it's parent div which has role as columnheader
$('div[role="columnheader"]').parent().hide();
Update with multiple jqGrid
Here you go with a solution https://jsfiddle.net/7v70640y/6/
$("#grid1").jqGrid({
colModel: [
{ name: "firstName" },
{ name: "lastName" }
],
caption: "The caption",
hiddengrid: true,
data: [
{ id: 10, firstName: "Angela", lastName: "Merkel" },
{ id: 20, firstName: "Vladimir", lastName: "Putin" },
{ id: 30, firstName: "David", lastName: "Cameron" },
{ id: 40, firstName: "Barack", lastName: "Obama" },
{ id: 50, firstName: "François", lastName: "Hollande" }
]
});
$("#grid2").jqGrid({
colModel: [
{ name: "firstName" },
{ name: "lastName" }
],
caption: "The caption",
hiddengrid: true,
data: [
{ id: 10, firstName: "Angela", lastName: "Merkel" },
{ id: 20, firstName: "Vladimir", lastName: "Putin" },
{ id: 30, firstName: "David", lastName: "Cameron" },
{ id: 40, firstName: "Barack", lastName: "Obama" },
{ id: 50, firstName: "François", lastName: "Hollande" }
]
});
$('#gview_grid1').find('div[role="columnheader"]').parent().hide();
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/themes/redmond/jquery-ui.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.14.1/css/ui.jqgrid.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.14.1/jquery.jqgrid.min.js"></script>
<table id="grid1"></table>
<br/><br/>
<table id="grid2"></table>
Hope this will help you.

sorting in kendo grid using custom values

need help with sorting these json results by days inside kendoGrid. I need a way to turn the plus sign into .5 or something along those lines. I suppose I have to loop through each one, if i find the plus sign then change the value to number.5 and then drop the new value back in before displaying?
{ name: Alex, days: "2" },
{ name: Jason, days: "1" },
{ name: Fred, days: "2+" },
{ name: Jane, days: "3" },
{ name: John, days: "3+" }
Here is code I got working
<body>
<div id="grid">
</div>
<div>
<script>
$(document).ready(function () {
//JSON data
var people = [
{ firstName: "Hasibul", lastName: "Haque", email: "hasibul2363#gmail.com", rank:"2" }
, { firstName: "Jane", lastName: "Smith", email: "jane.smith#kendoui.com", rank: "3+" }
, { firstName: "Jason", lastName: "Doe", email: "hasibul2363#gmail.com", rank: "1" }
, { firstName: "John", lastName: "doe", email: "hasibul2363#gmail.com", rank: "3+" }
, { firstName: "Joan", lastName: "doe", email: "hasibul2363#gmail.com", rank: "5" }
, { firstName: "Jack", lastName: "doe", email: "hasibul2363#gmail.com", rank: "3" }
, { firstName: "Jacob", lastName: "doe", email: "hasibul2363#gmail.com", rank: "3-" }
, { firstName: "Joe", lastName: "doe", email: "hasibul2363#gmail.com", rank: "3-" }
];
$('#grid').kendoGrid({
dataSource: {
type: "json",
data: people,
pageSize: 15,
sort: ({ field: "rank" })
},
sortable: true,
columns:[{
field: "rank",
sortable: {
compare: function (a, b, asc) {
var s1 = a.rank;
var s2 = b.rank;
var n1, n2;
var sg1, sg2;
var plus = s1.indexOf('+');
var minus = s1.indexOf('-');
if(plus >= 0){
n1 = parseInt(s1.substr(0, plus));
sg1 = 1;
}
else if(minus >= 0){
n1 = parseInt(s1.substr(0, minus));
sg1 = -1;
}
else{
n1 = parseInt(s1);
sg1 = 0;
}
plus = s2.indexOf('+');
minus = s2.indexOf('-');
if (plus >= 0) {
n2 = parseInt(s2.substr(0, plus));
sg2 = 1;
}
else if (minus >= 0) {
n2 = parseInt(s2.substr(0, minus));
sg2 = -1;
}
else {
n2 = parseInt(s2);
sg2 = 0;
}
if (n1 == n2) {
return sg2 - sg1;
} else {
return n2 - n1;
}
}
}
}]
,
pageable: {
buttonCount: 1
},
schema: {
data: "people"
}
//binding JSON data with grid
});
});
</script>

What is the method to group the data remotely for kendo grid?

I have data coming from the server like
Id AppId
1 23
2 28
1 69
1 123
What is the way to make it like this on kendo grid
Id AppId
1 23,69,123
2 28
You can use the group feature of the datasource:
var data = [
{Id: 1, AppId: 23},
{Id: 2, AppId: 28},
{Id: 1, AppId: 69},
{Id: 1, AppId: 123},
];
var ds = new kendo.data.DataSource({
data: data,
schema: {
model: {
fields: {
Id: { type: "number" },
AppId: { type: "number" },
}
}
},
group: {
field: "Id"
}
});
Then if you want to use the grid group by feature:
$("#grid").kendoGrid({
dataSource: ds,
columns: [
{ field: "Id", title: "ID", },
{ field: "AppId", title: "Application ID" },
]
});
If you want the comma delimited list, use the fetch() method of the datasource to build the new data array:
var groupedData = [];
ds.fetch(function(){
var data = this.view();
for (var i=0; i< data.length; i++){
var id = data[i].value;
var text = '';
for (var j=0; j< data[i].items.length; j++){
text += data[i].items[j].AppId;
if (j< data[i].items.length - 1){
text += ',';
}
}
groupedData.push({Id: id, AppId: text});
}
});
$("#grid2").kendoGrid({
dataSource: groupedData,
columns: [
{ field: "Id", title: "ID", },
{ field: "AppId", title: "Application ID" },
]
});
The following DOJO presents both options:
DEMO

Failing at constructing an instance of kendo.data.DataSource

I am having a basic problem which prevents me from developing a custom plugin based on KendoGrid. When I do this:
var ds = kendo.data.DataSource.create({
data: [
{ FirstName: "Joe", LastName: "Smith" },
{ FirstName: "Jane", LastName: "Smith" }
]
});
then ds.view() returns an empty array. Same with an alternative constructor: new kendo.data.DataSource({})
What am I doing wrong?
Your data is not available because the view() method "...should be used within the change event handler or the fetch method.".
Your code should look something like this.
var ds = new kendo.data.DataSource({
data: [
{ FirstName: "Joe", LastName: "Smith" },
{ FirstName: "Jane", LastName: "Smith" }
]
});
ds.fetch(function() {
var view = ds.view();
console.log(view[0].FirstName); // displays "Joe"
});
View the documentation for the view method here.

Resources