Kendo grid aggregate error (count is not defined) - kendo-ui

I'm trying to use the aggregation feature on the kendo grid control.
But every time I got next error
Uncaught ReferenceError: count is not defined
error
Here is the demo demo

The answer is here: https://www.telerik.com/forums/declarative-creation-of-grid-with-data-attribues-(footertemplate)
Look for Daniel's responses
You have to change your footerTemplate to contain a conditional to avoid the error during initialization where your datasource hasn't yet been created due to the way things are initialized.
Change your footerTemplate to
footerTemplate: 'Total Count: #=data.UnitPrice ? data.UnitPrice.count : 0 #'
and it should work.
Demo: https://dojo.telerik.com/#Stephen/ADelIC

None of the solutions on the Internet for this issue helped me (including the accepted answer here).
I specified schema for the datasource, the aggregates field (as proposed by the Telerik documentation) and I was still getting the same error. Here is how I managed to solve this thing. First some background:
In order for the grid to perform aggregate functions, the data has to be in the grid's datasource upon creation of the grid
If your data is in the DOM (for example in a table element) and you create the grid on this table, the aggregate functions will not work (not only count, but max, min, etc.) and you will end up with this error. Note that the grid itself will work, because this is supported behaviour (I think it is called DOM binding)
You have to create kendo grid via source binding, i.e. specify in the datasource the data.
Telerik Documentation for source binding
Working example (with source binding):
HTML:
<div id="myGrid"></div>
JavaScript:
$("#myGrid").kendoGrid({
sortable: true,
dataSource: {
data: [{
Id: 1,
Url: "https://stackoverflow.com/",
Year: 2020,
Status: "Active"
}]
}
//Other configuration
});
Not working example (with DOM binding) -> ends up with
Uncaught ReferenceError: count is not defined error
HTML:
<table id="myGrid">
<tr>
<th>Id</th>
<th>Url</th>
<th>Year</th>
<th>Status</th>
</tr>
<tr>
<td>1</td>
<td>https://stackoverflow.com/</td>
<td>2020</td>
<td>Active</td>
</tr>
</table>
JavaScript:
$('#myGrid').kendoGrid({
sortable: true,
// Other configuration
});
If you do not want to change the DOM you can go with my approach:
Take the DOM elements using JQuery,
Loop them and create an array of JavaScript object
Pass the array to the grid as dataSource.data
Hide or remove from DOM the original table.
P.S.
I have not tried the grid behaviour when the datasource is with transport, i.e. using ajax with/without server paging, so there the behaviour could be different, because it makes no sense to show aggregated value only on a single page of the whole data, maybe then we have to return from the server this aggregated values (never tried that tbh).

Related

Update Google Charts Dashboard cell with HTML value

I have a Google Charts Dashboard instance bound to a ChartWrapper instance that has allowHtml: true, and a DataTable instance that we get from a query response:
...
data = response.getDataTable();
data.setTableProperty("allowHtml", true);
...
dashboard = new google.visualization.Dashboard(document.getElementById('dashboard'));
table = new google.visualization.ChartWrapper({
'chartType': 'Table',
'dataTable' : data,
'containerId': 'table',
'options' : {'allowHtml': true, 'showRowNumber': true} //,
});
...
dashboard.bind(filters, table);
dashboard.draw(data);
This enables the drawing of HTML fine. We return plenty of html via the response and it gets drawn to the DOM fine.
The problem comes in when we try to update a value in the chart via the DataTable object ("data" in the above code snippet). When we try to update the values of a cell using the DataTable.setCell() function call with an HTML string, the updated cell just shows the raw HTML and does not format the cell as HTML.
data.setCell(row_index, column_index, response.html);
dashboard.draw(data);
We've set both the ChartWrapper and DataTable options to allowHtml = true, and there doesn't seem to be a way to set the allowHtml property for the Dashboard.
Does anyone have any insight into this? Could it be something wrong with how the objects are bound to one another? According to Google Charts:
A ChartWrapper class is used to wrap your chart and handle all
loading, drawing, and Datasource querying for your chart.
Am I supposed to be using a different API for updating the value? I've tried setting column properties, setting table properties, etc to all be allowHtml = true but nothing I've tried has enabled me to update a table with HTML. It always shows the raw HTML string
Facepalm
Okay it turns out our serverside code at one point was encoding the HTML string via Django's render_to_string() function, so that things like "<" were being converted to <.
They showed up in the Google Charts as the right values, that is the < value rendered as "<" in the DOM. Once I took out the render_to_string call, everything worked fine.

Setting data attribute on each row of a jqgrid table

