Grouped NestedLists? - sencha-touch

How can I create a grouped Nested List in ST2 like I would in Xcode with Storyboards? I only need groups at the root level. Here's some idea of what it looks like in a native app.
I didn't see anything in Sencha's NestedList documentation.

In ST2, the NestedList method getSubList() is now getList(), and it works a bit differently. Overriding it to propagate the grouping info worked for me:
/**
* Override Ext.dataview.NestedList.getList to propagate grouping info from
* parent NestedList to List sublist.
*/
getList: function(node) {
var list = this.callParent(arguments);
list.grouped = this.grouped;
list.store.setGrouper(this.getStore().config.grouper);
return list;
}

Already asked here on Sencha Touch forum.
http://www.sencha.com/forum/showthread.php?122238-Grouped-Nested-List.

You can look at the KitchenSink example (User Interface -> List -> Grouped)
http://docs.sencha.com/touch/2-0/#!/example/kitchen-sink
It's a simple list, just with a storers/grouper attribute in the store :
Ext.create('Ext.data.Store', {
id: 'ListStore',
model: 'Contact',
sorters: 'firstName',
grouper: function(record) {
return record.get('firstName')[0];
},
data: [...
And you call it in your list item settings :
items: [{
width: Ext.os.deviceType == 'Phone' ? null : 300,
height: Ext.os.deviceType == 'Phone' ? null : 500,
xtype: 'list',
store: 'ListStore',
itemTpl: '<div class="contact"><strong>{firstName}</strong> {lastName}</div>',
grouped: true,
indexBar: true
}]
Hope it'll help :)

Create a simple grouped list and set a "tap" event for the group headers. On tapping the header, open another panel and show the list with items from only that group.

Related

Creating a StoryMap app using the rallycardboard

I'd like to put together a StoryMap app using Initiative (second level) portfolio items as the backbone (columns). To do this the app needs to query for all the second level portfolio items, and then use each PI as a column header in the rallycardboard.
I've gotten the cardboard to display the column headers correctly, but I have not been able to get it to display the cards, which should be the first level of portfolio items (PortfolioItem/Feature).
Here is my code so far:
launch: function() {
this._getInitiativeStore();
},
_getInitiativeStore: function() {
this.initiativeStore = Ext.create('Rally.data.wsapi.Store', {
model: 'PortfolioItem/Initiative',
fetch: ['Name', 'Children'],
autoLoad: true,
listeners: {
load: this._createCardBoard,
scope: this
}
});
},
_createCardBoard: function(store, records) {
var initiativeColumns = [];
Ext.each(records, function(record) {
initiativeColumns.push({
xtype: 'rallycardboardcolumn',
columnHeaderConfig: {
xtype: 'rallycardboardcolumnheader',
fieldToDisplay: 'Name',
record: record,
},
cardConfig: {
xtype: 'rallycard',
record: 'PortfolioItem/Feature'
},
fields: ['Name', 'Parent'],
valueField: 'Parent',
value: record.get('_ref') // BUG FIXED HERE. Was: record.get('Parent')
});
}, this);
var cardBoardConfig = {
xtype: 'rallycardboard',
types: ['PortfolioItem/Feature'],
columns: initiativeColumns,
attribute: 'Parent',
};
var cardBoard = this.add(cardBoardConfig);
console.log('cardboard', cardBoard);
}
I realize I am using this perhaps a bit differently than the authors have planned for, but I'm willing to extend the rallycardboard and rallycolumnheader objects with Ext.define if that's what it takes. I'm starting to look at the Rally source code but its slow going so far.
I was able to figure out the problem by using Ext.define() to override the cardboardcolumn getStoreFilter function to print out its filter value. Probably for somebody good with a browser debugger that would not have been necessary, but I'm not and it pinpointed the problem right away: The "value" field of the initiativeColumn configs should have been record.get('_ref'), not record.get('Parent'). I'll edit the code above so it works.
Now the basic board works great as a story map with portfolio items! Next step is to see if I can incorporate the concept of releases into the map.
Also, I think I found a bug in the 'rallycardboard' constructor-- if I pass it a context reference like: context: { project: 'project/XXX'} where XXX is an OID, it crashes. Instead I need to instantiate a context object and pass that. But that's inconsistent from other items like the wsapi store. Workaround is easy, but it is a bit annoying.

Custom xtypes as a cell in ext.listview

I am using sencha touch 2 and not getting help inside sencha forum, so I hope you guys can help me.
I want to create a list with custom items. In this custom item i want to have a horizontal scrollable listview with buttons as items.
I tried to do it component.DataItem but it does no work for me.
I tried also to add an custom xtype als an item in a list, but this does not work.
I think this is a simple task but sencha touch makes it a challenge for me.
So please help me and show me, how can I get a view like shown in this picture.
Instead of a standard list you are going to want to use Component DataView. Essentially, you are going to need to first define an Ext.dataview.component.DataItem, which is then implemented into the DataView. Below is a simple example of a buttons in a DataView as referenced from the DataView guide: http://docs.sencha.com/touch/2-0/#!/guide/dataview
First create the DataItem:
Ext.define('MyApp.view.DataItemButton', {
extend: 'Ext.dataview.component.DataItem',
requires: ['Ext.Button'],
xtype: 'dataitembutton',
config: {
nameButton: true,
dataMap: {
getNameButton: {
setText: 'name'
}
}
},
applyNameButton: function(config) {
return Ext.factory(config, Ext.Button, this.getNameButton());
},
updateNameButton: function(newNameButton, oldNameButton) {
if (oldNameButton) {
this.remove(oldNameButton);
}
if (newNameButton) {
this.add(newNameButton);
}
}
});
We must extend Ext.dataview.component.DataItem for each item. This is an abstract class which handles the record handling for each item.
Below the extend we require Ext.Button. This is simply because we are going to insert a button inside our item component.
We then specify the xtype for this item component.
Inside our config block we define nameButton. This is a custom configuration we add to this component which will be transformed into a button by the class system. We set it to true by default, but this could also be a configuration block. This configuration will automatically generate getters and setters for our nameButton.
Next we define the dataMap. The dataMap is a map between the data of a record and this view. The getNameButton is the getter for the instance you want to update; so in this case we want to get the nameButton configuration of this component. Then inside that block we give it the setter for that instance; in this case being setText and give it the field of the record we are passing. So, once this item component gets a record it will get the nameButton and then call setText with the name value of the record.
Then we define the apply method for our nameButton. The apply method uses Ext.factory to transform the configuration passed into an instance of Ext.Button. That instance is then returned, which will then cause updateNameButton to be called. The updateNameButton method simply removes the old nameButton instance if it exists, and adds the new nameButton instance if it exists.
Now create the DataView:
Ext.create('Ext.DataView', {
fullscreen: true,
store: {
fields: ['name', 'age'],
data: [
{name: 'Jamie Avins', age: 100},
{name: 'Rob Dougan', age: 21},
{name: 'Tommy Maintz', age: 24},
{name: 'Jacky Nguyen', age: 24},
{name: 'Ed Spencer', age: 26}
]
},
useComponents: true,
defaultType: 'dataitembutton'
});
In your case, rather than using a button for the DataItem, you'll want to use a horizontal scrolling list. Here is an example that I found from this answer: Horizontal scrolling list
var list = Ext.create('Ext.DataView',{
store: store,
itemTpl: new Ext.XTemplate('<img src="{icon}" />'),
inline: { wrap: false },
scrollable: {
direction: 'horizontal',
directionLock: true
}
});
Note that you will probably have to use components in the second dataview as well in order to achieve your buttons with image

Search Option in Textbox

I am using ExtJs4.I have a form in my web application in which there is text box.The scenario is to provide an AJAX like search(like Google) when any key is pressed in the text box.Search will look into a web service and display the result(JSON object) in drop drown.Similar to Google search.
Is there any idea,link or tutorial for doing this?
Thanks
You could use ComboBox for this. With trigger or without one (that looks like a TextBox).
Sencha provides good examples:
http://docs.sencha.com/ext-js/4-0/#!/example/form/combos.html
http://docs.sencha.com/ext-js/4-0/#!/example/form/forum-search.html
This is a simple example:
{
xtype: 'combo',
id: 'myCombo',
store: Ext.create('Ext.data.ArrayStore', {
model: Ext.define('ComboModel', {
extend: 'Ext.data.Model',
fields: ['id','data1','data2']
}),
proxy: {
type: 'ajax',
url : 'data.json',
reader: {
type: 'array'
}
}
}),
triggerAction: 'query',
minChars: 2,
fieldLabel: 'Search',
displayField: 'data1',
msgTarget: 'side',
triggerCls : 'x-form-search-trigger', // Search Icon For Instance
listConfig: {
getInnerTpl: function() {
return '<div>{data1}</div><div>{data2}</div>';
}
}
}
And JSON file:
[
['1','data1-1','data2-1'],
['2','data1-2','data2-2'],
['3','data1-3','data2-3'],
['4','data1-4','data2-4'],
['5','data1-5','data2-5']
]
Try this example: http://docs.sencha.com/ext-js/4-0/#!/example/form/forum-search.html
I think this example http://docs.sencha.com/ext-js/4-1/#!/example/form/forum-search.html will be interesting for you. This realization use standard combobox control. In your case you need to set minChars property = 1, in this case store binded to Combobox will generate standard READ query with filter param to server. You can generate results there.

Extjs4 - Reloading store inside itemselector

I have an itemselecor inside a grid, and i have an combobox that should reload only the store inside the itemselector( the value fields should remain intact)
Here is the itemselector
var grid = Ext.widget('form', {
id: 'grid',
title: '',
width: 600,
bodyPadding: 10,
renderTo: 'itemselectorproduto',
items: [{
xtype: 'itemselector',
name: 'itemselector',
id: 'itemsel',
anchor: '100%',
imagePath: '/ux/images/',
store: store,
displayField: 'Nome',
valueField: 'ID',
value: vitrine,
allowBlank: true,
msgTarget: 'side'
}]
});
I tried to call the normal store.load(), but it have no effect and it shows no error on the console
If needed i will post more of the code, but i think just this should be enough
Thanks,
Looking through the code if ItemSelector it doesn't look like it supports any changes in the store once it's been binded. It basically creates local copies of the data. And if you call bindStore method to assign different store - it will erase your selection.
You can always improve code in ItemSelector to allow such behavior. It should not be a problem. You can subscribe to datachanged or load event of the store when binding to it, and then handle situation when store data is changed.
Actually i think the best way to do such thing is using ItemSelector`s "populateFromStore". Sure except of extending item selector. In case of extending you should look on the "onBindStore" function of the ItemSelector.
onBindStore: function(store, initial) {
var me = this;
if (me.fromField) {
me.fromField.store.removeAll()
me.toField.store.removeAll();
// Add everything to the from field as soon as the Store is loaded
if (store.getCount()) {
me.populateFromStore(store);
} else {
me.store.on('load', me.populateFromStore, me);
}
}
}
So as you see in case of the empty store it hooks to the load event. And it should be like this:
onBindStore: function(store, initial) {
var me = this;
if (me.fromField) {
me.fromField.store.removeAll()
me.toField.store.removeAll();
me.store.on('load', me.populateFromStore, me);
// Add everything to the from field as soon as the Store is loaded
if (store.getCount()) {
me.populateFromStore(store);
}
}
}

sencha touch - nestedlist - store all the fields' values of "activeItem of nestedlist"

i have a panel which should show the "description" field of "currently activeitem of nestedlist". nestedlist uses the model having fields:
id
text
description
when user taps on any item of nestedList [on selectionchange OR itemtap&backtap], i want to change description in the panel with description of "currently activeItem of nestedList".
Is this possible?
thanks for any help/solution/pointer.
The same problem I had today, and no solution had been found with a nested list, because no single field can be taken from a Ext.data.TreeStore. One solution could be that you have lots of "if-function 'do with all the ID's and then you give each ID a text. But that's not good.
I've decided to make a simple list.
if you want I can show you my solution for the simple list
ps.: I use Sencha Touch 1.1
Update:
NotesApp.views.NaviList = new Ext.List({
fullscreen: true,
flex: 1,
layout: 'card',
scroll: false,
useToolbar: false,
itemTpl: '{text}',
store: store,
listeners: {
itemtap: function (obj, idx, el, e) {
var record = this.store.getAt(idx);
var tle = record.get('text');
index = record.get('index');
NotesApp.views.notesListContainer.setActiveItem(index, { type: 'slide', direction: 'left' });
}
}
}
});
description:
My App has the name: "NotesApp".
"notesListContainer" is a Container where all my List are displayed. "index" is an ID that I get from the store and the calls list.
Now when you tap on my NaviList you set a new ActiveItem in this Container.
thanks a lot for the reply. I also tried using simple list with one Ext.button(back button in case of nestedlist). On itemtap and buttonclink, i change list's content by
var t = new Ext.data.Store and list.setStore(t).
Please let me know if there is any other better option to do it.