Ext.ux.ListPaging, Sencha Touch paging of Dataview Lists

Paging of grids in Ext JS is a complete different business than paging of lists in Sencha Touch. We can’t send a large number of records with server requests because we must assume that the user has possibly an expensive (mobile) data contract with his provider. So we have to manage efficiently what we send and how much we send. And only then when server communication is unavoidable.

In this article I will show a sample with the Ext.ux.ListPaging plugin that can be included in the Ext.dataview.List class. We are not going to do anything fancy. A working model that can be a stepping stone for your own demand. To make this sample work no extras are done with styling or extra visuals.

What we require

A model (Ext.data.Model)

A store (Ext.data.Store)

A list (Ext.dataview.List, with disclosure)

Our list pagesize is 3 records in a table of a total of 8 records. That is very small for practice but for this sample it makes a few things easier to show. But I suggest that you don’t use pages that load too many records at once either. The standard pagesize of a store is 25 records.

A simple search with a list

We start with an empty panel consisting of a search component and a List component. Initially no records are loaded. In Ext JS you might start with a loaded grid before the user searches anything. But in Touch I don’t load anything before user action (cheaper).

Initial view

Initial display, no records are shown (the Status button has nothing to do with our sample)

First records loaded

When “01” is entered it will show 3 records matching the search criteria.

As you can see the plugin is now adding the “Weitere Sätze” (more records) to the list. The plugin has a config setting autoPaging that is set to true. Now a swipe up will automatically load more records to the model.

You can also tap on “Weitere Sätze” and it will also load the additional records.

Browsing with swipe

After a swipe (upwards) the server call adds one more record and adds it to the records in the store. The paging plugin adds now the text “Keine weitere Sätze” (no more records).

No records found

When something is entered in the search field that would not lead to any results, the plugin’s output is not displayed and the List object will show the text that is entered at the config item: emptyText. We will hide the plugins output in the callback routine of the store.load method.

The structure of the List

The following code shows the structure of the Ext.dataview.List extension making class Mobile.view.dataview.Artikel. This file would be Artikel.js in the folder Apps/Mobile/view/dataview/.

Change the names to names that correspond with your own application. Replace the comment with your own actual data. As you can see I am using still a bit of Ext JS alike coding. I am still not so used to the config descriptions in Sencha Touch classes.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

Ext.define('Mobile.view.dataview.Artikel',{

extend:'Ext.dataview.List',

alias:'widget.ArtikelDataView',

alternateClassName:['ArtikelDataView'],

config:{

onItemDisclosure:true,//showthebuttonatendofrecord

emptyText:'Keine Daten gefunden',//shownwhennothingfound

plugins:[

{

xclass:'Ext.plugin.ListPaging',//partofSenchaTouch

autoPaging:true,//pageonswipedown

loadMoreText:'Weitere Sätze',//texttoshowwhenmorerecords

noMoreRecordsText:'Keine weitere Sätze'//textwhenallhasshown

}

],

itemTpl:[

'Artikel: {ar_artikel_nr} &lt;br /&gt;',

'&lt;span class="smaller"&gt;{bezeichnung}&lt;/span&gt;'

],

items:[

{

xtype:'toolbar',

docked:'top',

items:[

{

xtype:'searchfield',

placeHolder:'Suchen',

width:300,

listeners:{

action:function(searchfield,e){

varme=searchfield.up('ArtikelDataView');

me.SearchfieldClicked(searchfield,e);

}

}

},

...Statusbutton,notimportantforsample...

]

}

],

listeners:{

disclose:function(list,record){

/*...hereyouaddsomeactionwhenthedisclosebutton

ofarecordistapped(bluearrow)...*/

Ext.Msg.alert(

'Article Tap',

'You tapped on '+record.get('ar_artikel_nr')

);

}

}

},

/*

Atinitializationthestoreiscreated.

Thisisnotverycommon,itispreferabletouseseparateclasses

formodelandstore.

Stillthisisgoodplacetohaveextraworkdone.

*/

initialize:function(){

varme=this;

me.callParent();

/*definethemodel*/

Ext.define('ArtikelAuswahl',{

extend:'Ext.data.Model',

config:{

fields:[

...herethefieldsconfighastobeput,

fieldsmustcorrespondwithyourtemplatefields...

]

}

});

/*createthedatastore*/

varstore=Ext.create('Ext.data.Store',{

model:'ArtikelAuswahl',

pageSize:3,/*changethisvaluebasedongoodpractice*/

proxy:{

type:'ajax',

actionMethods:{

read:'POST'

},

url:..yoururltotheserver..,

reader:{

rootProperty:'records',

totalProperty:'total',

type:'json'

},

extraParams:{

..putheresomeadditionalparametervalues

thatyouliketosendtotheserver..

}

},

autoLoad:false/*noautomaticloading*/

});

/*bindthestoretothedataview*/

me.setStore(store);

},

/*Routineforthesearch*/

SearchfieldClicked:function(searchfield,e){

varme=this;

if(searchfield.getValue()==='')

returnfalse;

varstore=me.getStore();

/*

LikeExtJSstores_extraParamscanbeusedtofixatecallparameters

toastore.Itworkslikestickyvaluestoastoresproxy.

paramswillonlykeepthevaluesforthisonecall.

*/

store.getProxy()._extraParams.search=searchfield.getValue();

store.getProxy()._extraParams.someparameter='Some Value';

store.getProxy()._extraParams.anotherparameter=141063;

store.load({

scope:me,

params:{

start:0,

limit:3/*changethisvaluebasedongoodpractice*/

},

callback:function(records,model,success){

/*

thecallbackisexecutedafterstoreisloaded

Weneedtogetridofthemessage

thatisgeneratedbythepagingplugin

OnlytheList"No records found"messagehastobeshown

*/

varme=this;

if(records.length===0){

/*getthepagingplugin,thereisonlyone,so[0]*/

varpaging=me.getPlugins()[0];

/*

usethemethodalsousedintheplugin

(seepagingpluginsourceintheAPIdocumentation)

*/

paging._loadMoreCmp.hide();

}

}

});

}

});

Related posts:

Dedicated to professional software development since 1985. Has worked since 1992 as IT manager in several international operating companies. Since 2007 CEO and Sencha Ext JS web application developer at Enovision GmbH.