I am using jqGrid and I'm trying to add a data- attribute to each tr. I'm firing the loadComplete event, but I'm unsure of how to modify each row. Any code samples?
You can use rowattr to assign any additional attribute to <tr> elements (see the answer and this one for code examples). For example you can use
rowattr: function (rd) {
return {"data-mydata": JSON.stringify(rd)};
}
to save full input row data as data-mydata attribute. I recommend you to use rowattr``in combination withgridview: true` option to have the best performance results ()
The demo uses above rowattr cade and you can see that rows of grid have additional data-mydata attribute:
In my cases, I set the first column of grid by an identity. And in all my cases, id of each data row of my grids is the value of that identity column.
jqGrid column:
colModel: [
{
name:'ID',
label:'...',
width:1,
index:'ID'
...
Rendered :
<tr role="row" id="10777" ... > // in retrieved data: ID = 10777
So, if you have similar declarations like me, this could be a useful selector for you and you can simply add your data- attrib to these rows like this:
$('#trId').prop('data-whatever', 'value');
And if you want the above line to be performed automatically to all rows, you should change it slightly and put it into the gridComplete event of your grid:
gridComplete: function() { $("tr[role='row']").prop('data-whatever', 'value'); }

Kendo UI - Drop down list Setting Value autoBind = false setting

I am evaluating kendo ui right now to use in our big application. We have a situation where we have much values in dropdowns (like 200+) and there are more than 1 drop down with that size. So if we have a complex form. The Page Load takes time to render the form. (Due to that each box needs to be loaded from service and filled up).
We avoided this by writing our own asp.net web control with on demand support (like autoBind property) in the drop down list in kendo ui.
Now, DropDownList from KendoUI serves the purpose with autobind = false, BUT when setting value it fetches data from remote binding first and then selects appropriate value. (this is cool and really good for small lists) but Potentially this will mean that when we load the page and set the value it will issue remote binding calls for each of the drop downs.
Now,
Can we set value/ text to appear without issuing the remote binding. We want remote binding to be done ONLY when the user clicks on the drop down itself. (not when we are filling form). This will save extra calls to system and help quickly render the form to user.
Here is JS Bin
http://jsbin.com/ayivad/3/edit
If somebody from kendo ui would like me to help out - let me know, but this idea will allow us to use kendo ui drop downs with good use.
<input type="button" id="btnSet" value="Set Value (Click without clicking on DropDown" />
<br/><br/>
<select id="products"></select>
$(document).ready(function () {
$("#products").kendoDropDownList({
dataTextField: "ProductName",
dataValueField: "ProductID",
autoBind: false,
dataSource: {
transport: {
read: {
dataType: "jsonp",
url: "http://demos.kendoui.com/service/Products",
}
}
}
});
var combobox = $("#products").data("kendoDropDownList"),
setValue = function (e) {
if (e.type != "keypress" || kendo.keys.ENTER == e.keyCode)
combobox.value(3);
};
$("#btnSet").click(setValue);
});
Thanks,
Riz
1) Set text instead of value : http://docs.kendoui.com/api/web/dropdownlist#configuration-text
Kendo:
text String(default: "")
Define the text of the widget, when the autoBind is set to false.
Example
$("#dropdownlist").kendoDropDownList({
autoBind: false,
text: "Chai"
});
dirty alternative - Try to hijack ddl "optional label" for your needs. Load your data for the page inclusive of the value you want to show at the ddl, then initialize ddl's with optional values equal to the value you want to show. Once user opens the ddl, remote data will load, once data loaded you will ovewrite/remove the optional label and happy days.
http://docs.kendoui.com/api/web/dropdownlist#configuration-optionLabel
(Consider splitting the list, 200 long drop down us far from user friendly.)
$("#dropdownlist").kendoDropDownList({
optionLabel: "My value" });
Also consider using Kendo ComboBox, afterall auto complete after 3 chars or so sounds as quite sensible solution in case of your 200 items. We use same solution to 500 + combobox.

Kendo cascading dropdown loading dropdown based on other drop down selection

I am planning of using a cascading kendo drop down.
Drop down 1 - Countries - it will list down all the countries.
Drop down 2 - States - Based on the selection of the country I have to show the states here.
The data for both are loaded from my api controllers. I referred to this link
http://demos.kendoui.com/web/dropdownlist/cascadingdropdownlist.html
But, I need to pass the first selected value to the second drop down.
PLease suggest the best way to do it. Examples would be really helpful.
Thanks.
you have to use events for that
http://demos.kendoui.com/web/dropdownlist/events.html
.Events(e =>
{
e.Change("change").Select("select").Open("open").Close("close").DataBound("dataBound");
})
<script>
function change() {
// get a reference to the dropdown list
var dropdownlist = $("#dropdownlistTwoForStates").data("kendoDropDownList");
//Write your logic here to bind data for thie dropdown
// disable the dropdown list
dropdownlist.enable(true);
};
</script>

Browser Memory Usage Comparison: inline onClick vs. using JQuery .bind()

I have ~400 elements on a page that have click events tied to them (4 different types of buttons with 100 instances of each, each type's click events performing the same function but with different parameters).
I need to minimize any impacts on performance that this may have. What kind of performance hit am I taking (memory etc) by binding click events to each of these individually (using JQuery's bind())? Would it be more efficient to have an inline onclick calling the function on each button instead?
Edit for clarification :):
I actually have a table (generated using JQGrid) and each row has data columns followed by 4 icon 'button' columns- delete & three other business functions that make AJAX calls back to the server:
|id|description|__more data_|_X__|_+__|____|____|
-------------------------------------------------
| 1|___data____|____data____|icon|icon|icon|icon|
| 2|___data____|____data____|icon|icon|icon|icon|
| 3|___data____|____data____|icon|icon|icon|icon|
| 4|___data____|____data____|icon|icon|icon|icon|
I am using JQGrid's custom formatter (http://www.trirand.com/jqgridwsiki/doku.php?id=wiki:custom_formatter) to build the icon 'buttons' in each row (I cannot retrieve button HTML from server).
It is here in my custom formatter function that I can easily just build the icon HTML and code in an inline onclick calling the appropriate functions with the appropriate parameters (data from other columns in that row). I use the data in the row columns as parameters for my functions.
function removeFormatter(cellvalue, options, rowObject) {
return "<img src='img/favoritesAdd.gif' onclick='remove(\"" + options.rowId + "\")' title='Remove' style='cursor:pointer' />";
}
So, I can think of two options:
1) inline onclick as I explained above
--or--
2) delegate() (as mentioned in below answers (thank you so much!))
Build the icon image (each icon type has its own class name) using the custom formatter.Set the icon's data() to its parameters in the afterInsertRow JQGrid event. Apply the delegate() handler to buttons of specific classes (as #KenRedler said below)
> $('#container').delegate('.your_buttons','click',function(e){
> e.preventDefault();
> var your_param = $(this).data('something'); // store your params in data, perhaps
> do_something_with( your_param );
> }); //(code snippet via #KenRedler)
I'm not sure how browser-intensive option #2 is I guess...but I do like keeping the Javascript away from my DOM elements :)
Because you need not only a general solution with some container objects, but the solution for jqGrid I can suggest you one more way.
The problem is that jqGrid make already some onClick bindings. So you will not spend more resources if you just use existing in jqGrid event handler. Two event handler can be useful for you: onCellSelect and beforeSelectRow. To have mostly close behavior to what you currently have I suggest you to use beforeSelectRow event. It's advantage is that if the user will click on one from your custom buttons the row selection can stay unchanged. With the onCellSelect the row will be first selected and then the onCellSelect event handler called.
You can define the columns with buttons like following
{ name: 'add', width: 18, sortable: false, search: false,
formatter:function(){
return "<span class='ui-icon ui-icon-plus'></span>"
}}
In the code above I do use custom formatter of jqGrid, but without any event binding. The code of
beforeSelectRow: function (rowid, e) {
var iCol = $.jgrid.getCellIndex(e.target);
if (iCol >= firstButtonColumnIndex) {
alert("rowid="+rowid+"\nButton name: "+buttonNames[iCol]);
}
// prevent row selection if one click on the button
return (iCol >= firstButtonColumnIndex)? false: true;
}
where firstButtonColumnIndex = 8 and buttonNames = {8:'Add',9:'Edit',10:'Remove',11:'Details'}. In your code you can replace the alert to the corresponding function call.
If you want select the row always on the button click you can simplify the code till the following
onCellSelect: function (rowid,iCol/*,cellcontent,e*/) {
if (iCol >= firstButtonColumnIndex) {
alert("rowid="+rowid+"\nButton name: "+buttonNames[iCol]);
}
}
In the way you use one existing click event handler bound to the whole table (see the source code) and just say jqGrid which handle you want to use.
I recommend you additionally always use gridview:true which speed up the building of jqGrid, but which can not be used if you use afterInsertRow function which you considered to use as an option.
You can see the demo here.
UPDATED: One more option which you have is to use formatter:'actions' see the demo prepared for the answer. If you look at the code of the 'actions' formatter is work mostly like your current code if you look at it from the event binding side.
UPDATED 2: The updated version of the code you can see here.
You should use the .delegate() method to bind a single click handler for all elements ,through jQuery, to a parent element of all buttons.
For the different parameters you could use data- attributes to each element, and retrieve them with the .data() method.
Have you considered using delegate()? You'd have one handler on a container element rather than hundreds. Something like this:
$('#container').delegate('.your_buttons','click',function(e){
e.preventDefault();
var your_param = $(this).data('something'); // store your params in data, perhaps
do_something_with( your_param );
});
Assuming a general layout like this:
<div id="container">
<!--- stuff here --->
<a class="your_buttons" href="#" data-something="foo">Alpha</a>
<a class="your_buttons" href="#" data-something="bar">Beta</a>
<a class="your_buttons" href="#" data-something="baz">Gamma</a>
<a class="something-else" href="#" data-something="baz">Omega</a>
<!--- hundreds more --->
</div>

Resources