I have a KendoUI chart generated with JavaScript. Is there a way to clear the plotArea with a command? For the purpose of showing a "Loading..." image while waiting for a DataSource to read remote data.
Thanks
Displaying and hiding the loading animation is:
// Display progress
kendo.ui.progress($("#loading"), true);
// Hide progress
kendo.ui.progress($("#loading"), false);
Then you should use requestStart and requestEnd events in the DataSource for knowing when to show or hide the progress animation.
The DataSource of the Chart would be:
dataSource : {
transport : {
read: {
url:...
}
},
sort : {
field: "year",
dir : "asc"
},
requestStart: function () {
kendo.ui.progress($("#loading"), true);
},
requestEnd : function () {
kendo.ui.progress($("#loading"), false);
}
},
Example here: http://jsfiddle.net/OnaBai/kcptr/
Related
I have a grid control which I wish to export the content of. Upon initialisation, the pageSize attribute is set to 10 items however I want to increase the number of items per page during exportToPDF.
I have tried to modify the pageSize of the dataSource prior to carrying out the export but this seems to have no effect on the end product.
var grid = $("#grid").data("kendoGrid");
var filter = grid.dataSource.filter;
grid.dataSource.query({
filter: filter,
pageSize: 20, // has no effect on the exported PDF
page: 1,
group: [{
field: "groupField1",
dir: "asc"
}, {
field: "groupField2",
dir: "asc"
}, {
field: "groupField3",
dir: "asc"
}]
});
var progress = $.Deferred();
grid._drawPDF(progress)
.then(function (root) {
return kendo.drawing.exportPDF(root, { forcePageBreak: ".page-break", multiPage: true });
})
.done(function (dataURI) {
// ... do some manual manipulation of dataURI
kendo.saveAs({
dataURI: manipualtedDataURI
});
progress.resolve();
Is there something I am missing so I can display more items on each page of the PDF export?
EDIT
Including my grid definition with the pdfExport function suggested by the below answer (which never gets called):
var grid = $("#reportGrid").kendoGrid({
pdf: {
allPages: true,
avoidLinks: true,
repeatHeaders: true,
template: kendo.template($("#page-template").html()),
scale: 0.7,
margin: { top: "2.5cm", right: "1cm", bottom: "1.5cm", left: "1cm" },
paperSize: "A4",
landscape: true
},
// *this function is not getting called*
pdfExport: function(e) {
e.sender.dataSource.pageSize(10);
e.promise.done(function() {
e.sender.dataSource.pageSize(20);
});
},
toolbar: kendo.template($("#template").html()),
...
});
Note: A template is used to include a header / footer on each page of the PDF export.
Another note: 'Manual manipulation of dataURI' includes going out to the server to perform a merge with another PDF file, so I cannot use the default export via the grid :(
EDIT 2
I have extended the Dojo example from #R.K.Saini's answer to use the method by which I need to generate the PDF export (as per original post).
The snippet logs the URI of the grid being exported and when the pdfExport function is called. As you will see, when using the built in grid 'Export to PDF' button, the pdfExport function is triggered but when using the additional button below the grid, it is not.
You can use pdfExport event to change page size of your grid datasource before pdf export started and then when the export finish you just need to revert back the previous page size.
The call back function of this event receive grid instance as e.sender and and a promise as e.promise which can be used to set back the page size when exporting finish.
For more info check http://docs.telerik.com/kendo-ui/api/javascript/ui/grid#events-pdfExport
$("#grid").kendoGrid({
dataSource: dataSource,
pdf: {
allPages: true
},
pdfExport: function(e) {
e.sender.dataSource.pageSize(10);
e.promise.done(function() {
e.sender.dataSource.pageSize(20);
});
},
...
//Other configguration
});
Here is a working demo http://dojo.telerik.com/UzOXO
Edit
You can also change grid page size in your custom export function just change grid page size before calling _drawPdf() function and change it back when done.
$("#btnPdfExport").kendoButton({
click: function () {
var grid = $("#grid").data("kendoGrid");
var progress = $.Deferred();
// Change grid datasource pagesize before calling _drawPDF
grid.dataSource.pageSize(20);
grid._drawPDF(progress)
.then(function (root) {
return kendo.drawing.exportPDF(root, { forcePageBreak: ".page-break", multiPage: true });
})
.done(function (dataURI) {
console.log("Exporting " + dataURI);
kendo.saveAs({
dataURI: dataURI,
fileName: "export.pdf"
});
progress.resolve();
// Change grid datasource pagesize when done
grid.dataSource.pageSize(10);
});
}
});
Check Update DOJO here http://dojo.telerik.com/UzOXO/8
I am unable to get the built-in search for Kendo DropDownList to use the templated text instead of the raw text from the dataSource. I want to strip off the leading slash from the dataSource name for display, value, and search purposes.
<script>
$("#dropdownlist").kendoDropDownList({
dataSource: [ "/Apples", "/Oranges" ],
// None of these templates appear to fix the search text.
// Kendo is using the dataSource item to search instead of the template output.
// I want to be able to search using 'a' (for Apples) or 'o' (for Oranges).
// If I use '/' then it cycles through the items which proves to me that the search is not using templated text.
template: function(t) { return t.name.slice(1); },
valueTemplate: function(t) { return t.name.slice(1); },
optionLabelTemplate : function (t) { return t.name.slice(1); },
});
</script>
Here is a non-working sample in Kendo's UI tester:
http://dojo.telerik.com/#Jeremy/UvOFo
I cannot easily alter the dataSource on the server side.
If it's not possible to change how the search works then maybe there is a way to alter the dataSource after it's been loaded into the client from the server?
I'm not sure if this will help you at all, but I was able to force it to work. The control allows for you to subscribe to the filtering event on init. From here, you can set the value of the filter before it is submitted.
<script>
$("#dropdownlist").kendoDropDownList({
dataSource: ["/Apples", "/Oranges"],
template: function(t) { return t.slice(1); },
valueTemplate: function(t) { return t.slice(1); },
optionLabelTemplate : function (t) { return t.slice(0); },
filter: "startswith",
filtering: function(e) {
e.filter.value = '/'+e.filter.value;
}
});
</script>
Looking at the docs you can pass startup data to a widget:
editor.execCommand( 'simplebox', {
startupData: {
align: 'left'
}
} );
However this data is pointless as there seems to be no way to affect the template output - it has already been generated before the widget's init, and also the data isn't even available at that point:
editor.widgets.add('uselesswidget', {
init: function() {
// `this.data` is empty..
// `this.dataReady` is false..
// Modifying `this.template` here does nothing..
// this.template = new CKEDITOR.template('<div>new content</div>');
// Just after init setData is called..
this.on('data', function(e) {
// `e.data` has the data but it's too late to affect the tpl..
});
},
template: '<div>there seems to be no good way of creating the widget based on the data..</div>'
});
Also adding a CKEditor tag throws a "Uncaught TypeError: Cannot read property 'align' of undefined" exception so it seems the data is also not passed to the original template:
template: '<div>Align: {align}</div>'
What is the point of having a CKEDITOR.template.output function which can accept a context, if there's no way of dynamically passing data?
The only horribly hacky solution I've found so far is to intercept the command in a beforeCommandExec and block it, then modify the template and manually execute the command again..
Any ideas to generate dynamic templates based on passed data? Thanks.
Here's how I did it.
Widget definition:
template:
'<div class="myEditable"></div>',
init: function () {
// Wait until widget fires data event
this.on('data', function(e) {
if (this.data.content) {
// Clear previous values and set initial content
this.element.setHtml('')
var newElement = CKEDITOR.dom.element.createFromHtml( this.data.content );
this.element.append(newElement,true);
this.element.setAttribute('id', this.data.id);
}
// Create nestedEditable
this.initEditable('myEditable', {
selector: '.myEditable',
allowedContent: this.data.allowedContent
})
});
}
Dynamic widget creation:
editor.execCommand('myEditable', {startupData: {
id: "1",
content: "some <em>text</em>",
allowedContent: {
'em ul li': true,
}
}});
I'm new to Kendo and the Kendo grid but I'm trying to learn how to use the master detail Kendo grid where the detail grid is supposed to support batch editing. The data is available in a local JavaScript object.
This jsFiddle demonstrates the problems I'm seeing.
Here's how the grid is being created - see the jsFiddle for the complete snippet -
$("#grid").kendoGrid({
dataSource: items,
detailInit: createDetail,
columns: [
{ field: "Item", width: "200px" },
]
});
function createDetail(e) {
$("<div/>")
.appendTo(e.detailCell)
.kendoGrid({
dataSource: {
batch:true,
transport: {
read: function (options) {
options.success(e.data.SubItems);
}
}
},
editable:true,
pageable:true,
toolbar: ["save", "cancel"],
columns: [
{ field: "SubItem", title: "Sub Item", width: 200 },
{ field: "Heading1", title: "Heading 1", width: 100 }
]
});
}
When you edit an item in the grid and click to the next cell, the details grid automatically collapses not matter where I click, even in an adjacent cell. When I open it again, I don't see the change indicator in the cell (red notch) but the new value is there.
If I were to hook up the save to an ajax call, Kendo sends the right detail item(s) that were edited.
Nothing happens when I click cancel changes.
How do I get the grid to not collapse and see the change indicators ?
How do I get canceling of changes to work correctly ?
[Update] - Further investigation reveals that if I use an older Kendo version 2011.3.1129 , this works as expected. But if I use the newer 2012.3.1114, it doesn't. Dont know if this is a bug or a change in behavior.
After much effort, I found that the cause seems to be that the master grid is rebinding automatically causing the behavior I observed. I was able to get around this by handling the dataBinding event in the master grid and within that, checking if any of the detail datasources were dirty and if so, calling preventDefault.
Here are relevant code snippets :
dataBinding: function (e) {
if (masterGrid.AreChangesPending()) {
e.preventDefault();
}
}
AreChangesPending : function () {
var pendingChanges = false;
// I gave each detail div an id so that I can get a "handle" to it
$('div[id^="detail_"]').each(function (index) {
var dsrc = $(this).data("kendoGrid").dataSource;
$.each(dsrc._data, function () {
if (this.dirty == true || this.isNew()) {
pendingChanges = true;
}
});
// For some reason, Kendo did not detect new rows in the isNew()
// call above, hence the check below
if (dsrc._data.length != dsrc._total) {
pendingChanges = true;
}
});
return pendingChanges;
}
I'm using an Ext.picker.Date and I have some checks I run on the hide event. However, if a certain criteria is met, I want to stop the process and have the date picker not hide.
I've tried using the beforehide event, and running my code there, but that event doesn't seem to fire.
Below is the config for my datepicker. If the condition is true, how can I stop the picker from hiding?
Thanks for any help.
var datePicker = new Ext.picker.Date({
docked: "bottom",
listeners: {
beforehide: function() {
console.log("before hide");
},
hide: function() {
if (1 == 1) {
//how do I stop the picker from hiding?
Ext.Msg.alert("You cannot select that date.");
}
}
},
slotOrder: ["day", "month", "year"],
useTitles: false
});
this.add(datePicker);
Are you using Sencha Touch 2? I'm going to assume so, since you're using Ext.picker.Date.
According to the documentation, the date picker doesn't fire a beforehide event:
Sencha Docs
What you really want to do here is insert some logic after 'Done' is tapped and before the picker hides itself. The picker calls onDoneButtonTap internally; you can inject your own logic like so:
Ext.define('MyApp.widget.DatePicker', {
extend: 'Ext.picker.Date',
xtype: 'mypicker',
onDoneButtonTap: function() {
if (1 == 1) {
Ext.Msg.alert("You cannot select that date.");
} else {
Ext.picker.Date.prototype.onDoneButtonTap.call(this);
}
}
});
this.add({
xtype : 'mypicker',
docked : "bottom",
slotOrder : ["day", "month", "year"],
useTitles : false
});
This is assuming that your logic will be able to access what it needs within the scope of the date picker. If this isn't the case, you can pass additional configuration to the date picker when you create it...maybe something like acceptedDateRange {...}
The simplest way could be:
var datePicker = new Ext.picker.Date({
docked: "bottom",
slotOrder: ["day", "month", "year"],
useTitles: false,
onDoneButtonTap: function() {
if (1 == 1) {
Ext.Msg.alert("You cannot select that date.");
} else {
Ext.picker.Date.prototype.onDoneButtonTap.call(this);
}
}
});
this.add(datePicker);
I think defining your own class like in the first example is the way to go, especially in situations where you inject logic into existing framework code and when you use the component in more than one place. But the second example will work as well.