2007年9月17日 星期一

動態產生form欄位

在wicket中,幾乎所有的web元件都要有對應的html element+wicket id,因此要做到動態產生form內的欄位幾乎沒辦法。不過,最近同事在研究最新版的jtrac的source code,發現透過ListView + Fragment + BoundCompoundPropertyModel就可以做到:
  • ListView主要是用來作為動態新增項目layout的部份,因為它可以根據所給予的model或是List內的內容來產生應該要有的項目。
  • Fragment主要是用來簡化設計,因為原本Fragment就是一種不需要獨立的html template file的一種特殊Panel,所以可以運用來呈現每個ListItem裡的欄位
  • BoundCompoundPropertyModel主要是用來將POJO跟wicket component之間的綁定,採取更彈性的方式來實現。
事實上,應該不是只有以上3種東西的結合才做的出來,只是目前這三種東西的結合是比較容易的作法。主要的關鍵應該是在於如何在runtime的時候,才去產生form欄位的html與必要的code,這通常是需要像是ListView或是Loop這類可以重複產生item的元件。而雖然可以產生重複的item,但是item的內容還必須不一樣,所以才會需要Fragment(這邊也可以用Panel來達成,只是用Panel就會比較麻煩)。有了不同的item之後,另一個問題就是元件與實際data model之間的連結關係,使用BoundCompoundPropertyModel是可以用比較彈性的方式去做到,但是用其他的Model應該也可以,只是可能會比較困難。

有一點需要注意的是:由於是透過ListView來產生item,所以當發生validate error時而回到form時,ListView是會重新再產生新的item,而新的item會去讀取model內的值。但是,由於validation失敗,所以model是不會被更新,所以所有的item都會回到一開始的值,而不是之前輸入的值,這對於很大的form來說是會對user造成困擾的。所幸,可以透過ListViewsetReuseItem(true)來避免重新產生新的item,而是沿用先前產生的,所以就可以保留validation之前的輸入值。

P.S: 雖然說理論上不一定要用ListView,但是由於所知只有ListView才有setReuseItems(),所以若是使用Loop或是其他非ListView的subclasses的元件,可能要自己想辦法處理重複產生新item的問題。

沒有留言: