2012-02-27 37 views
7

Có vẻ như mỗi lần tôi học một nền tảng mới, tôi phải giải quyết vấn đề cũ này: Cập nhật các lựa chọn trong một trình đơn thả xuống khi thay đổi một trình đơn thả xuống khác, sử dụng Ajax. Lần này là khuôn khổ là Wicket.Wicket Ajax cập nhật một danh sách xuống

Tôi có hai thực thể, tôi sẽ gọi Foo và Bar và mỗi Foo có một danh mục, đó là nội dung của Foo. Ngoài ra, tồn tại một FooDAO với quá tải phương thức find(): phiên bản no-arg trả về tất cả Foo trong DB hoặc phiên bản có bộ lọc "paramater" của Foo loại trả về tất cả bộ lọc phù hợp với Foo trong giá trị không null.

Khách hàng muốn liên kết Foos với Thanh khi tạo Thanh mới, nhưng để lọc Foos theo danh mục trước khi thêm. Vì vậy, giả sử một số ít các Foo đã tồn tại, mỗi với một thể loại. Một người dùng vào trang tạo Bar và phần để thêm một Foo mới: Dropdown A liệt kê các thể loại, và khi lựa chọn một thể loại, Dropdown B được cho là hiển thị danh sách Foo có sẵn trong thể loại đó, thông qua một bản cập nhật Ajax. Lưu ý rằng không có danh mục nào được chọn, trình đơn thả xuống B sẽ hiển thị tất cả Foo có sẵn.

HTML của tôi trông một chút như thế này:

<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> 

(. Nút cuối cùng sẽ nhận được id và hành vi của riêng mình, nhưng ngay bây giờ tập trung là trên danh sách)

Đây là Java bên (trong phương thức khởi tạo của trang):

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..... 

tôi đã không được hiển thị logger.debug cuộc gọi của tôi, nhưng với họ, tôi có thể chỉ ra rằng newSelection đang được được chụp chính xác và DAO đang trả về danh sách Foo dự kiến. Ngoài ra, Danh sách avaliableFoo cũng chứa các giá trị được yêu cầu. Tuy nhiên, Dropdown B luôn hiển thị danh sách đầy đủ của Foo, bất kể của lựa chọn danh mục.

+1

Thấy như bạn đã có câu trả lời đúng, đây là trên một sidenote: Tôi có lẽ muốn di chuyển vùng chọn/lựa chọn cập nhật mã trong các mô hình tương ứng của các thành phần thả xuống lựa chọn và chỉ thực hiện lệnh 'target.addComponent()' trong phương thức 'onUpdate()', mã của bạn sẽ dễ đọc và bảo trì hơn nhiều. – biziclop

Trả lời

5

Bạn phải thêm DropDown của mình vào AjaxRequestTarget hoặc chúng sẽ không được cập nhật.

như trong

target.add(selectedFoo); 
+0

Tôi cũng phải thêm 'selectedFoo.setOutputMarkupId (true);' nhưng có vẻ như nó đang hoạt động. – cobaltduck

Các vấn đề liên quan