0

pass back data from a modal window to main window [closed]

asked 2011-10-18 10:03:22 +0800

jchiu gravatar image jchiu
30 2

updated 2011-10-18 10:07:13 +0800

Hi,
I have a main windows with a list box to show a list of records. When a row is selected, another modal popup window for editing the selected record will be triggered by right click the context menu item. I have databinding in the main window and I expect all changes made in the modal popup window will be reflected back to the main window. Unfortunately, it is not the case. Can I use any databinding concepts to tackle this problem ?

Appreciate anyone could give me a hand and resolve the subject problem. Million Thanks. / Jonathan

Main Window

<?page title="School" contentType="text/html;charset=UTF-8"?>
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
<zk>
	<window id="schoolctlview" title="School" border="normal"
		apply="model.SchoolViewCtl">
		<listbox id="lbSchool" mold="paging" pageSize="10"
			selectedItem="@{selected}" context="GridMenu">
			<auxhead sclass="category-center">
				<auxheader colspan="1">
					<image src="/img/funnel.png" />
					<textbox id="filter21" />
				</auxheader>
				<auxheader colspan="1">
					<image src="/img/funnel.png" />
					<textbox id="filter22" />
				</auxheader>
				<auxheader colspan="1">
					<image src="/img/funnel.png" />
					<textbox id="filter23" />
				</auxheader>
				<auxheader colspan="1">
					<image src="/img/funnel.png" />
					<textbox id="filter24" />
				</auxheader>
				<auxheader colspan="1">
					<image src="/img/funnel.png" />
					<textbox id="filter25" />
				</auxheader>
			</auxhead>
			<listhead>
				<listheader label="School Code" />
				<listheader label="School Name" />
				<listheader label="Tel" />
				<listheader label="Fax" />
				<listheader label="Email" />
			</listhead>
		</listbox>
		<menupopup id="GridMenu">
			<menuitem id="mitemView" label="View" />
		</menupopup>
	</window>
</zk>

Modal Popup Window
<?page id="pageSchool"title="School" contentType="text/html;charset=UTF-8"?>
<window id="wSchool" title="School" border="normal" mode="modal">
	<zscript><![CDATA[
		import model.School;
		School sch = (School)execution.getArg().get("data");
	]]></zscript>
	<label value="Name:" />
	<textbox id="nameTb" value="@{sch.school_name}"/>
	<button label="OK" xmlns:w="http://www.zkoss.org/2005/zk/client" w:onClick="this.$f('wSchool').fire('onClose');"/>
</window>

Control

package model;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.SuspendNotAllowedException;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zkplus.databind.AnnotateDataBinder;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.Menuitem;
import org.zkoss.zul.Window;

public class SchoolViewCtl extends GenericForwardComposer {
	private Listbox lbSchool;
	private Menuitem mitemView;
	private AnnotateDataBinder binder;

	@Override
	public void doAfterCompose(Component comp) throws Exception {
		super.doAfterCompose(comp);
		List allSchools = new SchoolDAO().findAll();
		ListModelList model = new ListModelList(allSchools);
		model.addSelection(allSchools.get(0));
		lbSchool.setModel(model);
		lbSchool.setItemRenderer(new ListitemRenderer() {
			public void render(Listitem listItem, Object data) throws Exception {
				final School sch = (School) data;
				listItem.setValue(sch);
				new Listcell(sch.getSchool_code()).setParent(listItem);
				new Listcell(sch.getSchool_name()).setParent(listItem);
				new Listcell(sch.getTel()).setParent(listItem);
				new Listcell(sch.getFax()).setParent(listItem);
				new Listcell(sch.getEmail()).setParent(listItem);
			}
		});
	}

	public void onClick$mitemView() {
		Window wSchool = new Window();
		Map data = new HashMap();
		data.put("data", (School)lbSchool.getSelectedItem().getValue());
		wSchool = (Window)Executions.getCurrent().createComponents("school.zul", self, data);
		binder = new AnnotateDataBinder(wSchool);
		binder.loadAll();
	}
}

delete flag offensive retag edit

The question has been closed for the following reason "too localized" by sjoshi
close date 2013-02-08 05:54:24

11 Replies

Sort by » oldest newest

answered 2011-10-18 10:46:20 +0800

cyiannoulis gravatar image cyiannoulis
1191 10

Hi Jonathan,

I 'm not sure if i understand correctly so let me recap. The school.zul is the modal dialog which is responsible to edit a school. As long as the user edits the selected school, you suppose that the execution in the SchoolViewCtl composer is paused and after closing the dialog the execution will continue to the following lines:

binder = new AnnotateDataBinder(wSchool);
binder.loadAll();

Is that the case?

1. The only way to force execution pausing while working in a modal dialog is to declare the <disable-event-thread> parameter inside the zk.xml. But i would not recommend that! After all there is a reason it is disabled by default since zk 5.0

2. A proper and simple way would be to pass the SchoolViewCtl itself to the dialog as parameter inside the data Map. After finishing editing, the modal dialog should invoke a method in the SchoolViewCtl (lets say "updateListView()" ) to reflect the changes back to the list.

hope that helps
/costas

link publish delete flag offensive edit

answered 2011-10-18 11:27:25 +0800

jchiu gravatar image jchiu
30 2

Hi Costas,

Million thanks for your reply. Your understanding to my question is exactly the same what I want to achieve. I am really interested in your point 2. Appreciate if you would share some lights by illustrating the handshake of data Map & updateListView(). I actually very green in developing using ZK and I found using ListitemRenderer from reference manual but not quite sure after I close the modal dialog how to refresh the new values captured.

Once again. Many thanks for your time and grateful to have your further guidence.

Jonathan

link publish delete flag offensive edit

answered 2011-10-19 03:23:05 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

Hi jchiu,

look here.

best
Stephan

link publish delete flag offensive edit

answered 2011-10-19 07:18:28 +0800

cyiannoulis gravatar image cyiannoulis
1191 10

Jonathan,

You will get all you need if you follow Stephan's links... Actually these are more or less the same links i followed to learn zk (thx stephan!)

Anyway if you are more impatient you can read below a fully working example of how to edit a list using an edit dialog.

The main schools list page:

<?page title="Schools" contentType="text/html;charset=UTF-8"?>
<zk>
<window id="winSchools" title="Schools" border="normal" height="100%" width="100%"
		apply="schools.SchoolsListController">
	
  <vlayout>
	
	<toolbar>
		<toolbarbutton id="tbtnEdit" label="Edit" image="/images/tb-edit.png" />
		<toolbarbutton id="tbtnRemove" label="Remove" image="/images/tb-delete.png" />
	</toolbar>
	
	<listbox id="lbSchools" model="@{ controller.schools }" selectedItem="@{ controller.selectedSchool }" vflex="true">
	
		<listhead sizable="true">
			<listheader label="Code" width="50px" />
			<listheader label="Name" width="150px"/>
			<listheader label="Address" width="200px"/>	
		</listhead>

		<listitem self="@{each='school'}" value="@{school}" >					
			<listcell label="@{school.code}" />
			<listcell label="@{school.name}" />
			<listcell label="@{school.address}" />
		</listitem>

	</listbox>
	
  </vlayout>
	
</window>
</zk>

The controller of the main schools page:

package schools;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.SuspendNotAllowedException;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zkplus.databind.AnnotateDataBinder;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.api.Listbox;
import org.zkoss.zul.api.Window;

public class SchoolsListController extends GenericForwardComposer {

	private static final long serialVersionUID = 1L;
	
	private AnnotateDataBinder binder;
	
	private Window winSchools;

	private Listbox lbSchools;
	private List<School> schools;
	private School selectedSchool;
	
	@Override
	public void doAfterCompose(Component comp) throws Exception {
		
		try {
			super.doAfterCompose(comp);
		} 
		catch (Exception e) {
			e.printStackTrace();
		}

		/*
		 * create the data binder and bind this composer as the base model bean 
		 */
		binder = new AnnotateDataBinder(comp);
		binder.bindBean("controller", this);
		
		/*
		 * populate data models
		 */
		createModels();
		
	}
	
	public void onCreate(Event event) {
		
		/*
		 * populate ui with data 
		 */
		binder.loadAll();
	}
	
	/*
	 * Create some mock data models  
	 */
	private void createModels() {
		
		schools = new ArrayList<School>();
		
		schools.add(new School("1", "1st school", "address-1"));
		schools.add(new School("2", "2nd school", "address-2"));
		schools.add(new School("3", "3rd school", "address-3"));
		schools.add(new School("4", "4th school", "address-4"));
		schools.add(new School("5", "5th school", "address-5"));
		schools.add(new School("6", "6th school", "address-6"));
		schools.add(new School("7", "7th school", "address-7"));
		schools.add(new School("8", "8th school", "address-8"));
		schools.add(new School("9", "9th school", "address-9"));
	}
	
