简体   繁体   中英

ZK Framework - How to access the onSelect method of a Combobox that is inside a Listbox generated with a render?

Good evening, I tell you my problem:

In the ZK Framework I need to use the onSelect method of a dynamically rendered Combobox within a Listbox that is also rendered.

When I select one of the Combobox options, its content should be saved in the observaciones variable of the DocumentoVinculado class. But the onSelect don't work. I appreciate any help: Attached code:

.zul

<zk>
<window id="myWindow" apply="com.curso.controller.NewFileComposer" title="Help">
        <listbox id="myListbox">
            <listhead>
                <listheader label="NroGEBI"></listheader>
                <listheader label="Observaciones"></listheader>
            </listhead>
        </listbox>
        <label id="myLabel"></label>
</window>
</zk>

Composer / Controller

public class NewFileComposer extends BaseController {

    private Window myWindow;
    private Listbox myListbox;
    private Combobox myCombobox0;
    private Combobox myCombobox1;
    private Label myLabel;

    public void onSelect$myCombobox0() { myLabel.setValue(myCombobox0.getValue()); }

    public void onSelect$myCombobox1() { myLabel.setValue(myCombobox1.getValue()); }
    
    public void onCreate$myWindow() {
        ListModelList<DocumentoVinculado> modelo = new ListModelList<>(crearLista());
        myListbox.setModel(modelo);
        myListbox.setItemRenderer(new NewFileRender());
    }
    
    private List<DocumentoVinculado> crearLista() {
        List<DocumentoVinculado> docVinculados = new ArrayList<>();
        docVinculados.add(new DocumentoVinculado("123GEBI1", " "));
        docVinculados.add(new DocumentoVinculado("123GEBI2", " "));
        return docVinculados;
    }
}

Render

public class NewFileRender implements ListitemRenderer {

    @Override
    public void render(Listitem item, Object data, int i) throws Exception {
        DocumentoVinculado docVinculado = (DocumentoVinculado) data;

        Listcell nroGebiCell = new Listcell(docVinculado.getNroGEBI());
        nroGebiCell.setParent(item);

        Listcell opcionesCell = new Listcell();
        opcionesCell.appendChild(comboboxObservaciones(i));
        item.appendChild(opcionesCell);
    }
    
    private Combobox comboboxObservaciones(int i) {
        Combobox combobox = new Combobox();
        List<String> listaDeOpciones = listaDeOpciones();
        for(String opcion : listaDeOpciones) {
            Comboitem myComboitem = new Comboitem();
            myComboitem.setLabel(opcion);
            myComboitem.setParent(combobox);
        }       
        combobox.setId("myCombobox" + i);
        return combobox;
    }
    
    private List<String> listaDeOpciones() {
        List<String> opciones = new ArrayList<>();
        opciones.add(" ");
        opciones.add("Opcion1");
        opciones.add("Opcion2");
        return opciones;
    }
}

Thank you for reading. Cheers!

From your syntax, it looks like you are using GenericForwardComposer as the super class for your BaseController. Is that correct?

Depending on how much you have already done, I'd recommend checking if you could switch to SelectorComposer instead. They work the same way (wire components, and listen to events), but the SelectorComposer is much more explicit in how things are wired. GenericForwardComposer can be somewhat error-prone unless you are very clear about its lifecycle.

Regarding why the onSelect would not be firing in this case:

ZK Composers works in phases. One important phase is the "compose" phase, during which the components are created, events listeners are put in places, etc.

At the end of that phase, the "afterCompose" phase takes place. During afterCompose, "magic" stuff (like the wiring of the private components in your current composer, or the auto-forwarding of the onSelect$myCombobox0 in the same class) takes place. It will also attempt to rewire stuff that was missing again just before triggering onCreate on its root anchor component.

Now, if your comboboxes are created dynamically after that step (for example, during an "onCreate$myWindow" event which happens after all of the above is finished), the composer will have already done all of the wiring and forwarding, and will not know to re-check the components for additional wiring.

With all of that explained, what can you do about it?

First, you can consider moving the onCreate code to a doAfterCompose method. Instead of waiting for onCreate to generate the Listbox content, if you do it during doAfterCompose (override from genericFowardComposer), you should be early enough that auto-wiring will trigger on these components.

That should look like this:

@Override
public void doAfterCompose(Component comp) {
    ListModelList<DocumentoVinculado> modelo = new ListModelList<>(crearLista());
    myListbox.setModel(modelo);
    myListbox.setItemRenderer(new NewFileRender());
}

2nd, if you move from genericForwardComposer to SelectorComposer, you can actually tell the composer to rewire itself "on demand" by using the Selectors.wireComponents method. Of course, that's only valid if your application can be refactored for this change.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM