PDA

View Full Version : Detailed view called from a list of items



Stephan Schrade
9 Jul 2010, 7:54 AM
Hi,
I have a list of items (like the list of recevied mails on my iPhone).
On click on the right arrow icon I want to show a detailed view of the item.
My idea was then to show a new card (within a card layout) with .setCard()
The list is currently generated via Jsonp request and a list template (config option tpl:)
This works very fine.

Any idea what to put into the tpl: configuration?
Or do I have to use a link?
And if yes, how can I then call the setCard() ?

TIA Stephan

Stephan Schrade
12 Jul 2010, 12:42 AM
No idea ?
I think this should be a common problem.
In many applications you have a list of items. And when you click on one them you get a detailed view of that item.

CU Stephan

robertj98
12 Jul 2010, 4:28 AM
Stephan,

This is exactly the kind of pattern that I would like to do - and it is very common when dealing with master-detail relationships and database driven apps. I think it would great to introduce this pattern as an example in the kitchen sink app or documentation so that we can see a recommended way of achieving this.

evant
12 Jul 2010, 7:46 AM
Here's a fairly trivial example, it's easy to do!



Ext.setup({
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'phone_startup.png',
icon: 'icon.png',
glossOnIcon: false,
onReady: function(){
Ext.regModel('Contact', {
fields: ['firstName', 'lastName']
});

var list = new Ext.List({
tpl: '<tpl for="."><div class="contact"><strong>{firstName}</strong> {lastName}</div></tpl>',
itemSelector: 'div.contact',

singleSelect: true,

store: new Ext.data.Store({
model: 'Contact',

getGroupString: function(record){
return record.get('firstName')[0];
},

data: [{
firstName: 'Tommy',
lastName: 'Maintz'
}, {
firstName: 'Ed',
lastName: 'Spencer'
}, {
firstName: 'Jamie',
lastName: 'Avins'
}, {
firstName: 'Aaron',
lastName: 'Conran'
}]
}),
listeners: {
itemtap: function(view, index, item, e){
var rec = view.store.getAt(index);
main.setCard(1);
detail.update({
firstName: rec.get('firstName'),
lastName: rec.get('lastName')
});
}
}
});

var detail = new Ext.Panel({
tpl: '<tpl for=".">First: {firstName}<br />Last: {lastName}</tpl>',
dockedItems: [{
dock: 'top',
xtype: 'toolbar',
items: [{
text: 'Back',
handler: function(){
main.setCard(0);
}
}]
}],
});

var main = new Ext.Container({
fullscreen: true,
layout: 'card',
items: [list, detail]
}).show();
}
});

Stephan Schrade
12 Jul 2010, 9:09 AM
Thanks very much.
I just "found" the event "itemtap" some hours ago :-)
But I don't have the items in a store.
Is it possible to get the data of the selected item via the parameter "item" of the event-function ?
If have an ID in the item that I could use to make another JSONP call to get the detailed data.

TIA Stephan

evant
12 Jul 2010, 9:12 AM
I'm not really sure what you're asking. How are you using a list if you don't have data in the store?

"item", in this case, is the selected dom node.

Stephan Schrade
12 Jul 2010, 9:20 AM
I used some parts from the twitter example.
Here you create a list with Ext.List with a template item:



var restaurantliste = new Ext.Component({
title: 'Rest',
cls: 'timeline',
tpl: [
'<tpl for=".">',
'<div class="restaurantliste_item">',
'<div class="kategorie">{ID} {Kategorie}</div>',
'<div class="inhalt">',
'<h2>{Bezeichnung}</h2>',
'<p>{PLZ} {Ort}</p>',
'</div>',
'<div class="entfernung">{Distanz} km</div>',
'</div>',
'</tpl>'
]
});

var ergebnispanel = new Ext.List({
id: 'ergebnisliste',
scroll: 'vertical',
singleSelect: true,
items: [restaurantliste]
}); // ergebnispanel

The list is populated within the callback function of the Ext.JSONP.request via:
restauranliste.update(data);

Stephan Schrade
12 Jul 2010, 1:17 PM
It would be really a good idea to have a working example for a JasonPReader populating a list (and then triggering a detailed view).
Unfortunately I can't find any example with a JsonPReader which is working together with a store.
And I can't use it the same way as I do with ExtJS. Some Methods and Config Options are not available.

TIA Stephan

evant
12 Jul 2010, 5:42 PM
Populating a list from a store works the same way, see:

http://www.sencha.com/forum/showthread.php?103921-Basic-list-display-problem&p=487452#post487452

Stephan Schrade
12 Jul 2010, 11:28 PM
Yes, but how can I set the callback parameter and additional parameters?
Unfortunately I couldn't find a load() method where I can set parameters and a callback function etc.

There is a read() method for ServerProxy but no parameters can be set here.

taylon
13 Jul 2010, 5:43 AM
Is there a big difference modifying this to the List example that's part of Kitchen Sink? I'm getting both the List and Detail appearing on the same card. It's kind of funny actually. The detail information is sitting directly below the list information. At least the detail changes based on the list item I'm picking, heh.

Stephan Schrade
13 Jul 2010, 11:11 AM
So, can we please please have an example with a list filled from a store where the data comes from a JSONP request with parameters. :-)
There are at least 5 threads dealing with the same problem now.

TIA Stephan

TommyMaintz
14 Jul 2010, 11:50 AM
Here is an example (taken from the twitter example) of a List, populated over JSONP (twitter), sending paramaters (query, limit etc), with a custom template.



Ext.setup({
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'phone_startup.png',
icon: 'icon.png',
glossOnIcon: false,
onReady: function() {
Ext.regModel('Tweet', {
fields: [
{name: 'id', type: 'int'},
{name: 'profile_image_url', type: 'string'},
{name: 'from_user', type: 'string'},
{name: 'text', type: 'string'}
]
});

var twitterStore = new Ext.data.Store({
model: 'Tweet',
proxy: {
type: 'scripttag',
url: 'http://search.twitter.com/search.json',
extraParams: {
q: 'sencha',
rpp: 50,
suppress_response_codes: true
},
reader: {
type: 'json',
root: 'results'
}
},
autoLoad: true
});

var timeline = new Ext.List({
fullscreen: true,
tpl: [
'<tpl for=".">',
'<div class="tweet">',
'<img src="{profile_image_url}" />',
'<div class="x-tweetanchor"></div>',
'<div class="tweet-bubble">',
'<div class="tweet-content">',
'<h2>{from_user}</h2>',
'<p>{text}</p><strong></strong>',
'<span class="posted">{created_at}</span>',
'</div>',
'</div>',
'</div>',
'</div>',
'</tpl>'
].join(''),

itemSelector: 'div.tweet',
emptyText : '<p style="padding: 10px">No tweets found matching that search</p>',

store: twitterStore
});
}
});

Stephan Schrade
14 Jul 2010, 11:54 AM
Hi,
many thanks but I found this already.
What I do need is the possibility to set the parameters at runtime because they come from a form panel.

TIA Stephan

TommyMaintz
14 Jul 2010, 12:10 PM
Alright, again this could be found in the twitter example.

I added a toolbar with a search field and button to the top of the list. Whenever you press the search button, we are getting the value form the search field and reload the store with the results for that search term.



Ext.setup({
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'phone_startup.png',
icon: 'icon.png',
glossOnIcon: false,
onReady: function() {
Ext.regModel('Tweet', {
fields: [
{name: 'id', type: 'int'},
{name: 'profile_image_url', type: 'string'},
{name: 'from_user', type: 'string'},
{name: 'text', type: 'string'}
]
});

var twitterStore = new Ext.data.Store({
model: 'Tweet',
proxy: {
type: 'scripttag',
url: 'http://search.twitter.com/search.json',
extraParams: {
q: 'sencha',
rpp: 50,
suppress_response_codes: true
},
reader: {
type: 'json',
root: 'results'
}
},
autoLoad: true
});

var searchField = new Ext.form.SearchField({
placeholder: 'Search',
flex: 1
});

var timeline = new Ext.List({
fullscreen: true,
dockedItems: {
xtype: 'toolbar',
dock: 'top',
items: [searchField, {
xtype: 'button',
ui: 'mask',
iconCls: 'search',
handler: function() {
var value = searchField.getValue();
if (value.length > 0) {
twitterStore.read({
params: {
q: value
}
});
}
}
}]
},
tpl: [
'<tpl for=".">',
'<div class="tweet">',
'<img src="{profile_image_url}" />',
'<div class="x-tweetanchor"></div>',
'<div class="tweet-bubble">',
'<div class="tweet-content">',
'<h2>{from_user}</h2>',
'<p>{text}</p><strong></strong>',
'<span class="posted">{created_at}</span>',
'</div>',
'</div>',
'</div>',
'</div>',
'</tpl>'
].join(''),

itemSelector: 'div.tweet',
emptyText : '<p style="padding: 10px">No tweets found matching that search</p>',

store: twitterStore
});
}
});

shellgrit
16 Jul 2010, 2:06 AM
Thanks for the example code Evan - I was struggling to get this to work on my own, but it works fine now with your help.

Would it be possible for the 'detail' panel to be a carousel? If so, can you give a simple example for this as well?

Is it possible for the number of cards in the carousel to be defined at run time?

My list consists of shorebird species (ie. thumbnail, name & size) and when a user taps on an item it brings up a full sized image and a description. What I would like to do is add photos on other cards in the carousel.

Neil

shellgrit
16 Jul 2010, 6:05 PM
Having trouble with the detail panel as a carousel - getting error 'p.contains is not a function'. Code for carousel follows - code for list omitted as it works fine.

The toolbar shows but not the carousel.


// First, define the illustration panel

var browseIllustration = new Ext.Panel({
tpl: [
'<tpl for=".">',
'<div class="browseDetail">',
'<p><strong>{speciesCommon}</strong></p>',
'<p>{speciesSize}cm - {speciesStatus}</p>',
'<img src="illustrations/{speciesImage}.jpg" /><br />',
'<p>{speciesDescription}</p>',
'</div>',
'</tpl>'
],
itemSelector: 'div.browseDetail',
scroll: 'vertical'
});

// Second, define the photo panel

var browsePhoto = new Ext.Panel({
tpl: [
'<tpl for=".">',
'<div class="browseDetail">',
'<p><strong>{speciesCommon}</strong></p>',
'<p>{speciesSize}cm - {speciesStatus}</p>',
'<img src="photos/doublebandedplover.jpg" /><br />',
'<p>In Flight (Alan Fletcher)</p>',
'</div>',
'</tpl>'
],
itemSelector: 'div.browseDetail',
scroll: 'vertical'
});

// Third, define the carousel

var browseCarousel = new Ext.Carousel({
ui: 'light',
defaults: {
cls: 'card'
},
items: [ browseIllustration, browsePhoto ]
});

// Fourth, a panel to hold the toolbat and the carousel

var browseDetail = new Ext.Panel({
items: [browseCarousel],
dockedItems: [{
xtype: 'toolbar',
dock: 'top',
ui: 'light',
items: [{
text: 'Back',
ui: 'back',
handler: function(){
main.setCard(0);
}
},{
text: '\/\\',
ui: 'action',
id: 'prevButton',
disabled: true
},{
text: '\\\/',
ui: 'action',
id: 'nextButton',
disabled: true
}]
}]
});

/***********************
* THE MAIN CONTAINER *
***********************/

var main = new Ext.Container({
fullscreen: true,
layout: 'card',
items: [ browseList, browseDetail ]
}).show();

}Any suggestions would be appreciated.

shellgrit
17 Jul 2010, 1:28 AM
I have progressed - the list shows fine and tapping an item in the list brings up a detailed view of a two card carousel, with a toolbar docked at the top (the 'back' button on the toolbar also works fine).

However the only way I can get anything to show on either card in the carousel is with the html config item - I just can't get a tpl config item to work (it does when I have a simple panel without the carousel).


