2012-02-27 59 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