ExtJS AJAX save as dialog box - extjs

I make an ExtJS AJAX request and I want the standard browser 'save as' dialog box to be displayed to the user. The file to download can be a pdf, jpg or png file.
At the moment the AJAX request is successfully submitted but as it's asynchronous no dialog box comes up.
I could simply not use AJAX but there is a lot of javascript code that I need to use prior to making the request and I don't really feel rewriting it to java.
My code looks like this:
var params = getPrintInfo(form);
Ext.Ajax.request({
url : 'print',
method : 'POST',
params : {
customData: params.customData,
dpi: params.dpi,
format: params.format,
grid: params.grid,
title: params.title
},
autoAbort : false,
success : function(result, request) {
if(result.responseText==''){
//display error message
}else{
// display save as dialog box
}
}
});
In my controller I'm setting the headers to be:
httpResponse.setHeader("Content-disposition", "attachment; filename=" + this.config.getString("print.file.name")+outputType);
EDIT:
Have actually found this solution:
Ext.DomHelper.append(document.body, {
tag: 'iframe',
frameBorder: 0,
width: 0,
height: 0,
css: 'display:none;visibility:hidden;height:1px;',
src: 'http://blabla.com/f75e927b-2041-473e-86ba-cbbc60dbc285.pdf'
});
Now the question is: How can I change the pdf name to be pretier, for example map.pdf instead of having that long ugly alphanumeric string?

You can use window.open to have save as dialog box, for example
window.open('print?parameters...','_blank');

Related

Kendo Grid Server Side filtering sending null as a filter object to the backend

