Sencha grid aggregate store entries - extjs

Let's assume I have a store:
Buyer,Good,ItemCount,ItemPrice
{'Alice','Apple',5,$.25}
{'Bob','Pear',2,$.35}
{'Bob','Banana',5,$.25}
{'Bob','Pear',4,$.35}
{'Eve','Grapefruit',2,$.40}
And I have a grid in which to display this store's content, and at least a dozen functions scattered all over the place that change this store, changing filters, reloading data from the server, etc.
Is there a fast way to add another grid, which shows every good in a row and every buyer in a column, and how many items of that kind everyone bought in total? This grid should update whenever the original grid is updated.
The way I know, this would require another store, and then I would have to attach to the originalStore's datachanged and filterchanged event and populate the new store by hand every time? Or is there some other solution?
EDIT: I am now looking at pivot grid, as suggested by the first answer, and I have to expand my example a bit, as I stumbled upon a problem I didn't see before:
Buyer,Good,ItemCount,ItemPrice
{'Alice','Apple',5,$.25}
{'Bob','Pear',2,$.35}
{'Bob','Banana',5,$.25}
{'Bob','Pear',4,$.35}
{'Eve','Grapefruit',2,$.40}
{{'Alice','Bob'},'Candlelight Dinner Set',1,$45}
{'Eve',{'Ski mask','Baseball bat'},1,$65}
{'Francis',{'Ski mask','Ski poles'},1,$80}
Where I would want the dinner to show up at both Alice and Bob, and the products sold in a bundle to show up separately.

Try to use PivotGrid for your purpose:
var pivot = new Ext.grid.PivotGrid({
store: yourStore,
aggregator: 'sum',
measure: 'ItemCount',
leftAxis: [
{
dataIndex: 'Buyer'
}
],
topAxis: [
{
dataIndex: 'Good'
}
]
});
Official Pivot Grid Links:
Documentation (Sencha Docs 5.1)
Announcement (Sencha Blog)
Download (Free 30-Day Evaluation)

Related

Activating enterprise adds "breaking changes" on filter. How to avoid?

