Sencha Touch’s NestedList
component is very handy when it comes to show hierarchical data with some relation. We usually use NestedList
when we have data in a child-parent relationship as a tree, where you have a node and many leafs associate to that node. Each leaf itself is a node which has many leafs associate to it.
I am using my previous Movie classes and categories them as MovieGenre
. Based on each genre, user will select one and it will show the entire movie list associate to that Genre. User can tap to any movie list item and it will be shown with Movie Details, which is a last leaf in the hierarchy.
First step is to create a Movie java class which is not more then a POJO.
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
|
package org.techzoo.touch.vo;
public class Movie {
private int id;
private String title, director;
private int yearOfRelease;
private MovieGenre genre;
public enum MovieGenre {
Action, Comedy, Family, Horror, War;
}
public Movie(){}
public Movie(int id, String title, String director,
int yearOfRelease, MovieGenre genre)
{
super();
this.id = id;
this.title = title;
this.director = director;
this.yearOfRelease = yearOfRelease;
this.genre = genre;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDirector() {
return director;
}
public void setDirector(String director) {
this.director = director;
}
public int getYearOfRelease() {
return yearOfRelease;
}
public void setYearOfRelease(int yearOfRelease) {
this.yearOfRelease = yearOfRelease;
}
public MovieGenre getGenre() {
return genre;
}
public void setGenre(MovieGenre genre) {
this.genre = genre;
}
@Override
public String toString() {
return String.format(
“Movie [title = %s, director = %s, genre = %s]”,
this.title, this.director, this.genre.name());
}
}
|
Next is a MovieDatabase java class which we used to hold few Movie objects.
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
|
package org.techzoo.touch.vo;
import static org.techzoo.touch.vo.Movie.MovieGenre.Action;
import static org.techzoo.touch.vo.Movie.MovieGenre.Comedy;
import static org.techzoo.touch.vo.Movie.MovieGenre.Family;
import static org.techzoo.touch.vo.Movie.MovieGenre.Horror;
import static org.techzoo.touch.vo.Movie.MovieGenre.War;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.techzoo.touch.vo.Movie.MovieGenre;
final public class MoviesDatabase {
private static List<Movie> movies = null;
private static MoviesDatabase _instance = null;
private MoviesDatabase()
{
if(null == movies){
initializeMovies();
}
}
public static MoviesDatabase getInstance()
{
if(null == _instance){
_instance = new MoviesDatabase();
}
return _instance;
}
public List<Movie> getMovies()
{
return movies;
}
public List<Movie> getMoviesByPage(int start, int limit)
{
return movies.subList(start, start+limit);
}
private void initializeMovies()
{
movies = new ArrayList<Movie>();
/** Action **/
movies.add(new Movie(1001, “Ek Tha Tiger”, “Kabir Khan”, 2012, Action));
movies.add(new Movie(1002, “Khiladi”, “Abbas Mastan”, 1992, Action));
movies.add(new Movie(1003, “Kick”, “Sajid Nadiadwala”, 2014, Action));
movies.add(new Movie(1004, “Rowdy Rathore”, “Prabhudheva”, 2012, Action));
/** Horror **/
movies.add(new Movie(1005, “Bhoot”, “Ram Gopal Varma”, 2003, Horror));
movies.add(new Movie(1006, “Raat”, “Ram Gopal Varma”, 1992, Horror));
movies.add(new Movie(1007, “Aatma”, “Deepak Ramsay”, 2013, Horror));
movies.add(new Movie(1008, “Mahal”, “Kamal Amrohi”, 1949, Horror));
/** Comedy **/
movies.add(new Movie(1009, “Gol Maal”, “Hrishikesh Mukherjee”, 1979, Comedy));
movies.add(new Movie(1010, “Jaane bhi do Yaaro”, “Kundan Shah”, 1983, Comedy));
movies.add(new Movie(1011, “Andaz apna apna”, “Rajkumar Santoshi”, 1994, Comedy));
movies.add(new Movie(1012, “3 Idiots”, “Rajkumar Hirani”, 2009, Comedy));
/** Family **/
movies.add(new Movie(1013, “Chakde India”, “Shimit Amin”, 2007, Family));
movies.add(new Movie(1014, “Khichdi”, “Aatish Kapadia”, 2010, Family));
movies.add(new Movie(1015, “Vivah”, “Sooraj Barjatya”, 2006, Family));
movies.add(new Movie(1016, “Beta”, “Indra Kumar”, 1992, Family));
/** War **/
movies.add(new Movie(1017, “Border”, “JP Datta”, 1997, War));
movies.add(new Movie(1018, “LOC Kargil”, “JP Datta”, 2003, War));
movies.add(new Movie(1019, “Lakshya”, “Farhan Akhtar”, 2004, War));
movies.add(new Movie(1020, “Tango Cahrlie”, “Mani Shankar”, 2005, War));
}
}
|
And now most important class is ItemVO
. This class is used to create a hierarchy between movie objects.
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
|
package org.techzoo.touch.vo;
import java.util.List;
public final class ItemVO {
private String text;
private Object items;
private boolean leaf;
public ItemVO() {}
public ItemVO(String text, Object items, boolean leaf) {
this.items = items;
this.text = text;
this.leaf = leaf;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Object getItems() {
return items;
}
public void setItems(List<ItemVO> items) {
this.items = items;
}
public boolean isLeaf() {
return leaf;
}
public void setLeaf(boolean leaf) {
this.leaf = leaf;
}
}
|
Create a MovieService
class which helps in showing Movie objects in hierarchy.
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
|
package org.techzoo.touch.service;
import java.util.LinkedList;
import java.util.List;
import org.techzoo.touch.vo.ItemVO;
import org.techzoo.touch.vo.Movie;
import org.techzoo.touch.vo.MoviesDatabase;
import org.techzoo.touch.vo.Movie.MovieGenre;
public final class MovieService {
private MovieService() {}
private static MoviesDatabase mdb = MoviesDatabase.getInstance();
public static List<ItemVO> getMoviesByGenre(MovieGenre genre)
{
List<ItemVO> items = new LinkedList<ItemVO>();
for (Movie movie : mdb.getMovies())
{
if(movie.getGenre().equals(genre))
{
ItemVO item = new ItemVO(movie.getTitle(), movie, true);
items.add(item);
}
}
return items;
}
public static List<ItemVO> getAllMovies()
{
List<ItemVO> items = new LinkedList<ItemVO>();
for(MovieGenre genre : MovieGenre.values())
{
ItemVO item = new ItemVO();
item.setText(genre.name());
item.setItems(getMoviesByGenre(genre));
items.add(item);
}
return items;
}
}
|
And last is our Spring Controller which will take the request from ExtJS store and return the Movie List.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package org.techzoo.touch.controller;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.techzoo.touch.service.MovieService;
import org.techzoo.touch.vo.ItemVO;
@Controller
public class MovieController {
@RequestMapping (value = “movies/loadmovies.do”, method = RequestMethod.GET)
public @ResponseBody ItemVO loadAllMovies()
throws Exception
{
final List<ItemVO> itemsVo = MovieService.getAllMovies();
final ItemVO movies = new ItemVO(“Movies – Genre”, itemsVo, false);
return movies;
}
}
|
Here we end with Java part and let me quickly show you what you need to create a NestedList
in Sencha Touch.
First of all, create a Model like below.
1
2
3
4
5
6
7
8
|
Ext.define(“TechZoo.model.Movie”, {
extend: “Ext.data.Model”,
config: {
fields: [
{name: ‘text’, type: ‘string’}
]
}
});
|
Next, create a store which has the reference of Model in it and define proxy. Please note the proxy url is same as spring controller @RequestMapping
value. Also observe that our store is extending Ext.data.TreeStore
instead of Ext.data.Store
.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Ext.define(‘TechZoo.store.Movie’, {
extend: ‘Ext.data.TreeStore’,
storeId: ‘movieStore’,
config: {
model: ‘TechZoo.model.Movie’,
defaultRootProperty : ‘items’,
proxy: {
type: ‘ajax’,
url: ‘/SenchaTouchTutorials/api/movies/loadmovies.do’
}
}
});
Ext.create(‘TechZoo.store.Movie’);
|
Now, create Ext.dataview.NestedList
which has the store reference and a listener to leafitemtap event. Pay attention to detailCard : true
snippet. If its true then after clicking on last node in the tree, it shows a Ext.Container
with last leaf details.
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
|
Ext.define(‘TechZoo.view.MovieList’, {
extend: ‘Ext.dataview.NestedList’,
alias : ‘widget.movielist’,
config: {
store : ‘Movie’,
title: ‘Movies – by Genre’,
itemTpl : ‘
{title}
‘ , displayField: ‘text’,
detailCard : true,
listeners : {
leafitemtap: function(nestedList, list, index, node, record) {
var movie = record.raw.items;
var tpl = new Ext.Template(
“
Movie ID : {id} “ , “
Movie Name : {title} “ , “
Director : {director} “ , “
Movie Genre : {genre} “ , “
Year Of Release : {yearOfRelease} “ , {compiled: true}
);
var detailCard = nestedList.getDetailCard();
detailCard.setHtml(tpl.apply(movie));
}
}
}
});
|
Output:
On initial launch you will see below…
Click on any of the Movie genre and it will load all the movies available on genre.
Now select any movie and you will see its details in a detailCard container like below.
I hope you enjoy the post. Happy coding 🙂
Source techzoo.org