	/**
	 * Event handler method triggered when the "edit" toolbar button is pressed 
	 */
	public void onClick$tbtnEdit() {
		
		if (selectedSchool == null) {
			try {
				Messagebox.show("You have to select a school from the list first.", "Error", Messagebox.OK, Messagebox.ERROR);
			} 
			catch (InterruptedException e) {
				e.printStackTrace();
			}
			return;
		}

		Map<String, Object> parameters = new HashMap<String, Object>();
		parameters.put("SELECTED_SCHOOL", selectedSchool);
		parameters.put("PARENT_WINDOW", winSchools);
		Window editDialog = (Window) Executions.createComponents("/schools/SchoolEditor.zul", winSchools, parameters);
		
		try {
			editDialog.doModal();
		} 
		catch (SuspendNotAllowedException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * This method is actualy an event handler triggered only from the edit dialog
	 * and it is responsible to reflect the data changes made to the list.
	 */
	public void onSchoolSaved() {

		int index = lbSchools.getSelectedIndex();
		
		if (index == -1)
			return;
		
		binder.loadComponent( lbSchools.getItemAtIndexApi(index) );
	}
	
	/**
	 * Event handler method triggered when the "remove" toolbar button is pressed 
	 */
	public void onClick$tbtnRemove() {
		
		if (selectedSchool == null) {
			try {
				Messagebox.show("You have to select a school from the list first.", "Error", Messagebox.OK, Messagebox.ERROR);
			} 
			catch (InterruptedException e) {
				e.printStackTrace();
			}
			return;
		}
			
		try {
			
			/*
			 * This event listener is needed to catch the response given by the user in the confirmation dialog  
			 */
			EventListener eventListener = new EventListener() {
				
				@Override
				public void onEvent(Event event) throws Exception {
					 switch (((Integer) event.getData()).intValue()) {
	                    case Messagebox.OK:
	                        deleteSchool();
	                        break;
					 }
				}
			};
			
			Messagebox.show("Are you sure you want to delete " + selectedSchool.getName() +  "?", 
							"Warning", 
							Messagebox.OK | Messagebox.CANCEL, 
							Messagebox.QUESTION,
							eventListener);
		} 
		catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Delete the selected school 
	 */
	private void deleteSchool() {
		schools.remove(selectedSchool);
		selectedSchool = null;
		binder.loadComponent(lbSchools);
	}
	

	public AnnotateDataBinder getBinder() {
		return binder;
	}

	public void setBinder(AnnotateDataBinder binder) {
		this.binder = binder;
	}

	public List<School> getSchools() {
		return schools;
	}

	public void setSchools(List<School> schools) {
		this.schools = schools;
	}

	public School getSelectedSchool() {
		return selectedSchool;
	}

	public void setSelectedSchool(School selectedSchool) {
		this.selectedSchool = selectedSchool;
	}
	
}

The edit dialog page:

<?page title="Schools" contentType="text/html;charset=UTF-8"?>
<zk>
<window id="winEditor" title="School Editor" border="normal" height="350px" width="400px" closable="true"
		apply="schools.SchoolEditorController">
	
  <vlayout>
	
	<toolbar>
		<toolbarbutton id="tbtnSave" label="Save" image="/images/tb-save.png" />
		<toolbarbutton id="tbtnExit" label="Exit" image="/images/tb-exit.png" />
	</toolbar>

	<grid>
		<columns>
			<column width="100px"/>
			<column/>
		</columns>
		<rows>
			<row>
				<label value="Code" />
				<textbox value="@{ controller.selectedSchool.code, access='both', save-when='none' }"/>
			</row>
			<row>
				<label value="Name" />
				<textbox value="@{ controller.selectedSchool.name, access='both', save-when='none' }"/>
			</row>
			<row>
				<label value="Address" />
				<textbox value="@{ controller.selectedSchool.address, access='both', save-when='none' }"/>
			</row>
		</rows>
	</grid>	
	
  </vlayout>
	
</window>
</zk>

And finally the school editor composer:

package schools;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zkplus.databind.AnnotateDataBinder;
import org.zkoss.zul.api.Window;

public class SchoolEditorController extends GenericForwardComposer {

	private static final long serialVersionUID = 1L;
	
	private AnnotateDataBinder binder;

	private School selectedSchool;
	
	private Window parentWindow;
	
	private Window winEditor;
	
	@Override
	public void doAfterCompose(Component comp) throws Exception {
		
		try {
			super.doAfterCompose(comp);
		} 
		catch (Exception e) {
			e.printStackTrace();
		}

		/*
		 * create the data binder and bind this composer as the base model bean 
		 */
		binder = new AnnotateDataBinder(comp);
		binder.bindBean("controller", this);
		
		/*
		 * retrieve parameters passed here by the caller
		 */
		selectedSchool = (School)arg.get("SELECTED_SCHOOL");
		parentWindow = (Window)arg.get("PARENT_WINDOW"); 
	}
	
	public void onCreate(Event event) {
		
		/*
		 * populate ui with data 
		 */
		binder.loadAll();
	}
	
	/**
	 * Event handler for closing this dialog using the "exit" toolbar button 
	 */
	public void onClick$tbtnExit() {
		winEditor.detach();
	}
	
	/**
	 * Event handler for saving the model values
	 */
	public void onClick$tbtnSave() {
		binder.saveAll();
		winEditor.detach();
		Events.sendEvent(new Event("onSchoolSaved", parentWindow));
	}
	
	public AnnotateDataBinder getBinder() {
		return binder;
	}

	public void setBinder(AnnotateDataBinder binder) {
		this.binder = binder;
	}

	public School getSelectedSchool() {
		return selectedSchool;
	}

	public void setSelectedSchool(School selectedSchool) {
		this.selectedSchool = selectedSchool;
	}
	
}

Hope that helps

/Costas

link publish delete flag offensive edit

answered 2011-10-19 19:16:18 +0800

jchiu gravatar image jchiu
30 2

Stephen & Costas, many thanks for your help! Its really helpful and much appreciate both of your time and sharing. Very clear!

Regards,
Jonathan

link publish delete flag offensive edit

answered 2011-10-22 03:27:27 +0800

jchiu gravatar image jchiu
30 2

wondering a trivial question. based on the code Costas provided, i try to add a new button to create a new school. This i thouht should be very simple by setting selectedSchool to new School(). However, no matter what had been entered into Modal Window, when I click save button, it always return a empty instance of School back to SchoolsListController. Any code / concepts I missed here? Really appreciate further assistance and I had been sitting and researching internet for 2 days. Many Thanks. / Jonathan.

link publish delete flag offensive edit

answered 2011-10-22 03:57:51 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

updated 2011-10-22 04:01:51 +0800

only Pseudo-Code:

  void doNew() {
      School school = new School();
      setSelectedSchool(school);
}

You must told the binder to save the UI components data to the bean properties.
 (because in costas sample zul file is standing ... save-when='none'...)

  void doSave(){
       getBinder.saveAll();
       myDataBase.saveMyBeanData(getSelectedSchool());
}

best
Stephan

PS: Try to debug the article module in ZKsample2.
Online-demo: http://www.zk-web.de/zksample2/

link publish delete flag offensive edit

answered 2011-10-26 08:38:03 +0800

jchiu gravatar image jchiu
30 2

Stephan,

Perfect! Thanks for your explaination.

Jonathan

link publish delete flag offensive edit

answered 2012-08-06 08:58:29 +0800

tita gravatar image tita
12

Hi,
I have a problem similar to jchiu one.
I have a window that opens a modal by clicking a button; the modal contains a form and I want that after I fill in all the form, the modal closes itself and results are shown in the window below. In reality nothing of that happens and I have null pointer exception. I already read all post about this topic and I also studied terrytornado examples.... but nothing!
I really hope that someone could help me...

attivita.zul

<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c" ?>
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
<vlayout>
	<label sclass="title" value="${labels.attivita}" />
	<window id="attivitaWindow" sclass="cardSys" border="none"
		apply="org.zkoss.bind.BindComposer" 
		viewModel="@id('vm') @init('it.iks.smash.web.controller.AttivitaVM')" >
		
		<!-- bottone per aprire la modal window della ricerca -->
		<div id="button" apply="it.iks.smash.web.controller.AttivitaVM">
			<button id="apriModal" label="Apri modal window" />
		</div>

...

AttivitaVM.java controller for attivita.zul

@VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class)
public class AttivitaVM extends SelectorComposer<Component>{

	private static final long serialVersionUID = 1L;
	
	static Logger log = Logger.getLogger(AttivitaVM.class.getName());
	
	@WireVariable(value = "attivitaService")
	private IAttivitaService attivitaService;
	private List<AttivitaAbstract> listAttivita;
	
	private AttivitaAbstract selectedAttivita;
	private AttivitaDettaglio attivitaDettaglio;
	
	@Wire
	private Textbox userTextBox;
	@Wire
	private Textbox cosdiaTextBox;
	@Wire
	private Listbox attivita;
	
	private AnnotateDataBinder binder;
	
	public Listbox getAttivita() {
		return attivita;
	}	
	
	@Wire
	private Window attivitaWindow;
	
	private QueryManagerVM queryManagerController;

	
	public void setAttivita(Listbox attivita) {
		this.attivita = attivita;
	}

	@Listen("onClick = #apriModal")
	public void showModal(Event e) {
		log.info("@Listen(onClick=#apriModal)");
		Window queryManager= new Window();
		final HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("AttivitaVM", this);
	        queryManager = (Window)Executions.getCurrent().createComponents("/WEB-INF/view/query-manager.zul", attivitaWindow, map);
	        queryManager.doModal();
	        binder = new AnnotateDataBinder(queryManager);
		binder.loadAll();
	}
.....

query-manager.zul: the zul of the modal window

<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c" ?>
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?> 
<window id="queryManagerModal" closable="true" position="center,center" 
	apply="org.zkoss.bind.BindComposer" title="Query Manager" border="normal" 
    viewModel="@id('vm') @init('it.iks.smash.web.controller.QueryManagerVM')"
    validationMessage="@id('vmsg')"
    form="@id('fx') @load(vm.queryManagerBean) @save(vm.queryManagerBean, before='eseguiQuery') "  > 
   <vlayout>

....

<div id="button" apply="it.iks.smash.web.controller.QueryManagerVM" >
		<button id="eseguiQuery" label="Ricerca" onClick="@Command('eseguiQuery')"/>
	</div>	
	</vlayout>
</window>

QueryManagerVM.java: controller for the modal window query-manager.zul

@VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class)
public class QueryManagerVM extends SelectorComposer<Component>{
	

	private static final long serialVersionUID = 1L;
	static Logger log = Logger.getLogger(AttivitaVM.class.getName());
	@Wire("#queryManagerModal")
	private Window queryManagerModal;
	
	@WireVariable(value = "attivitaService")
	private IAttivitaService attivitaService;
	
	private AttivitaVM controllerAttivita;//controller della pagina delle attività

	private QueryManager queryManagerBean=new QueryManager();
	
....
        @Init
	public void init(@ExecutionArgParam("AttivitaVM") AttivitaVM controllerAttivita) {
		log.info("init:: inizializzazione");
		setControllerAttivita(controllerAttivita);
		log.info("doAfterCompose(Component comp):: setControllerAttivita()");
		// la lista attività ha il controller della modalwindow
		getControllerAttivita().setQueryManagerController(this);
		log.info("doAfterCompose(Component comp):: getControllerAttivita()");
	}
	
	@Listen("onClick=#eseguiQuery")
	public void search(){
		log.info("onClick$eseguiQuery()");
		if(queryManagerBean.getTextboxUser().isEmpty())
			log.info("textboxuser vuota");
		log.info("queryManagerBean.getTextboxUser() "+queryManagerBean.getTextboxUser());
		HashMap<String, Condizione> condizioni=new HashMap<String, Condizione>();
		
		condizioni=(HashMap<String, Condizione>) searchCheckTipoAttivita();
		condizioni.putAll(searchCampiRicerca());
		condizioni.putAll(searchBonificoRicerca());
		if(condizioni.isEmpty())
			log.info("onClick$eseguiQuery:: condizioni empty");
		else
			log.info("onClick$eseguiQuery:: condizioni"+condizioni.keySet().toString());
		List<AttivitaAbstract> listAttivita=attivitaService.ricerca(condizioni);

		for(int i=0; i<listAttivita.size(); i++){
			log.info("search():: listAttività["+i+"]: "+listAttivita.get(i)+", ");
		}
		//getControllerAttivita().setLista(listAttivita);
        queryManagerModal.detach();
	}

.....
        

Thank you to anybody that could help me

link publish delete flag offensive edit

answered 2012-08-10 08:48:17 +0800

jimmyshiau gravatar image jimmyshiau
4921 5
http://www.zkoss.org/ ZK Team

Hi tita
you can refer to
http://www.zkoss.org/forum/listComment/19829-ZK-MVVM-Modal-Window

link publish delete flag offensive edit

Question tools

Follow
2 followers

RSS

Stats

Asked: 2011-10-18 10:03:22 +0800

Seen: 2,257 times

Last updated: Feb 06 '13

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More