2010年7月9日金曜日

zend + dojo : 画像のsubmitの挙動が変だったハナシ

Zend + Dojoで画像ボタンでsubmitしようとしたんですが、サーバからの返却が何やらおかしかった。
<input type="submit">を<input type="image" src="">にしたい場面はたくさんありますが、ajaxでの接続で挙動がおかしい場面があったのでメモ。

通常のボタンでsubmitする場合

HTML

<form action="#" id="hoge">
   
<button name="btn_submit" id="btn_hoge" type="button" value="hoge">hoge</button>
</
form>

// dojo.connect
<script type="text/javascript">
   
// イベントハンドラの登録
    dojo
.addOnLoad(function() {
       
// btn_hoge要素にイベントハンドラを設定する。
       
// onclickイベントを引っ掛けて、hogeフォームの内容をsubmit
       
// /fuga/piyoアクションをコールして、json形式でレスポンスを受け取る。
        dojo
.connect(dojo.byId("btn_hoge"), "onclick", function() {
            dojo
.xhrPost({
                url
: "/fuga/piyo/format/json",
                content
:{"a":"b"},
                form
: "hoge",
                handleAs
: "json",
                load
: function(data){
                    alert
('OK');
               
},
                error
: function(error, args) {
                    alert
('NG');
               
}
           
});
       
});
   
});
</script>
Zend

/**
 * Fugaコントローラ
 */

class FugaController extends Zend_Controller_Action
{
   
/**
     * piyoアクションのコンテキストとしてjsonを登録
     */

   
public function init()
   
{
        parent
::init();
        $contextSwitch
= $this->_helper->getHelper('contextSwitch');
        $contextSwitch
->addActionContext('piyo', 'json')
                     
->initContext();
   
}

   
/**
     * Piyoアクション
     */

   
public function PiyoAction()
   
{
       
// View変数をシリアライズしてjsonとして返却
       
// {"viewMessages":"abc"}
        $this
->view->message = 'abc';
   
}
}

上記は、普通にajax通信できますが、以下のようにボタンを画像にすると、dojoのイベントハンドラでerror関数がコールされ、error変数として「Error: Unable to load /fuga/piyo/format/json status:0」という良く分からないエラーが返却されます。

HTML

<form action="#" id="hoge">
   
<input type="image" src="" name="btn_submit" id="btn_hoge" value="btn_submit" />
</form>

サーバでログ取ってみても、postされてたりされてなかったり、規則性なくランダムにサーバにリクエストが到達しているようでした。
error関数も複数回コールされることがあり、1回のボタン押下で何回か/puga/piyoアクションがコールされることもありました。

何でそんなことになるのか分かりませんでしたが、dojo.connectでinput属性のエレメントにハンドラを設定しているのが問題っぽい。

<form action="#" id="hoge">
</form>
<input type="image" src="" name="btn_submit" id="btn_hoge" value="btn_submit" />

こんな感じでformの外にimage要素を配置すると、サーバには1回だけ行儀よくPOSTし、返却値も期待するJSON形式で受け取れるようになります。

formの中にいる<input type="image">な要素にdojo.connectすると、dojoで接続されたイベントハンドラと、form自体のactionとの両方が実行されてしまうようです。

0 件のコメント:

コメントを投稿