Posted at

Sencha Touchの2つのカルーセルで同一レコードの値を表示

More than 3 years have passed since last update.

Sencha Touchでストアのインラインデータ上に保存しているプレーヤーの情報をランダムで取得し、1つ目のカルーセルに名前を、2つ目のカルーセルに詳細情報を表示する例。

モデル作成からビューの作成の箇所が冗長なのでコントローラの作成の所を見れば事足りると思う


アプリ作成

下記コマンドでValuetestというサンプルアプリをつくる。

sencha -sdk $HOME/Code/Framework/touch-2.3.1 generate app Valuetest valuetest


モデル作成

できたvaluetestディレクトリに移動して下記コマンドでモデルを作成する。

sencha generate model --name=Player --fields=name:string,no:int,position:string


app/model/Players.js(自動生成)

Ext.define('Valuetest.model.Player', {

extend: 'Ext.data.Model',

config: {
fields: [
{ name: 'name', type: 'string' },
{ name: 'no', type: 'int' },
{ name: 'position', type: 'string' }

]
}
});


app.jsに下記を追加


app.jsの一部

models: ['Player'],



ストア作成

下記の内容でapp/store/Players.jsを作成する。


app/store/Players.js

Ext.define('Valuetest.store.Players', {

extend: 'Ext.data.Store',
config: {
model: 'Valuetest.model.Player',
data: [
{
name: 'Wayne Rouney',
no: 10,
position: 'Striker'
},
{
name: 'Daren Flecher',
no: 24,
position: 'Midfielder'
}
]
}
})

app.jsに下記を追加。


app.jsの一部

stores: ['Players'],



ビューの作成

下記内容でカルーセルを表示するためのコンテナを作る。


app/view/Main.js

Ext.define('Valuetest.view.Main', {

extend: 'Ext.Carousel',
xtype: 'main',
requires: [
'Valuetest.view.Playername',
'Valuetest.view.Playerinfo',
],

config: {
xtype: 'carousel',
fullscreen: 'true',
direction: 'horizontal',
items: [
{
xtype: 'playername'
},
{
xtype: 'playerinfo'
}
]
}
})


次に1つ目の名前を表示するビューを作る。


app/view/Playername.js

Ext.define('Valuetest.view.Playername', {

extend: 'Ext.Container',
xtype: 'playername',
config: {
tpl: Ext.create('Ext.XTemplate',
'<tpl>',
'<p>Name: {name}</p>',
'</tpl>'
),
}
})

次に2つ目の詳細情報を表示するビューを作る。


app/view/Playerinfo.js

Ext.define('Valuetest.view.Playerinfo', {

extend: 'Ext.Container',
xtype: 'playerinfo',
config: {
tpl: Ext.create('Ext.XTemplate',
'<tpl>',
'<p>No: {no}<p>',
'<p>Position: {position}</p>',
'</tpl>'
)
}
})


コントローラーの作成

下記コマンドでコントローラを作成。

sencha generate controller Main

app.jsにコントローラを追加


app.jsの一部

controllers: ['Main'],


下記内容でapp/controller/Main.jsを作成。


app/controller/Main.js

Ext.define('Valuetest.controller.Main', {

extend: 'Ext.app.Controller',

config: {
refs: {
playerName: 'playername',
playerInfo: 'playerinfo',
},
control: {
'playername': {
activate: 'getCurrentRecord'
},
'playerinfo': {
activate: 'getDetailInfo'
}
},
},

currentid: '',

getCurrentRecord: function() {
var store = Ext.getStore('Players');
var store_length = store.getCount();
var randnum = Math.floor(Math.random() * store_length);
var name = store.getAt(randnum).get("name");
var view = this.getPlayerName();
view.setData(
{
name: name,
}
);
this.currentid = randnum;
},

getDetailInfo: function(){
var store = Ext.getStore('Players');
var indexid = this.currentid;
var current_record = store.getAt(indexid);
var no = current_record.get("no");
var position = current_record.get("position");
var view = this.getPlayerInfo();
view.setData(
{
no: no,
position: position
}
);
},
});


ポイントは currentid: '',の部分で、Playernameのビューがアクティブになるたびにストア内の要素をランダムで取ってきたあとにスタア内で何番目のデータかを記憶させておいてPlayerinfoのビューがアクティブになった時にcurrentidの数字を元に再度ストア内を検索してnoとpositionの値を表示することができる。

ただし、この方法だとクエリが2度も発生してしまうのでビューからビューへ値を渡す方法を調査して適用するほうがいいはずだけど、今のところやり方がわからない。

早い段階でこの例のようにグローバル変数を定義して書き換えればできるだろうことは想像出来てたけど、この方法はあまり美しくなさそう、という理由からまる1日調べるのに時間を費やしてしまった…


ブラウザで確認

アプリルートディレクトリで下記コマンドで簡易HTTPサーバを起動。

python -m SimpleHTTPServer

これでフリックした時に名前と詳細情報の表示を確認できる。