Ext.setup({
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'phone_startup.png',
icon: 'icon.png',
glossOnIcon: false,
onReady: function(){

/***********************************************
* THE BROWSE LIST PANEL AND ASSOCIATED ITEMS *
***********************************************/

// First, define the buttons

var browseButtons = [{
xtype: 'splitbutton',
items: [{
text: 'Name',
handler: function(){
speciesList.sort('speciesCommon', 'ASC');
}
}, {
text: 'Size',
handler: function(){
speciesList.sort('speciesSize', 'ASC');
}
}]
}];

// Second, define the toolbar

var browseToolbar = new Ext.Toolbar({
xtype: 'toolbar',
dock: 'top',
ui: 'light',
items: browseButtons,
layout: {
pack: 'center'
}
});

// Third, define the list

var browseList = new Ext.List({
dockedItems: [ browseToolbar ],
tpl: [
'<tpl for=".">',
'<div class="browseList">',
'<img src="thumbnails/{speciesImage}.png" align="left" />',
'<p><strong>{speciesCommon}</strong></p>',
'<p>{speciesSize}cm - {speciesStatus}</p>',
'</div>',
'</tpl>'
],
itemSelector: 'div.browseList',
singleSelect: true,
store: speciesList,
listeners: {
itemtap: function(view, index, item, e){
var rec = view.store.getAt(index);
main.setCard(1);
browseCarousel.update({
speciesCommon: rec.get('speciesCommon'),
speciesImage: rec.get('speciesImage'),
speciesDescription: rec.get('speciesDescription'),
speciesStatus: rec.get('speciesStatus'),
speciesSize: rec.get('speciesSize')
});
}
}
});

// Fourth, sort the list alphabetically initially

speciesList.sort('speciesCommon', 'ASC');

/************************************************
* THE SPECIES DATA PANEL AND ASSOCIATED ITEMS *
***********************************************/

// First, define the carousel

var browseCarousel = new Ext.Carousel({
ui: 'light',
defaults: {
cls: 'card'
},
items: [{
title: 'illustration',
html: '<img src="illustrations/doublebandedplover.jpg" />'
},{
title: 'photo',
html: '<img src="photos/doublebandedplover.png" />'
}]
/* items: [{
tpl: [
'<tpl for=".">',
'<div class="browseDetail">',
'<p><strong>{speciesCommon}</strong></p>',
'<p>{speciesSize}cm - {speciesStatus}</p>',
'<img src="illustrations/{speciesImage}.jpg" /><br />',
'<p>{speciesDescription}</p>',
'</div>',
'</tpl>'
],
itemSelector: 'div.browseDetail'
// scroll: 'vertical'
},{
tpl: [
'<tpl for=".">',
'<div class="browseDetail">',
'<p><strong>{speciesCommon}</strong></p>',
'<p>{speciesSize}cm - {speciesStatus}</p>',
'<img src="photos/doublebandedplover.jpg" /><br />',
'<p>In Flight (Alan Fletcher)</p>',
'</div>',
'</tpl>'
],
itemSelector: 'div.browseDetail'
}] */
});

// Second, define a panel to hold the carousel and a toolbar

var browseDetail = new Ext.Panel({
layout: {
type: 'vbox',
align: 'stretch'
},
defaults: {
flex: 1
},
items: [browseCarousel],
dockedItems: [{
xtype: 'toolbar',
dock: 'top',
ui: 'light',
items: [{
text: 'Back',
ui: 'back',
handler: function(){
main.setCard(0);
}
},{
text: '\/\\',
ui: 'action',
id: 'prevButton',
disabled: true
},{
text: '\\\/',
ui: 'action',
id: 'nextButton',
disabled: true
}]
}]
});

/***********************
* THE MAIN CONTAINER *
***********************/

var main = new Ext.Container({
fullscreen: true,
layout: 'card',
items: [ browseList, browseDetail ]
}).show();

}

});Working version without the carousel is available at www.alphalink.com.au/~shelley/shorebirds/ (http://www.alphalink.com.au/%7Eshelley/shorebirds/)

Neil