2012-02-27 63 views
7

似乎每次我學習一個新平臺時,我都必須重新解決相同的老問題: 使用Ajax更改另一個下拉菜單時更新下拉菜單中的選項。這一次 的框架是Wicket。Wicket Ajax將其中一個下拉菜單更新爲另一個下拉菜單

我有兩個實體,我稱之爲Foo和Bar,每個Foo都有一個類別,這是Foo內部的枚舉。此外,還有一個重載find()方法的FooDAO:no-arg版本返回數據庫中的所有Foo,或者帶有類型Foo的參數「過濾器」的版本,它返回非空值中的所有Foo匹配過濾器。

客戶希望在創建新Bar時將Foos與Bars關聯,但在添加Fo之前按類別過濾Foos。因此,假設少數Foo已經存在,每個都有一個類別。用戶轉到創建欄頁面並添加新的Foo部分:下拉列表中列出了類別,並且在選擇某個類別時,Dropdown B應該通過Ajax更新顯示該類別中可用Foo的列表。請注意,沒有選擇類別,下拉B應該顯示所有可用的Foo。

我的HTML看起來有點像這樣:

<form wicket:id="createBarForm"> 
<div> 
    <label>Category</label> 
    <select wicket:id="category"> 
    </select> 
</div> 
<div> 
    <label>Available Foo(s)</label> 
    <select class="xlarge" wicket:id="selectedFoo"> 
    </select> 
</div> 
<button style="float:right;">Add</button> 

<!-- and more Bar related fields --> 
</form> 

(該按鈕將最終獲得自己的ID和行爲,但現在的重點是在名單)

這裏是Java側(在頁面的構造方法):

createBarForm = new Form<Bar>("createBarForm", 
      new CompoundPropertyModel<Bar>()); 

    final List<Foo> availableFoo = fooDao.find(); 

    final FormComponent<Foo> selectedFoo = 
      new DropDownChoice<Foo>("selectedFoo", 
        Model.of(new TechnologyFoo()), availableFoo); 

    Foo.Category categoryStandin = null; 

    final FormComponent<Foo.Category> fooCategory = 
      new DropDownChoice<Foo.Category> 
       ("fooCategory", Model.of(categoryStandin), 
         Arrays.asList(Foo.Category.values())); 

    fooCategory.add(new AjaxFormComponentUpdatingBehavior("onchange") { 
     private static final long serialVersionUID = 1L; 
     @Override 
     protected void onUpdate(AjaxRequestTarget target) { 
      // re-set the form component 
      availableFoo.clear(); 
      ((DropDownChoice<Foo>)selectedFoo).setChoices(availableFoo); 
      createBarForm.remove(selectedFoo); 

      Foo.Category newSelection = 
        fooCategory.getModelObject(); 
      if (newSelection != null) { 
       Foo filter = new Foo(); 
       filter.setCategory(newSelection); 
       availableFoo.addAll(fooDao.find(filter)); 
      } 
      else { 
       availableFoo.addAll(fooDao.find()); 
      } 
      // re-fresh the form component 
      ((DropDownChoice<Foo>)selectedFoo).setChoices(availableFoo); 
      createBarForm.add(selectedFoo); 
     } 
    }); 

    createBarForm.add(fooCategory); 
    createBarForm.add(selectedFoo); 

    // etc..... 

我沒有表現出我的logger.debug電話,但與他們我能夠表明newSelection正在正確捕獲,並且DAO正在返回Foo的預期列表。此外,avaliableFoo列表也包含所需的值。但是,無論類別選擇爲 ,下拉B總是顯示Foo的完整列表。

+1

看到,因爲你已經得到了正確的答案,這是阿里納斯:我可能會移動選擇/選擇更新代碼,在下拉菜單中選擇組件各自的模型和公正在'onUpdate()'方法中調用'target.addComponent()'方法,你的代碼將更容易閱讀和維護。 – biziclop 2012-02-27 22:32:31

回答

5

您必須將DropDowns添加到AjaxRequestTarget,否則它們將不會更新。

target.add(selectedFoo); 
+0

我還必須添加'selectedFoo.setOutputMarkupId(true);'但它似乎工作。 – cobaltduck 2012-02-27 16:21:52