How to export extjs grid data to excel? - extjs

I have a grid with large number of records. I use filters to filter the data as required. But i want to export the filtered data to a excel sheet for further usage.
I went through some articles available but they seem different and not compatible with latest 4.2 version.
Please help me in achieving this in simple manner.
Thanks much!

For extjs < 4
http://edspencer.net/2009/11/24/ext-ux-exporter-export-any-grid-to-excel-or-csv/
For extjs >= 4
http://www.sencha.com/forum/showthread.php?136598-Export-store-to-Excel

As far as I know this isn't possible without a Serverside implementation in a cross browser manner.
In theory you create a OpenXML document string by reading the current records from the store and encode it with base64. Then write this to a Data Uri. The first that didn't allow inline data other then images is IE so this won't work for all IE browser version due to limitations like size and images only. This will be the reason why there are no up to date implementations.

Successfully implemented this approach for Ext JS 4. To give it a flexibility of an abstract class, follow the instructions:
Take functions from here and extract them into a separate class
as global.
Replace all "this" function references to global function calls.
Add "grid" parameter to all functions starting with the entry one
(downloadExcelXml()).
Replace the remaining "this" calls to grid references (as functions were expected to act inside a grid).
Now add this button in your grid constructor and call
downloadExcelXml() as a handler like this:
exportButton = {
xtype: 'button',
text: 'xls',
listeners: {
click: function (button, event, eOpts) {
downloadExcelXml(
false,
"TableHeader",
eOpts.data.grid);
},
data: {
grid: this
}
};

Related

How to reuse store in EXT JS 4 MVC application without multiple reloading?

I am working on extjs 4 MVC application.
Application runs the Viewport, which contains tabpanel.
Each tab has own controller and multiple views.
See my sandboxs at http://wap7.ru/folio/ext-reuseable-store/TE.html
I have one Store used several times (e.g. one tab in topmenu combobox, another in the clietns grid.)
Store configured with autoload: true.
Proxy is configured in the Model.
My problem: Store is loaded multiple times - at every mention in the controller [stores] array.
If I remove one from the array [stores] controller- combobox will be empty, although it states store: Ext.getStore ('STORE-ID')
Please give me a hint, or an example of re-using Store (not Model) as in here http://docs.sencha.com/ext-js/4-0/#!/guide/mvc_pt2
You can just instantiate your store and load it, remove the autoload.
var store = Ext.create('App.store.YourStore').load();
Then pass that store to all your components, just like you would do when you want a paging bar connected to a grid.
This normally works fine to call your store from other controllers:
Ext.getStore('PlatformClient');
I've never tried to put the same store in more than one controller stores array. That seems strange to me.
There are a couple of other oddities about the code you have posted though, maybe they're just typos and maybe they don't make any difference to the framework but they're different from what I normally do so I'll point them out:
First, your model array in the "typical controller" contains a store:
models:[
'te.store.PlatformClient'
],
That one is probably just a typo.
Second, I don't put the full namespace in my store arrays, this is something that may not make a difference, but I don't know. Maybe ExtJS is prepending the namespace on top of the namespace you have written out so it thinks that you are instantiating a different store whenever it initializes a new controller - thereby causing it reload. For example this is more "normal" for whatever it's worth:
stores:[
'Taxonomy',
'PlatformClient',
'DataType'
],
controllers:[
'Taxonomies' ,
'DataType' ,
'DataSale' ,
'Clients'
],
Try setting it up like that and get rid of the duplicative stores in the other controller store arrays.
Also, I want to make sure that you caught the bit in the docs about not needing to define a storeId config for MVC stores. The framework will automatically give the store this:
storeId: [StoreClassName]
So in your example, you would get this automatically:
storeId: 'PlatformClient'
Someone else had trouble with MVC stores recently and it traced back to the framework being flabbergasted by the audacity of the dev supplying their own storeId config with the MVC pattern.
We used to have similar problems with loading. Also got issues with filtering in case of multiple use of the same store (you may want to set filter on one but not on the other). Therefore we load all the stores at application launch. Then whenever we need that store for displaying purposes then instead of using the original we are cloning it in the memory with ha utility function as below.
/**
* Use this for example if you want to apply a filter on a store
* but you dont want the original store to change, so:
* singleton store has no filter
* you clone it to be used with filters in some places.
*
* Note: this will have memory proxy, so no changes to the stores are persistent,
* changes will have no effect on the local/remote db.
*
*/
createStore: function(storeId, data) {
//
// Creates a new store from the given array of records without
// registering the new store.
// See cloneStore for more info
//
var modelName = storeId;
var prevStore = Ext.getStore(storeId);
data = data || prevStore.data.all;
var clonedStore = Ext.create('App.store.' + storeId, {
data: data,
model: 'App.model.' + modelName,
proxy: 'memory'
});
Ext.data.StoreManager.register( prevStore );
return clonedStore;
}
Please note the cloned copy is using memory proxy. Therefore write operations shouldn't be done on it. If you need to update the store then always use the original.
I hope this helps on some way.

Add a "permanent" filter to a store, until I manually call clearFilter

I'm using a store to fetch the specializations of all hikers (so hiker has many specializations). However, I have a detail window where this specializations are added/removed/shown ony for currently selected hiker (yea, it's a detail window).
My problem here is that my store fetch data for all hikers, but I want it to show, when detailed window is up, only data for given hiker. Notice also that I'm showing data in data-grid, so the user possibly can add filters and I noticed that if I add a filter with store.filter({...}) and user add a filter with data-grid, my filters are removed (so basically they are useless.
Which approach should I use? Do you have any suggestion? I were thinking about 1 store for each hiker, but I don't like this solution.
Edit 1:
I also noticed that I can't create a filter in the same way as data-grid builds them:
Ext.create('Ext.util.Filter', {
type: 'numeric',
comparison: 'eq',
field: 'hiker_id',
property: 'hiker_id',
value: me.hiker.get('id'),
root: 'data'
})
Which is boring, because I imnplemented on server side a functionality that parses the grid filters already.
We just give our filters in json format to the store's extra params. And parse that back-end. The extra params stay the same while paging or refreshing the grid.
grid.getStore().getProxy().extraParams = { filter: yourFilter };
-How- are your users doing the filter?
store.filter accepts both arrays and functions, so you can do quite a bit with it, without actually juggling the data on the server. (eg manage an array that is being passed to the filter, test against an object somewhere, or whatever)
Permanent filter? Not so much, but since you can add multiple filters etc, it is relatively trivial to keep track of what filters are in place.
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.Store-method-filter