Normally in Development activating features should be "on demand" to avoid having to change undesired breaking changes.
This is different in ag-grid. When ONLY activating the license it adds features - which we don't want. We want to activate them explicitly. Now we basically have to change a lot of things.
The actual question at this moment
Without enterprise you have the simple filters, they look like this (we just changed a few styles)
Now when activating ONLY the license it suddenly changes to this (a top menu with 3 options of which the middle one is the filter which looks obviously odd because we didn't style it yet as we neither want nor need it):
Now not only a new menu appeared but also the SimpleFilter changed to unwanted Set filter. I overcame the Set Filter by explicitly recreating the SimpleFilter like this
{
filterOptions: [
SimpleFilter.CONTAINS,
SimpleFilter.NOT_CONTAINS,
SimpleFilter.EQUALS,
SimpleFilter.NOT_EQUAL,
SimpleFilter.STARTS_WITH,
SimpleFilter.ENDS_WITH,
SimpleFilter.BLANK,
SimpleFilter.NOT_BLANK,
],
defaultOption: SimpleFilter.CONTAINS,
}
We were confused that there isn't a ready-to-use flag/preset...
But furthermore we don't want that 3 option bar. We just want the old version of this menu! How can this be done?
In the column menu you can select which tabs to show using the column definition menuTabs property.
If you only want to show the filter tab in the column menu for the COUNTRY column, use this column definition code:
{ field: 'country', filter: 'agTextColumnFilter', menuTabs: ['filterMenuTab'], }

How to selectively populate a Store in Sencha Touch 2

I have the following store in my Sencha Touch 2.4.1 application:
Ext.define('NativeApp.store.Item', {
extend: 'Ext.data.Store',
config: {
model: 'NativeApp.model.Item',
storeId: 'item-store',
fields: ['id', 'description'],
proxy: {
type: 'ajax',
url: 'resources/json/item.json',
reader: {
type: 'json',
rootProperty: 'items'
}
},
autoLoad: true
}
});
It's being populated with everything in the JSON file, which let's say looks like this:
{
"items": [
{
"id": 's1',
'description': 'desc'
},
{
"id": 's2',
'description': 'desc'
}
]
}
Let's say that in my view I have two buttons, "s1" and "s2".
If I click on "s1", I am taken to a page with a list that contains the data with id "s1". (In this case, there is only one, but there could be more).
How would this be accomplished?
Idea 1:
The autoload attribute can be set to an Object. From here - "If the value of autoLoad is an Object, this Object will be passed to the store's load() method."
So if in my controller, in the handler that's executed when the button is tapped, I can generate this object (parse the JSON file) and somehow pass it to the store - mission accomplished. Sort of.
Besides the question of how to pass it to the store, the immediate problem is when is the data loaded into the store?
According to the docs, "this store's load method is automatically called after creation". Is creation when the app launches, or when I create the view object that uses the store:
var view = {xtype: 'myview'};
Idea 2:
Maybe I could dynamically switch out the url from the proxy and have separate JSON files for each id (there won't be too many). But that seems unlikely to work.
Idea 3:
Pass in a data object to the store (again parsing the JSON) from that controller.
Are any of these feasible? And if not, what is an alternative solution?Perhaps I'm overthinking this.
Edit:
I have a list of items, and each item has a list of sub-items. So when I select one item, I want to be taken to page of the sub-items. Right now, all of these sub-items are in one JSON file, so after clicking on one item, I need a way of telling the store to load only part of the json data.
Is Ext.data.model.load still the best approach?
Idea 1:
Yes, you could do that... probably more trouble than it's worth IMO. The store will load immediately after it is created -- so if you create the store at application start, then it loads then. If you create a store randomly during runtime, it loads then. If the store is defined inline for a view, it's loaded when the view is created.
Idea 2:
Arguably a better solution, but still a lot of trouble to swap the URL for the proxy, then forcibly load it, parse the data, etc.
Depending on your view, you could just directly load the data for a single model using NativeApp.model.Item.load(id) (see docs). This assumes you have an API setup for that, but it's easier IMO and certainly more RESTful.
Idea 3:
Meh. It really sounds to me like Ext.data.Store is the wrong construct for what you're trying to accomplish.
Are any of your ideas feasible? Yes.
Are you over-thinking this? Slightly, but then again you wouldn't be a programmer if you didn't.
It's hard to tell you exactly what I'd do without seeing the rest of your application and understanding the WHY you're doing X, Y, or Z... but if you're only planning on displaying a single model's data on a given "Detail" screen (and you need that data loaded on-demand), then the static Ext.data.Model.load() method is probably what you need.

How to export extjs grid data to excel?

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
}
};

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: Month/Day Selector (ie. no year)

I am currently using a EXTJS EditorGridPanel in my application, and for one of the column inputs I require the user to be able to pick a month and day (no year).
I am currently using a DateField to do this, but I need to be able to disable the "year" aspect of it in the UI. I do not care if the "value" in the end has a year associated with it, I can simply disregard it. I have searched to see if anyone has done such a thing, but my only findings are people that way to show only Month/Year.
My other option is to create my own custom input (with comboboxes for month and day, where the day combo changes based on the month), however, I honestly don't have all that much time to make one myself as I would have to go through the learning curve since I have never created a custom input extension before.
--> So my big question then is, has anyone heard of an existing EXTJS month/day picker?
Any help would be much appropriated stack overflow peoples!
Although I would probably create my own custom component to use as the editor, if you're not comfortable doing that, have you considered breaking the Month and Day fields into separate columns in your grid column model?
Another option would be to add a input mask to the textfield (you'll need to specify one as a customEditor in your cm). I believe this is done via custom vtypes. This input mask would force the user to enter the date in the format that you specify.
Using this approach would :
keep all month/day data in one column
simplifies your UI code by using the out-of-the-box components. (IMO this is key for learning ExtJS)
try this one
picker: {
slotOrder: [ 'month', 'day' ]
}
Your post appears to contain code that is not properly formatted as code. Please indent all code by 4 spaces using the code toolbar button or the CTRL+K keyboard shortcut. For more editing help, click the [?] toolbar icon.
Try something like:
{
xtype: 'datepickerfield',
name: 'OrderDate',
label: 'Order Date',
picker: { yearTo: 2011, yearFrom: 2020 }
}
I hope this will help you.

Resources