Edited at

Alloyのcontroller同士を上手に連携させる

More than 3 years have passed since last update.

Alloyを使っていて慣れない人が一番最初に戸惑うのは、コントローラ同士の連携だといわれています(記事を書く側はいつでも勝手に読み手の考えを決めつけることができます)。そこでいい機会なので(どんな機会なんでしょうね)まとめておきます。


1. 引数で連携する

まず、最も単純な例です。あるコントローラの中から別のコントローラを呼び出す際に引数を渡します。

var args = {

tab: $.index.tab,
model: e.model
};
var window = Alloy.createController('another_controller', args).getView();

createControllerされる別のコントローラの中で引数argsを受け取るには

var args = arguments[0] || {};

var tab = args.tab;
var model = args.model;

このように記述します。


1.5 呼び出された側から呼び出し元の機能にアクセスする

もう少しましな例を。呼び出されたコントローラ側から呼び出し元の機能にアクセスする手段も同じやり方で提供することができます。

var API = {

setTitle: function(title){
$.index.setTitle(title);
},
removeAllFriends: function(){
$.index.removeAllFriends({force: true});
}
};
var window = Alloy.createController('another_controller', API).getView();

コントローラらしくなってきましたね。


2. 呼び出し元が呼び出したコントローラの機能にアクセスする

親の機能に子からアクセスするのはデータを渡すだけなので上のように簡単に実現できるのですが、反対に子の機能に親の方からアクセスする方法はどうでしょう。

最も単純なのは、exportsを使ってこちらもAPIを用意するやり方です。実際の例を見てみましょう。

アプリ内で共通のActivityIndicatorを用意して使いまわしたい場合、デフォルトのメッセージを渡したり、状況に応じてmessageプロパティを更新したいなんてことはよくあるはずです。そこで、こんなViewとControllerを用意しました。

<Alloy><!-app/views/indicator.xml-->

<View class="container">
<ActivityIndicator id="ind" />
</View>
</Alloy>

// app/controllers/indicator.js

var args = arguments[0] || {};
$.ind.message = args.message ? args.message : "お待ちください…";
exports.API = {
setMessage: function(message){
$.ind.message = message;
}
};

tssは省略しましたが、これを実際に呼び出して使ってみます。

// app/controllers/index.js

var indicator = Alloy.createController('indicator', {message: "スタート!"}); //ここではgetViewはしない
var indicator_view = indicator.getView();
$.index.add(indicator_view);

var i = 0, timer = null;
timer = setInterval(function(){
//exportsで指定されたオブジェクトにアクセスできる
indicator.API.setMessage(i + "秒経過…");
i++;
if(i > 10){
$.index.remove(indicator_view);
clearInterval(timer);
}
}, 1000);

このように、呼び出されるコントローラ側でexportsを使って呼び出し元のコントローラにアクセスさせるAPIを用意してあげると、簡単にコントローラ同士を連携させることができます。他にも例えばViewの要素のプロパティに関数をセットしてアクセスさせるやり方もありますが、呼び出し元から直接Viewにアクセスさせず、処理はAPIとして公開するだけの方が、コードの見通しもいい上に気軽に外観の変更もできるのでメンテナンスも楽になります。