2012-02-27 15 views
7

Parece que cada vez que aprendo una nueva plataforma, tengo que volver a resolver este mismo viejo problema: Actualice las opciones en un menú desplegable al cambiar otro menú desplegable, usando Ajax. Esta vez el marco es Wicket.Wicket Ajax actualiza un menú desplegable a otro

Tengo dos entidades a las que llamaré Foo y Bar, y cada Foo tiene una categoría, que es una enumeración interna de Foo. Además, existe un FooDAO con métodos find() sobrecargados: la versión no-arg devuelve todos los Foo en el DB, o una versión con un "filtro" paramater de Type Foo que devuelve todos los filtros coincidentes Foo en valores no nulos.

El cliente desea asociar Foos a Barras cuando crea una nueva Barra, pero para filtrar Foos por categoría antes de agregar una. Asume que un puñado de Foo ya existen, cada uno con una categoría. Un usuario va a la página Crear barra y la sección para agregar un nuevo Foo: El menú desplegable A enumera las categorías, y al elegir una categoría, se supone que la Lista desplegable B muestra la lista de Foo disponible en esa categoría mediante una actualización de Ajax. Tenga en cuenta que no se selecciona ninguna categoría, el menú desplegable B debe mostrar todos los Foo disponibles.

Mi HTML se ve un poco como esto:

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

(. El botón con el tiempo obtener su propio ID y el comportamiento, pero en este momento la atención se centra en las listas)

Aquí es el de Java lateral (en el método constructor de la página):

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

no he mostrado mis logger.debug llamadas, pero con ellos soy capaz de demostrar que el newSelection está siendo capturado correctamente, y el DAO está devolviendo la lista esperada de Foo. Además, la lista avaliableFoo contiene los valores necesarios también. Sin embargo, Dropdown B siempre muestra la lista completa de Foo, sin importar de la categoría seleccionada.

+1

En vista de que usted tiene la respuesta correcta, esto es en una nota al margen: Probablemente me muevo el código de actualización de selección/elección en los respectivos modelos de los componentes alternativos desplegable y justo Haga la llamada 'target.addComponent()' en el método 'onUpdate()', su código será mucho más fácil de leer y mantener. – biziclop

Respuesta

5

Tienes que agregar tus DropDowns al AjaxRequestTarget o no se actualizarán.

como en

target.add(selectedFoo); 
+0

También tengo que agregar 'selectedFoo.setOutputMarkupId (true);' pero parece estar funcionando. – cobaltduck

Cuestiones relacionadas