YiiFramework.comでは、毎日のようにエクステンションが登録されたり、チュートリアルが投稿されています。眺めていると使えそうなものや、アイデアに出会えたりして楽しいですよね。
さて、今回はエクステンションを自作してみます。一口にエクステンションといってもいろいろありますが、jQuery UI MultiSelect WidgetをYiiFrameworkのウィジェットにします。
ウィジェットを作る前に
ビューで直接jQuery UI MultiSelect Widgetを使ったコードです。
MultiSelect on View
<?php
// データ
$data = array(
1=>'Yii',
2=>'Advent',
3=>'Calendar',
4=>'2012',
);
$select = array(1, 3);
// 依存する JavaScript,CSS をインクルードする (一部)
$url = Yii::app()->getAssetManager()->publish($assets_dir.DIRECTORY_SEPARATOR.'jquery.multiselect.js');
Yii::app()->getClientScript()->registerScriptFile($url, CClientScript::POS_END);
// SELECTタグ出力
echo CHtml::dropDownList('multiselect',$select,$data,array(
'id'=>'multiselect',
'multiple'=>'multiple',
));
// SELECTタグにjquery.multiselectを適用する
Yii::app()->getClientScript()->registerScript('#multiselect', "$('#multiselect').multiselect();");
?>
なんかいろいろやっててとてもビューに見えません。これでもJavaScript、CSSのインクルードを省略しているんですが。。。えーと、他のビューで同じマルチセレクトを使いたいとき、これらをコピペするのでしょうか?!
いいえ、YiiFrameworkではウィジェット化するんです!
ウィジェットは、ユーザインタフェースコードの再利用性を高めてくれます。
http://www.yiiframework.com/doc/guide/1.1/ja/basics.view#sec-3
ウィジェットを作る
jQuery UIウィジェットのYiiウィジェット化は、決して難しくありません。どのjQuery UIウィジェットでも、最低限やるべきことは3つです。
- 依存するjsファイル、cssファイルをインクルードする
- ウィジェットに必要なHTMLを出力する
- オプションをjQuery UIウィジェット設定インタフェースに渡す
そして作成したウィジェットはこちら。
EMultiSelectWidget.php
EMultiSelectWidgetを使う
EMultiSelectWidgetを使うと、ビューはこのようにすっきりします。
EMultiSelectWidget :
<?php
$this->widget('ext.emultiselectwidget.EMultiSelectWidget', array(
'name'=>'EMultiSelectWidget',
'data'=>$data,
'select'=>$select,
));
$data
と$select
は省略しましたが、上のコードと同じです。
EMultiSelectWidgetの設定
options
からjQuery UI MultiSelect Widgetのオプションを設定できます。CJavaScriptExpressionを使ってJavaScriptも注入できる!jQueryウィジェットとYiiウィジェットって相性いいなあ。
htmlOptions
から出力するSELECTタグの属性を設定できます。
EMultiSelectWidget :
<?php
$this->widget('ext.emultiselectwidget.EMultiSelectWidget', array(
'name'=>'EMultiSelectWidget',
'data'=>$data,
'select'=>$select,
'options'=>array(
'checkAllText'=>'すべて選択',
'uncheckAllText'=>'選択解除',
'noneSelectedText'=>'選択してください',
'selectedText'=>'#つ選択中',
'click'=>new CJavaScriptExpression('function(){console.log(\'click!!\')}'),
)
'htmlOptions'=>array(
'id'=>'hogeid',
'class'=>'piyoclass',
)
));
Yii Advent Calendar 2012でも何度か触れられていますが、CWidgetFactoryにまとめて設定することで、使う度に設定する手間も省けます。
まとめ
PHP+HTML+JavaScript+CSSを一括りにするときはウィジェット化しよう。ウィジェット単体でテストできるし、再利用もできる。
もうひとつ - 思いつき
ウィジェット化すると、PHP+HTML+JavaScript+CSSが一括りにできて便利なのですが、HTMLとしては読みにくくなります。そこで思いついたのですが、次だとどうでしょう。
<?php $w = $this->beginWidget("multiselect"); ?>
<select id="<?php echo $w->id; ?>" class="...">
<?php echo CHtml::listOptions($select, $data); ?>
</select>
<?php $this->endWidget(); ?>
未検証ですが、次のメリットがあるかなーと。
- select タグを使っていることを明確にできる
- select タグの属性を、
array('htmlOptions'=>)
でなく、HTMLに書ける