ExtJS Ajax vs Extjs Store for single row from server

Scenario: I have a URL that returns details about the current logged in user. I.e.
one record
no list needed
Options I have:
Perform a manual ExtJS Ajax call each time, having to insert the code everywhere I need the callbacks etc.
Create an ExtJS Store once and fetch the first record from the store instance every time.
Question: Any better options? I'm using ExtJS 4.1.
You don't need to go into low level details to do something like that; use the standard tools. Define a Model, assign it a Proxy of the type you need, and load it. See the docs: http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.Model
Why are you doing an ajax call each time?
Do it once, and assign it as a global variable?
Ext.Ajax.request({
url: 'page.php',
params: {
id: 1
},
success: function(response){
var text = response.responseText;
window.user = Ext.JSON.decode(text);
my.custom.launchFunction();//does your viewport etc for you
}
});
Having done this, you can now, from anywhere do
console.log(user.Name);
Its neater, and faster, than doing a store lookup.
As a bonus, you user object can be much more complex than the store would handle without a ton of config.

Atk4 form Columns

I'm trying to use columns in a form.
I have the next code, that produces the
The code is this:
$col=$this->add('Columns');
$left=$col->add($f->addField('text','observaciones'));
$right=$col->add($f->addField('line','cantidad_de_bocas'));
the fields of the columns, are based on form fields. I whant to add more than one field to the columns (ex. 2 fields on left column and 4 fields on right columns).
I have seen some examples about this, like
$col=$page->add('Columns');
$left=$col->addColumn(2)->add('View_SlotMachine');
$right=$col->addColumn(2)->add('View_SlotMachine');
Why the fields are duplicated ?
What does the method addColumn(2) does ?
Very thanks
If you havent gone to far with development using atk 4.1, you could download 4.2 and look at the examples here. There is a lot of new functionality in 4.2 which you can take advantage of and the demos and examples are being updated to reflect these changes.
In 4.2, there is an example of styling with two columns like this
class StylingForm extends Form {
function init(){
parent::init();
$f=$this;
$f->addField('line','name')->validateNotNull()
->setFieldHint('Click "Register" to see error');
$f->addField('line','email')
->validateNotNull()
->validateField('filter_var($this->get(), FILTER_VALIDATE_EMAIL)')
.. .. ..
}
functoin init() {
// Stacked class puts labels on top of fields
$form=$page->add('StylingForm');
$form->addClass('stacked atk-row');
$form->template->trySet('fieldset','span6');
$sep=$form->addSeparator('span6');
$form->add('Order')->move($sep,'before','age')->now();
}
In atk4.1, the form is a view so it has a template in atk4/templates/shared/view/form.html and some code in atk4/lib/View/form.php
In the example of the slot machine that you mention from here the addColumns(2) is being used to set the width of the views to 20% of the available screen width but in the example, each column will contain a view of the slot machine. If you wanted to forms on the same page, you could use the same functionality, but what you appear to want is a single form across two columns with a single submit button.
If you have to continue to use atk4.1, you need to look at the form.html. Romans may be able to suggest how you could create a two column form in that version. I can see there are some classes defined in the css such as atk-form-vertical-2col and atk-form-vertical-3col and there is a function setFormClass to set them but i cant see what tags you would set to put fields into the right hand side - by default, everything goes to the left.

Can extjs Control/toggle groupField data?

here is the example edited by crop grid:
1st i view like a normal grid like this image
http://imageshack.us/f/836/groupcontrollingb4.png/
then i create a check box name as "Cuisine:American" and check it to reload become image like this
http://imageshack.us/f/803/gridcontrollingafter.png/
the group data "Cuisine:American" can be group it and expand
then other data still remain the normal grid view
Does any one know a example or possibility for controlling the groupView like in the example i've shown ?
Hope u all can understand my question
thankz.
It's harder than it should be, because ext is not calling Ext.util.Grouper.getGroupString method. I've managed to bypass this. Here is working sample: http://jsfiddle.net/bP7Y2/
I am basing on Grouped Grid Example from Ext JS site. I've created CuisineGrouper which is extending Ext.util.Grouper. There are 2 important methods: getGroupString which returns gruping string and sorterFn which sorts in that way that grupped elements are on the top. For example when there is grouping by 'Cuisine:American' getGroupString returns 'American' or '' depending on cuisine value.
Another important bit is overriden getGroupString method on Restaurants store, so now it calls Ext.util.Grouper.getGroupString.
Last thing I've modified is groupHeaderTpl of groupingFeature.
(Update) It's possible to hide Others grouping header with some hacks. Example: http://jsfiddle.net/bP7Y2/1/

Resources