Using Kendo AngularJS and ASP .NET MVC I am trying to send the filters object of a grid to the backend. However any filters made on the frontend are null in the request even though I set serverFiltering to true.
grid.dataSource = new kendo.data.DataSource({
serverFiltering: true,
transport: {
read: {
url: "api/foo",
dataType: "json",
type: "POST"
}
},
schema: {
data: "data", // records are returned in the "data" field of the response
total: "total"
}
});
//set grid to filterable
grid.filterable = {
mode: 'row',
operators: {
string: {
contains: "contains"
}
}
};
I took a look at a similar question but it did not help me as I wasn't able to replicate the solution listed as the accepted answer
On the controller side the "DataSourceRequest" mapped out the form values differently (e.g. inspecting the POST request on the frontend sent "filter" instead of "Filters" as an argument. I had to create a new model class that binded the proper values

this.proxy is undifened EXT JS paging

I have a store :
var store = new Ext.data.JsonStore({
root: 'list',
fields: rec,
totalProperty:'totalCount',
pruneModifiedRecords:true
});
And want to do paging.
my paging toolbar :
var paging = new Ext.PagingToolbar({
pageSize : limit,
width : 600,
store : store,
displayInfo : true,
displayMsg : 'Total: {2}, (Show:{0}-{1})',
emptyMsg : "No data"
});
and my grid :
var grid = new Ext.grid.EditorGridPanel({
region:'center',
stripeRows: true,
frame: false,
border:false,
loadMask: {msg : 'Loading...'},
trackMouseOver:false,
store: store,
cm: cm,
sm: sm,
tbar:gridTbar,
bbar: paging,
viewConfig: {enableRowBody:true,emptyText: 'no data'}
});
And when button pressed load data from database :
var limit= 100;
function storeDoldur(){
Ext.Ajax.request({
url: '../project/listData.ajax',
params:{
date:date.getRawValue(),
start:0,
limit:limit
},
success:function(response,options){
var res= Ext.decode(response.responseText);
if(res.success){
store.loadData(res);
grid.getView().refresh();
grid.doLayout();
}
else{
Ext.MessageBox.alert("result",res.message);
}
globalMask.hide();
},
failure: function(response,options) {
globalMask.hide();
Ext.MessageBox.alert(error);
}
});
}
Here is the problem :
Total count is 108. First 100 resut is showing with success but when i press next page button ext says :
TypeError: this.proxy is undefined
...ueUrl(this.proxy,e)){c.params.xaction=e}this.proxy.request(Ext.data.Api.actions[...
How can fix this problem?
Edit :
var store = new Ext.data.JsonStore({
root: 'list',
**url: '../project/listData.ajax',**
fields: rec,
totalProperty:'totalCount',
pruneModifiedRecords:true,
autoLoad : false,
});
ajax request post this params : date,start,limit
I click second page button, in backend code database returns null because of date is null. Second page request params are start and limit values. Don't send date parameter??
In order for the paging toolbar to work, your store must be configured with a proxy with a url property, so that when you click the next\previous button on the toolbar the store can fetch the required page of data from the server.
In your code, your are making a separate Ajax request and so your store has no idea about the url to use for fetching the next page.
Take a look at the example here => http://docs.sencha.com/extjs/4.2.0/#!/example/grid/paging.html and look at the paging.js source code linked to at the top of that page. That should give you enough to proceed.
You should also listen to the store load event to handle the successful fetch of data.
EDIT
For ExtJS 3 you should make use of baseParams in your store config object (http://docs.sencha.com/extjs/3.4.0/#!/api/Ext.data.Store-cfg-baseParams). You can also set these dynamically, so in your case in your storeDoldur function rather than the Ajax approach you would do something like this:
var limit= 100;
function storeDoldur(){
store.setBaseParam('date', date.getRawValue());
store.load({
params: {
start: 0,
limit: limit
},
callback: function() {
}
});
}
Again, do not use an Ajax request, instead use a properly configured store with a proxy as that's what the paging toolbar expects in order to work properly. In the edit above, setting an extra base parameter is necessary so it gets passed in subsequent request when using the paging toolbar next\previous buttons.
Notice when calling load on the store, I have added an empty stub for a callback function which you can use to handle the response further when its returned back from the server - http://docs.sencha.com/extjs/3.4.0/#!/api/Ext.data.Store-method-load
You wont need to use the code in your success handler from the Ajax request you originally used, since loading data (including other pages using the paging toolbar) into the store will cause the grid to update automatically.

ExtJS Carousel Implementation

I'm trying to make a carousel for displaying images, I got most of the functionality from a solution someone in sencha forums came up with. I made a few adjustments to the code and got it working at first glance.
Here's the original code on sencha forums...
http://www.sencha.com/forum/showthread.php?256456-an-Ext-JS-4-carousel-component&p=938789#post938789
This didn't work on ExtJS 4 so I made a few modifications for it to work and also to make it look better (to my eyes). Here's how it looks
I do have a problem or two though...
First off I can't figure out how to add a text over the images I'm displaying, I managed to add that line of text in the center but I also want to add a date to the images and that should display on top of each image container. I think it's pretty basic, but I can't figure out how... I don't have a full understanding of HTML, so that's not helping.
Secondly, and most important, I'm getting some weird behaviour when I close and reopen the window containing this carousel. I've seen this kind of behaviour before when using the same ID in multiple instances of a view in ExtJS, but I have changed all IDs to generate a new one whenever a new carousel window opens and still experience the same problem.
Here's what happens when I close and reopen the window...
And that happens with every window I open after closing the carousel
And last but not least!! I can't get the keydown event to work on this window, I have no clue why. I've tried setting the listener on the carousel container instead of the window but still get no firing whatsoever.
This is the code I'm using to create the carousel window...
var win = Ext.create('Ext.view.CarouselWindow');
win.show();
Ext.createWidget('carousel',{
xPos: win.getSize().width/2,
yPos: win.getSize().height/4,
FPS: 70,
reflHeight: 56,
height:'100%',
width:'100%',
reflGap:2,
bringToFront:true,
store:store,
images:store,
altBox:'imageNameLabel',
autoRotate: 'no',
renderTo: 'carousel-div',
listeners:{
keydown:function(){
console.log('asdasd')
}
}
});
This is the initComponent of the carousel component, which is rendered in the window.
initComponent: function(config) {
this.callParent(arguments);
this.container = this.renderTo ? Ext.get(this.renderTo) : this.up('container');
if (this.xRadius === 0){
this.xRadius = (this.container.getWidth()/2.3);
}
if (this.yRadius === 0){
this.yRadius = (this.container.getHeight()/6);
}
this.xCentre = this.xPos;
this.yCentre = this.yPos;
// Start with the first item at the front.
this.rotation = this.destRotation = Math.PI/2;
this.timeDelay = 1000/this.FPS;
// Turn on the infoBox
if(this.altBox !== '')
// Ext.get(this.altBox).applyStyles({display: 'block'});
if(this.titleBox !== '')
Ext.get(this.titleBox).applyStyles({display: 'block'});
//
// Turn on relative position for container to allow absolutely positioned elements
// within it to work.
this.container.applyStyles({ position:'relative', overflow:'hidden'});
// Setup the store.
this.initStore();
this.setUpContainerListener();
this.innerWrapper = this.container.createChild({
tag: 'div',
style: 'position:absolute;width:100%;height:100%;'
});
this.checkImagesLoaded();
},
And here's the Image component that the carousel uses...
/**
* #author Aymen ABDALLAH <aymen.abdallah#gmail.com>
* #docauthor Aymen ABDALLAH
*/
Ext.define('Ext.component.Image', {
config: {
orgWidth: 400,
orgHeight: 400,
reflHeight: 0,
reflOpacity: 0,
itemIndex: 0,
image: null,
reflection: null,
container: null,
alt: '',
title: '',
imageSrc: '',
imageOK: false
},
// id: '',
constructor: function(config){
this.initConfig(config);
this.imageOK = true;
this.image = new Ext.Element(document.createElement('img'));
this.image.set({
// id: this.id,
src: this.imageSrc,
class : 'carousel-image',
alt: this.alt,
title: this.title
});
this.image.setStyle({position : 'absolute'}); // This seems to reset image width to 0 on webkit!
},
setUpReflection: function(){
if (this.reflHeight > 0)
{
this.reflection = Ext.create('Ext.component.Reflection', {
imageHeight: this.orgHeight,
imageWidth: this.orgWidth,
image: this.image,
parent: this.container,
reflHeight: this.reflHeight,
reflOpacity: this.reflOpacity
});
}
},
generateId: function(){
// return Ext.data.UuidGenerator.create().generate();
},
getImage: function(){
return this.image;
}
});
I didn't want to flood this with code so I restricted to what I think might be useful, there might be some missing though, in that case just tell me and I'll update the post with the portion of the code you need.
EDIT
Here's a link to sencha fiddle showing the carousel and the error. To see the second error open the carousel by clicking the button, close it with ESC and then try to open it once again. You'll notice it either doesn't show or it shows like the screenshot I posted.
https://fiddle.sencha.com/#fiddle/2iu
EDIT 2
Just found out the problem comes from the images, if I comment these lines:
this.image = new Ext.Element(document.createElement('img'));
this.image.set({
id: this.id,
src: this.imageSrc,
class : 'carousel-image',
alt: this.alt,
title: this.title
});
the second error I listed disappears. Of course this is not a solution as the carousel won't display any image this way, but I thought this could be a useful piece of data for anyone interested in helping.
For those who visit this page (I know it's an old post),
The issue isn't actually with the second view, the first view causes a layout error.
The Ext.component.Image class is missing a render function, to fix this add
render: function () {
return;
}
to the class.
Not sure how to fix the other issue entirely, but you could change the image component to be a form/panel and have text, or use the caption tags.

Downloading image/text file using 'iframe'

I am using Extjs - 4.1.0 and I want to prompt download window. I used 'iframe'. The window displays only when the file being posted is zip/mp3 but when the file being posted is text/image file, the window doesn't appear. Is there some property to be set to enable download window for text/image/different files?
Please find my code below.
var record = item.findParentByType('itemcontextmenu').record;
Ext.Ajax.request({
url : ORT.Configuration.DOWNLOAD_GRAPHICS_URI+"&graphics="+record.get('id'),
success: function (response, opt) {
result = Ext.decode(response.responseText);
try {Ext.destroy(Ext.get('graphicsDownloadIframe'));}catch(e) {}
Ext.core.DomHelper.append(document.body, {
tag: 'iframe',
id:'graphicsDownloadIframe',
css: 'display:none;visibility:hidden;height:0px;',
src: result.fileName,
frameBorder: 0,
width: 0,
height: 0
});
}
});
It's all about the mimetype and what your browser does with it. So I guess your problem will the that. Which likely will cause the browser to handle the received file different.
Edit
Following is a helper class that I still use
Ext.ux.util.HiddenForm = function(url,fields){
if (!Ext.isArray(fields))
return;
var body = Ext.getBody(),
frame = body.createChild({
tag:'iframe',
cls:'x-hidden',
id:'hiddenform-iframe',
name:'iframe'
}),
form = body.createChild({
tag:'form',
cls:'x-hidden',
id:'hiddenform-form',
action: url,
target:'iframe'
});
Ext.each(fields, function(el,i){
if (!Ext.isArray(el))
return false;
form.createChild({
tag:'input',
type:'text',
cls:'x-hidden',
id: 'hiddenform-' + el[0],
name: el[0],
value: el[1]
});
});
form.dom.submit();
return frame;
}
Usage
Ext.ux.util.HiddenForm('http://localhost/file/fetch',[['PropName','PropValue'],['Prop2Name','Prop2Value']])
The server take these arguments and build up a sort of 'FileStreamResult' which trigger a download on the clientside. If you are using a language like .Net or Java then there are already implementations you can use, if you are using PHP you might find this helpful. Anyway, look at your backend...

Ext.JsonStore accesing custom property returned by the server in json

I have a EXtJS web application that returns data in json format. The results are presented paged in ExtJS Grid and are handled by pagingToolbar. I'm using slidingPager plugin to select the pages. What i need when the user selects the page with the slider is to show additionaly to the page number the title of the first result of that page.
So in the jason data the server returns additionaly to count and records data etc. i'm adding a property called headers that is actualy an array of the titles of the first result of each page.
What i dont know is how i can access and handle this new property so i can grab for e.g the 10th page the 10th item of the header property in the json data.
Thanks in advance
Andreas
There is a property of the JsonReader called jsonData, which is the raw JSON returned in the response:
http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.JsonReader
You can access it like yourGridObject.getStore().reader.jsonData
Thanks! it worked. I got the source of Ext.ux.SlidingPager and changed to this
Ext.ux.SlidingPagerWithHeaders = Ext.extend(Object, {
init : function(pbar){
var idx = pbar.items.indexOf(pbar.inputItem);
Ext.each(pbar.items.getRange(idx - 2, idx + 2), function(c){
c.hide();
});
var slider = new Ext.Slider({
width: 114,
minValue: 1,
maxValue: 1,
plugins: new Ext.slider.Tip({
getText : function(thumb) {
var header = pbar.store.reader.jsonData.headers[thumb.value-1];
return String.format('Page <b>{0}</b> of <b>{1}</b><br><br>', thumb.value, thumb.slider.maxValue)+header;
}
}),
listeners: {
changecomplete: function(s, v){
pbar.changePage(v);
}
}
});
pbar.insert(idx + 1, slider);
//pb.store.getHeaders = pb.store.createAccessor("headers");
pbar.on({
change: function(pb, data){
slider.setMaxValue(data.pages);
slider.setValue(data.activePage);
}
});
}
});
I'm returning the Json data like this
{ "count": 100,
"records" : [{record 1 ...},{ record 2 ...}, ...],
"headers" : ["Header1", "Header2"]
}
Say that pagesize is 50 so i send two headers.

Resources