-
FEATURED COMPONENTS
First time here? Check out the FAQ!
Hi all, first great work guys and thank’s the precious help. I am new to ZK, and I’m experimenting it in order to adopt it for our future projects, actually I’m facing a problem while achieving this pattern I have a classical model for invoicing system (aka Invoice, Invoice-Item and Product) *** **** **** * Invoice ----------- n -- Invoice-Item * -- n -------------- * Product * *** **** **** Ok now I’m trying to make a zk window for editing a invoice, that window have the following parts: - A header for the invoice info and the business partner info - The invoiced products area, which contains a “Listbox” with “inplace” edition components (a Bandbox for products selection, textboxes for quantities and prices editing. My problem is that when I click a button to add a new InvoiceItem to the Invoice, the event handler "onNew$InvoiceItemsListbox" creates a new InvoiceItem and put it into the invoice (model is updated), but the Listbox does not shows a new “Item” (aka the changes are not reflected in the Listbox), so what’s wrong with my code ?
here is the code..
package org.ah.ui.zk.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Execution;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.ForwardEvent;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zkplus.databind.AnnotateDataBinder;
import org.zkoss.zkplus.databind.BindingListModelList;
import org.zkoss.zkplus.spring.SpringUtil;
import org.zkoss.zul.Button;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Window;
import org.ah.model.Invoice;
import org.ah.model.InvoiceItems;
import org.ah.service.IInvoiceService;
@SuppressWarnings({ "rawtypes", "serial" })
public class InvoiceCRUDController extends GenericForwardComposer{
@WireVariable
private IInvoiceService CRUDService;
private Invoice selectedInvoice;
private InvoiceItems selectedInvoiceItems;
private String recordMode;
private AnnotateDataBinder binder;
protected Window invoiceCRUD; // autowired
protected Button save; // autowired
protected Button cancel; // autowired
private Window parentWindow;
private boolean makeAsReadOnly;
@SuppressWarnings("unchecked")
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
CRUDService = (IInvoiceService) SpringUtil.getBean("InvoiceCRUDService");
this.self.setAttribute("controller", this, false);
final Execution execution = Executions.getCurrent();
setSelectedInvoice((Fonction) execution.getArg().get("selectedRecord"));
setRecordMode((String) execution.getArg().get("recordMode"));
setParentWindow((Window) execution.getArg().get("parentWindow"));
}
public void onCreate(Event event) {
this.binder = (AnnotateDataBinder) event.getTarget().getAttribute(
"binder", true);
}
public void onClick$save(Event event) {
Map<String, Object> args = new HashMap<String, Object>();
binder.saveAll();
CRUDService.save(this.selectedInvoice);
fonctionCRUD.detach();
args.put("selectedRecord", getSelectedInvoice());
args.put("recordMode", this.recordMode);
Events.sendEvent(new Event("onSaved", parentWindow,args));
}
public void onClick$cancel(Event event) {
fonctionCRUD.detach();
}
public Invoice getSelectedInvoice() {
return selectedInvoice;
}
public void setSelectedInvoice(Invoice selectedFonction) {
this.selectedInvoice = selectedInvoice;
}
public String getRecordMode() {
return recordMode;
}
public void setRecordMode(String recordMode) {
this.recordMode = recordMode;
}
public Window getParentWindow() {
return parentWindow;
}
public void setParentWindow(Window parentWindow) {
this.parentWindow = parentWindow;
}
public boolean isMakeAsReadOnly() {
return makeAsReadOnly;
}
public void setMakeAsReadOnly(boolean makeAsReadOnly) {
this.makeAsReadOnly = makeAsReadOnly;
}
/*
* add a new item to the selected Invoice
*
*/
public void onNew$InvoiceItemsListbox(ForwardEvent evt) {
// the model is updated but the listbox does not shows a new ListItem !!!
v pb = new InvoiceItems();
pb.setInvoice(this.getSelectedInvoice());
this.getSelectedInvoice().getInvoiceItems().add(pb);
}
/**
* @return the selectedFonctionElementsPaie
*/
public InvoiceItems getSelectedv() {
return selectedInvoiceItems;
}
/**
* @param selectedInvoiceItems the selectedInvoiceItems to set
*/
public void setSelectedInvoiceItems(
InvoiceItems selectedInvoiceItems) {
this.selectedInvoiceItems = selectedInvoiceItems;
}
}
2) the zul file
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" arg0="./invoiceCRUD" ?>
<zk>
<window title="Invoice" id="invoiceCRUD" border="normal"
width="50%"
apply="org.ah.ui.zk.controller.invoiceCRUDController"
mode="modal" maximizable="false" closable="true" sizable="true">
<panel width="100%">
<panelchildren>
<tabbox id="tabBoxIndexCenter" width="100%"
style="padding: 0px">
<tabs id="tabsIndexCenter">
<tab label="Invoice Header" />
<tab label="Invoied Products" />
</tabs>
<tabpanels>
<tabpanel>
<separator />
<grid>
<columns>
<column></column>
<column></column>
</columns>
<rows>
<row>
<label
value="${c:l('invoice.number')}" />
<textbox id="invoiceNumber"
hflex="1"
value="@{controller.selectedInvoice.invoiceNumber, access='both', save-when='none'}"
readonly="@{controller.makeAsReadOnly}" mold="rounded"
width="100%" />
</row>
<row>
<label
value="${c:l('invoice.date')}" />
<textbox id="date"
hflex="1"
value="@{controller.selectedinvoice.date, access='both', save-when='none'}"
readonly="@{controller.makeAsReadOnly}" mold="rounded"
width="100%" />
</row>
</rows>
</grid>
</tabpanel>
<tabpanel>
<panel width="100%">
<panelchildren>
<div width="100%">
<div width="100%">
<toolbar
id="tb_invoiceItemsListe" sclass="vista"
height="20px" align="end">
<toolbarbutton
id="tbb_invoiceItems_new"
tooltiptext="${c:l('crud.new.tooltip')}"
image="/widgets/menu/toolbar/img/new.gif"
forward="onClick=InvoiceItemsListbox.onNew" />
<toolbarbutton
id="tbb_invoiceItems_rem"
tooltiptext="${c:l('crud.rem.tooltip')}"
image="/widgets/menu/toolbar/img/rem.gif"
forward="onClick=InvoiceItemsListbox.onDelete" />
<toolbarbutton
id="tbb_invoiceItems_print"
tooltiptext="${c:l('crud.print.tooltip')}"
image="/widgets/menu/toolbar/img/print.gif"
forward="onClick=InvoiceItemsListbox.onPrint" />
</toolbar>
</div>
<separator />
<listbox
id="InvoiceItemsListbox"
model="@{controller.selectedInvoice.invoiceItems}"
selectedItem="@{controller.selectedInvoiceItems}"
multiple="false"
emptyMessage="${c:l('MSG.NO_ITEMS')}" mold="paging"
pageSize="20" sizedByContent="false" nonselectableTags="">
<listhead
sizable="true">
<listheader
label="products" />
<listheader
label="qte" />
<listheader
label="price" />
</listhead>
<listitem
self="@{each='invoiceItems'}"
value="@{invoiceItems}">
<listcell>
<bandbox
id="bbInvoiceItem" inplace="true"
value="@{InvoiceItems.product.productlabel}"
constraint="no empty" mold="rounded" autodrop="true"
apply="org.ah.ui.zk.controller.InvoiceItemsController"
width="100%">
<bandpopup>
<listbox
height="250px" width="350px" id="ProductListbox"
multiple="false"
emptyMessage="no product found"
mold="paging" pageSize="20" sizedByContent="false"
onSelect="self.parent.parent.value = self.selectedItem.label; self.parent.parent.close();">
<template
name="model">
<listitem>
<listcell
label="${each.productNumber}" />
<listcell
label="${each.productLabel}" />
</listitem>
</template>
</listbox>
</bandpopup>
</bandbox>
</listcell>
<listcell>
<textbox
inplace="true" value="@{invoiceItems.qte}"
mold="rounded" width="100%" />
</listcell>
<listcell>
<intbox
inplace="true" value="@{invoiceItems.price}"
mold="rounded" width="100%" />
</listcell>
</listitem>
</listbox>
</div>
</panelchildren>
</panel>
</tabpanel>
</tabpanels>
</tabbox>
</panelchildren>
</panel>
<separator />
<separator />
<div align="right">
<button label="${c:l('crud.save.lbl')}" id="save"
width="73px" />
<button label="${c:l('crud.cancel.lbl')}" id="cancel"
width="73px" />
</div>
<separator />
</window>
</zk>
As far as i can see you are using the 'old' approach of data binding. This means that you have to tell to the data binder when to synchronize UI and models. So, first of all autowire the listbox in your java code:
protected Listbox InvoiceItemsListbox;
and then try the following:
public void onNew$InvoiceItemsListbox(ForwardEvent evt) {
// the model is updated but the listbox does not shows a new ListItem !!!
v pb = new InvoiceItems();
pb.setInvoice(this.getSelectedInvoice());
this.getSelectedInvoice().getInvoiceItems().add(pb);
/*
* If you were using the MVVM pattern this would be achieved using
* the @NotifyChange declaration
*/
binder.loadComponent( InvoiceItemsListbox );
}
Also, if you want to update the whole page, even those components which are not auto-wired, you may do:
binder.loadAll();
/costas
Asked: 2013-07-19 18:59:45 +0800
Seen: 36 times
Last updated: Jul 22 '13