2010年10月6日水曜日

ExtJS-99 Ext.form.ComboBoxとhiddenName

今日、先日の勉強会でご一緒させて頂いた@taka_2さんが
ふとつぶやいていた件について
「あー、そういわれれば確かに。なんでComboBoxでhidenNameを指定すると取得できるんだろか?」
ととっても新鮮な気付きをいただきました。

で、ちょっと調べてみた。
ちょっと読んだだけだからばっちりあってるとはかぎらないけど、
概要はあってるはず。

まず、しょっぱなから本題からそれるけど、storeプロパティに配列指定だけで動いている
仕組みを追ってみた。

storeを配列で指定した場合、ComboBoxのstoreは内部でストアマネージャでlookupしてる。
指定されたidが配列だったら'field1'、'field2'…というフィールド名でArrayStoreを内部で生成してるようです。
だから配列で設定しても内部ではArrayStoreなんですね。

次。

FormPanel.getForm().getValuesで取得な話。
form.getValuesは内部でExtのコンポーネントのgetValue()をしているわけじゃなく、
HTMLElementのvalueを取得している。

もう少し構造を追ってみる。

getValuesはBasicFormで実装されてて,
Ext.lib.Ajax.serializeForm(this.el.dom);となっている。
key=valueの形でelement.name = element.value/element.textになる。
各値は&結合。

このelementはExt.ElementじゃなくてDomのエレメント。
serializeFormするときのelement.valueはDomのHTMLInputElement.valueということになる。
で、DomのHTMLInputElement.valueはtypeが「text,file,password」の時は入力されている値がそのまま
セットされるためシリアライズするときのvalueは表示されているものが設定される。
ということになるっぽい。

ComboBoxっていったってもとはTextFiledクラスを継承したTrggerFieldクラスを継承してるだけで、
選択肢がみえているのはComboListLayerで別Divでそう見させているから。
実はinputタグのtypeがtext。

だからgetValuesすると表示している値が取得できてしまうのである。っぽい。

まずはこれがComboBoxがgetValuesで取得するとvalueが取得できない理由でした。

ではhiddenNameを設定するとなぜ取得できるのか。。

hiddenNameを設定するとComboBox内部でinputタグをtypeをhiddenで作成する。
DomのHTMLInputElement.valueはtypeが「button,hidden,submit,reset,image,checkbox,radio」の時は
value属性値が設定されるからhiddenタグはvalue値になるわけ。
ComboboxのSetValueでhiddeenField.valueにvalue値を設定しているもんね。

だからシリアライズするときはvalue値が設定される。
と、こういう解釈で良いのかな??。。

でもひとつ腑に落ちない。

hiddenNameを設定するとvalueが取得できて、いままで取得できてた元の値が取得できなくなるのはなぜか?
insertSiblingで挿入しているので
type='text'な値とtype='hidden'な値が取得できても良いじゃないか。
とおもった。

前に書いた様に、
getValuesで取得できるのはExt.lib.Ajax.serializeFormでシリアライズしてるから。
でその対象の条件は!element.disabled && name。
が、hiddenNameが設定してあると元となる表示されている方のエレメントはname属性がついていない。

なぜか。

このname属性、ComboBoxのhiddenName指定すると
onRender内で
submitValue = falseにする。
で、ComboBoxの基底クラスであるFieldクラスのonRenderでは
submitValue === falseだと
this.el.dom.removeAttribute('name');
としていてname属性を削除している。

ということでname属性が無くなり、
getvaluesしても取得できないんだ。。。










↑hiddenName未設定時のDomツリー











↑hiddenName設定時(「hidden」という名前で設定)のDomツリー


====
おさらい。

ComboBoxその1:storeを配列で指定した場合の話
ComboBoxのstoreは内部でストアマネージャでlookupしてる。指定されたidが配列だったら'field1'、'field2'…というフィールド名で
ことでArrayStoreを内部で生成してた。
だから配列で設定しても内部ではArrayStoreなんですね。

ComboBoxその2:Comboboxの値の話
フォーム内の値はHTMLElementのvalueをシリアライズ化しているのでCombboxの実体はtype=textなので表示されている
値がvalueとなっちゃうよ。ということ。

ComboBoxその3-1:Comboboxの値の話
表示している値(displayFiled)じゃなくて(valueFild)が取得したい場合はhiddenNameを指定する。
これを指定するとinsertSiblingでhiddenタグをname属性をhiddenNameで挿入してくれる。
で、元からあるinputタグのname属性は削除される。

ComboBoxその3-2:フォームのgetValuesについて
内部でformが抱えるDomエレメント分まわしてシリアライズ化する。key(name属性)/value(value属性)で。
で、そのときの対象は!element.disabled && name。

=====
まとめ

ComboBoxを利用するときは配列指定であれば特にArrayStore=SimpleStoreは
指定することなく利用できるようです。

hiddenNameを指定することで値が取得できるようになるのは
内部でinputタグをtype=hiddenで作成しているからgetForm時のシリアライズ化時に
value値をちゃんと取得してくれるから。

hiddenNameを指定するといままで設定していたname属性は排除されて
シリアライズ化対象から外れます。

=====
おしまい。

自分なりにすっきり!!

0 件のコメント: