2012-02-27 19 views
7

Wydaje się, że za każdym razem, gdy uczę się nowej platformy, muszę ponownie rozwiązać ten sam stary problem: Zaktualizuj opcje w jednym menu po zmianie innego menu, używając Ajax. Tym razem ramą jest Wicket.Ajax Wicket uaktualnienie jednego dropdown do innego

Mam dwa podmioty, które będę nazywać Foo i Bar, a każdy Foo ma kategorię, która jest wewnętrzną enum dla Foo. Istnieje również metoda FooDAO z przeciążonymi metodami: Argument no-arg zwraca wszystkie Foo w DB lub wersję z parametrem "filter" typu Foo, która zwraca wszystkie pasujące filtry Foo w wartościach innych niż NULL.

Klient chce skojarzyć Foos z Bars podczas tworzenia nowego paska, ale aby filtrować Foos według kategorii przed dodaniem. Załóżmy, że garstka Foo już istnieje, każda ma kategorię. Użytkownik przechodzi do strony tworzenia paska, a sekcja do dodania nowego Foo: Dropdown A zawiera listę kategorii, a po wybraniu kategorii, Dropdown B ma pokazać listę dostępnych Foo w tej kategorii, poprzez aktualizację Ajax. Pamiętaj, że nie wybrano żadnej kategorii, menu rozwijane B powinno pokazywać wszystkie dostępne Foo.

Moje HTML wygląda trochę tak:

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

(. Przycisk ostatecznie dostać swój własny identyfikator i zachowanie, ale teraz skupiamy się na listach)

Oto Java bok (w metodzie konstruktora strony użytkownika):

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

nie wykazały moje logger.debug połączeń, ale z nich jestem w stanie pokazać, że jest w trakcie newSelection poprawnie zrobione, a DAO zwraca oczekiwaną listę Foo. Ponadto lista avaliableFoo zawiera również wymagane wartości. Jednak lista rozwijana B zawsze pokazuje pełną listę Foo, niezależnie od tego, czy jest to wyboru kategorii.

+1

Widząc jak masz właściwą odpowiedź, to na marginesie: ja prawdopodobnie przenieść wybór/wybór kodu aktualizującego w odpowiednich modeli komponentów wyboru rozwijana i po prostu wykonaj wywołanie 'target.addComponent()' w metodzie 'onUpdate()', kod będzie znacznie łatwiejszy do odczytania i konserwacji. – biziclop

Odpowiedz

5

Musisz dodać DropDowns do AjaxRequestTarget lub nie będą one aktualizowane.

jak w

target.add(selectedFoo); 
+0

Muszę również dodać 'selectedFoo.setOutputMarkupId (true);' ale wygląda na to, że działa. – cobaltduck

Powiązane problemy