読者です 読者をやめる 読者になる 読者になる

名称未定ドキュメント"Que"

hidesukeの読書感想文

SenchaTouchのformで、standardSubmitを使うときの罠

javascript SenchaTouch SmartPhone

読書感想文ブログですが、hidesukeの本業はweb系エンジニアだったりします。
最近までSenchaTouchを使ってごにょごにょするお仕事をやっていたのですが、はまったというか、バグっぽい挙動を見つけてしまったのでメモ。


SenchaTouchでformを作るときは、Ext.form.FormPanelを使って実装すると思います。
んで、Ext.form.Selectとか、Ext.form.Textとか使って、入力コンポーネントを書く。
こんな感じになるはず。

var form = Ext.form.FormPanel({
  items : [
    {
      xtype : "selectfield",
      label : "選択肢のサンプル",
      name : "selection",
      options : [
         {text : "option1", value : 1},
         {text : "option2", value : 2)
      ]
    }
  ]
});

var button = Ext.Button({
  text : "submit",
  listeners : {
    tap : function() {
      form.submit();
    }
  }
});

実はすでにここで注意しなきゃ行けない点があります。
SenchaTouchのAPIドキュメントのSmapleなどでは、selectfieldにnameプロパティが書いてないのですが、このnameプロパティを省略すると、実機(iPhone or Android)でselectができません
いちいち実機で確認するの面倒なので、ChromeとかSafariで確認していると陥りやすい罠です。

Ext.form.FormPanelのsubmit()は、デフォルトだとAjax通信することを期待しています。なので、successとか、failuerとかのコールバック関数を書いてあげる必要があります。
まぁ、スマホだし、そういうUIの方が普通ですよねー。

で、自分がやってる案件ではちょっと特殊なことをしていて、Ajax通信したくなかったんですね。submit押すとsubmit先のアクションでリダイレクトさせたいみたいな。
こういう場合だと、SenchaTouchは「そんなリソースねぇよ!」とエラーをはいて、ページ遷移を行いません。

こういう時は、standardSubmitをtrueにしてあげると解決します。

var form = Ext.form.FormPanel({
  standardSubmit : true,
  items : [
    {
      xtype : "selectfield",
      label : "選択肢のサンプル",
      name : "selection",
      options : [
         {text : "option1", value : 1},
         {text : "option2", value : 2)
      ]
    }
  ]
});

で、こっからが問題。
単純にstandardSubmit : true と付けるだけだと、selectfieldの挙動がおかしくなります。
どうおかしくなるかというと、パラメタとして、 「http://example.com/?selection=1」 とかじゃなくて、「http://example.com/?selection=選択肢のサンプル」みたいにlabelの値を何故か値として送信します。
これは、APIリファレンスに対策が書いてあって(Ext.form.Selectに書いてある)、standardSubmitのときは、nameではなくてhiddennNameを使いましょうと書いてあります。
なので、hiddenNameに修正.

var form = Ext.form.FormPanel({
  standardSubmit : true,
  items : [
    {
      xtype : "selectfield",
      label : "選択肢のサンプル",
      hiddenName : "selection",
      options : [
         {text : "option1", value : 1},
         {text : "option2", value : 2)
      ]
    }
  ]
});

よしよし、意図通りに動いた。
と、PCのブラウザだけで確認して満足したら大間違い
実機で確認してみてください。また、selectボックスが動かなくなっています!
じつはnameプロパティが無いと実機でselectボックスは動かないらしい。。。

var form = Ext.form.FormPanel({
  standardSubmit : true,
  items : [
    {
      xtype : "selectfield",
      label : "選択肢のサンプル",
      hiddenName : "selection",
      name : "dummyName",
      options : [
         {text : "option1", value : 1},
         {text : "option2", value : 2)
      ]
    }
  ]
});

これでselectもできるようになりました。
ただ、 「http://example.com/?selection=1&dummyName=選択肢のサンプル」 のようなリクエストを吐いています……。
これってバグだよなぁ。


というようなことにハマって、頭を掻き毟っていたのでしたので、メモ、と。
みんなで幸せになろうよ。