0

dynamic Tabbox

asked 2010-04-14 05:47:02 +0800

dickdastardly gravatar image dickdastardly
168 1 5

OK

I am trying to use a dynamic Tabbox on a zul page

I have a java ArrayList to accept childrens details and want each tab in the tabbox to be associated with a different child, using the selectedindex
of the tab to drive the arraylist index.

I have a a composer that looks like this

package com.pre.school.zk.composer;

import java.util.List;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Components;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.ForwardEvent;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zkplus.databind.AnnotateDataBinder;
import org.zkoss.zul.Button;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.Tab;
import org.zkoss.zul.Tabbox;
import org.zkoss.zul.Tabpanel;
import org.zkoss.zul.Tabpanels;
import org.zkoss.zul.Tabs;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.impl.InputElement;

public class ValidationComposer extends GenericForwardComposer {

	private static final long serialVersionUID = -1870580858482873118L;

	private AnnotateDataBinder binder;
	private Component childComponent;
	public boolean allFieldsValid = true;
	private Button nextButton;
	private Tabbox childrenTabbox;

	@Override
	public void doAfterCompose(Component comp) throws Exception {
		super.doAfterCompose(comp);
		addChildrenTab();
		addChildrenTab();

	}

	public void onCreate$win(ForwardEvent event) {
		binder = (AnnotateDataBinder) event.getTarget().getAttributeOrFellow("binder", true);
		nextButton.setDisabled(true);

	}

	@SuppressWarnings("unchecked")
	public void onOK$win(ForwardEvent event) {
		List childComponents;

		childComponents = event.getTarget().getChildren();

		childComponent = (Component) childComponents.get(0);

		if (getChildren(childComponent)) {
			nextButton.setDisabled(false);
		} else {
			nextButton.setDisabled(true);
		}

		binder.saveAll();
		addChildrenTab();

	}

	private void addChildrenTab() {
		Tabpanel tabpanel = new Tabpanel();
		Executions.createComponents("childTAB.zul", tabpanel, null);
		Tab tab = new Tab("Another Child");
		
		if (childrenTabbox.getTabs() == null){
			childrenTabbox.appendChild(new Tabs());			
			childrenTabbox.appendChild(new Tabpanels());			
		}
			
		childrenTabbox.getTabs().appendChild(tab);
		childrenTabbox.getTabpanels().appendChild(tabpanel);

	}

	@SuppressWarnings("unchecked")
	private boolean getChildren(Component theseChildren) {

		List<Component> componentList;

		if (theseChildren == null) {
			return false;
		}

		componentList = (List<Component>) theseChildren.getChildren();

		if ((componentList == null) || (componentList.size() == 0)) {
			return allFieldsValid;
		}

		for (Component myComponent : componentList) {

			if (myComponent instanceof Textbox) {
				((Textbox) myComponent).getValue();
			} else if (myComponent instanceof Datebox) {
				((Datebox) myComponent).getValue();
			}

			if (myComponent instanceof InputElement) {
				if (allFieldsValid) {
					allFieldsValid = ((InputElement) myComponent).isValid();
				}
			}

			getChildren(myComponent);

		}

		return allFieldsValid;

	}

}

my childTAB.zul sub page looks like this

<grid fixedLayout="false">
	<columns>
		<column label="" width="15%" />
		<column label="" width="30%" />
	</columns>
	<rows>
		<row>
			<label value="Gender" />
			<combobox model="@{preSchoolReferenceData.genders}"
				selectedItem="@{family.child.gender}" readonly="true"
				mold="rounded">
				<comboitem self="@{each='childGender'}"
					label="@{childGender.description}">
				</comboitem>
			</combobox>
		</row>
		<row>
			<label value="First Name" width="100px" />
			<textbox constraint="no empty"
				value="@{family.child.firstName, save-when='self.onBlur'}"
				width="190px" />
		</row>
		<row>
			<label value="Middle Name" width="100px" />
			<textbox
				value="@{family.child.middleName, save-when='self.onBlur'}"
				width="190px" />
		</row>
		<row>
			<label value="Surname" width="100px" />
			<textbox constraint="no empty"
				value="@{family.child.surname, save-when='self.onBlur'}"
				width="190px" />
		</row>
		<row>
			Date Of Birth:
			<hbox>
				<datebox onSelection="self.close()"
					readonly="false" mold="rounded"
					constraint="no empty, no future: Please enter a valid Date Of Birth"
					format="dd/MM/yyyy"
					value="@{family.child.dateOfBirth, save-when='self.onChange'}" />
			</hbox>
		</row>
		<row>
			<label value="Language" />
			<combobox model="@{preSchoolReferenceData.languages}"
				selectedItem="@{family.child.language}" readonly="true"
				mold="rounded">
				<comboitem self="@{each='childLanguage'}"
					label="@{childLanguage.description}">
				</comboitem>
			</combobox>
		</row>
		<row>
			<label value="Ethnic Group" />
			<combobox model="@{preSchoolReferenceData.ethnicGroups}"
				selectedItem="@{family.child.ethnicGroup}" readonly="true"
				mold="rounded">
				<comboitem self="@{each='childEthnicGroup'}"
					label="@{childEthnicGroup.description}">
				</comboitem>
			</combobox>
		</row>
		<row>
			<label value="Religion" />
			<combobox model="@{preSchoolReferenceData.religions}"
				selectedItem="@{family.child.religion}" readonly="true"
				mold="rounded">
				<comboitem self="@{each='childReligion'}"
					label="@{childReligion.description}">
				</comboitem>
			</combobox>
		</row>
	</rows>
</grid>

My first test was successful and added my initial sing tab to the tabbox and all data binding works fine
the only thing i dont have working at this single tab stage is the selectedindex from the Tab driving the arraylist of children.

My second test failed. What i tried was to call

addChildrenTab();
in
public void onOK$win(ForwardEvent event) {}

the second tab was displayed however none of the databinding had happend so my drop downs didnt have any data in them and any text
i entered in the input fields was ignored. I think this is i have added a new tab and not run "doaftercompose()" although i am not sure i am allowed to do that!

My third test...

just as a quick and dirty test I added two childrens tabs in doaftercompose method

The good news is the comboboxes have been bound to the backing data sources and have drop down content
the bad news is i get this exception

Cannot find associated CollectionItem=<Comboitem z_h4_15>, binding=[binder:[email protected], comp:<Comboitem z_h4_15>, attr:label, expr:childLanguage.description, load-when:null, save-when:null, load-after:null, save-after:null, load:true, save:false, converter:null], collectionComp=<Comboitem @z_h4_t3_0>

any ideas how i get passed this?

is what i am trying an acceptable approach?

Thanks in advance

Dick Dastardly

delete flag offensive retag edit

4 Replies

Sort by ยป oldest newest

answered 2010-04-14 09:06:35 +0800

dickdastardly gravatar image dickdastardly
168 1 5

whats the cleanest way to set the arraylist index to the selected tab tabindex?

I cannot mix @{} with ${arg.tabindex} so how can it be done?

link publish delete flag offensive edit

answered 2010-04-19 20:32:54 +0800

ashishd gravatar image ashishd flag of Taiwan
1972 6

Hi dickdastardly,
Can you give me your main zul file to which your composer is applied? It will be more easier for me reproduce your problem at my end.

Thanks
- Ashish

link publish delete flag offensive edit

answered 2010-04-20 13:09:50 +0800

dickdastardly gravatar image dickdastardly
168 1 5

ashishd

thanks for looking at this


my main page is

<?xml version="1.0" encoding="UTF-8" ?>
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
<?page title="family"?>
<zk>
	<window id="win" title="B U R H A M  PreSchool" border="normal"
		width="100%" height="100%"
		apply="com.pre.school.zk.composer.ValidationComposer">
		<borderlayout height="100%">
			<north size="30%" flex="true" maxsize="250"
				splittable="true" collapsible="true">
			</north>
			<center border="normal">
				<borderlayout>
					<west title="Parents/Gaurdians" size="33%"
						flex="true" maxsize="300" splittable="true" collapsible="true">
						<div>
							<tabbox id="parentTabbox">
								<tabs>
									<tab label="Mother" />
									<tab label="Father" />
								</tabs>
								<tabpanels>
									<tabpanel>
										<grid fixedLayout="false">
											<columns>
												<column label=""
													width="25%" />
												<column label=""
													width="25%" />
											</columns>
											<rows>
												<row>
													<label
														value="Title" />
													<combobox
														model="@{preSchoolReferenceData.titles}"
														selectedItem="@{family.mother.title}" readonly="true"
														mold="rounded">
														<comboitem
															self="@{each='motherTitle'}"
															label="@{motherTitle.description}">
														</comboitem>
													</combobox>
												</row>
												<row>
													<label
														value="First Name" width="100px" />
													<textbox
														constraint="no empty"
														value="@{family.mother.firstName, save-when='self.onBlur'}"
														width="190px" />
												</row>
												<row>
													<label
														value="Middle Name" width="100px" />
													<textbox
														value="@{family.mother.middleName, save-when='self.onBlur'}"
														width="190px" />
												</row>
												<row>
													<label
														value="Surname" width="100px" />
													<textbox
														constraint="no empty"
														value="@{family.mother.surname, save-when='self.onBlur'}"
														width="190px" />
												</row>
												<row>
													<label
														value="eMail Address" width="100px" />
													<textbox
														constraint="no empty"
														value="@{family.mother.emailAddress, save-when='self.onBlur'}"
														width="190px" />
												</row>
												<row>
													<label
														value="Address" width="100px" />
													<textbox
														constraint="no empty"
														value="@{family.homeAddress.addressLine1, save-when='self.onBlur'}"
														width="230px" />
												</row>
												<row>
													<label value=""
														width="100px" />
													<textbox
														constraint="no empty"
														value="@{family.homeAddress.addressLine2, save-when='self.onBlur'}"
														width="230px" />
												</row>
												<row>
													<label value=""
														width="100px" />
													<textbox
														value="@{family.homeAddress.addressLine3, save-when='self.onBlur'}"
														width="230px" />
												</row>
												<row>
													<label value=""
														width="100px" />
													<textbox
														value="@{family.homeAddress.addressLine4, save-when='self.onBlur'}"
														width="230px" />
												</row>
												<row>
													<label value=""
														width="100px" />
													<textbox
														value="@{family.homeAddress.addressLine5, save-when='self.onBlur'}"
														width="230px" />
												</row>
												<row>
													<label value=""
														width="100px" />
													<textbox
														value="@{family.homeAddress.addressLine6, save-when='self.onBlur'}"
														width="230px" />
												</row>
												<row>
													<label value=""
														width="100px" />
													<textbox
														value="@{family.homeAddress.addressLine7, save-when='self.onBlur'}"
														width="230px" />
												</row>
												<row>
													<label
														value="Post Code" width="100px" />
													<textbox
														constraint="no empty"
														value="@{family.homeAddress.postcode, save-when='self.onBlur'}"
														width="90px" />
												</row>
											</rows>
										</grid>
									</tabpanel>
									<tabpanel>
										<grid fixedLayout="false">
											<rows>
												<row>
													<label
														value="Title" />
													<combobox
														model="@{preSchoolReferenceData.titles}"
														selectedItem="@{family.father.title}" readonly="true"
														mold="rounded">
														<comboitem
															self="@{each='fatherTitle'}"
															label="@{fatherTitle.description}">
														</comboitem>
													</combobox>
												</row>

												<row>
													<label
														value="First Name" width="100px" />
													<textbox
														value="@{family.father.firstName, save-when='self.onBlur'}"
														width="190px" />
												</row>
												<row>
													<label
														value="Middle Name" width="100px" />
													<textbox
														value="@{family.father.middleName, save-when='self.onBlur'}"
														width="190px" />
												</row>
												<row>
													<label
														value="Surname" width="100px" />
													<textbox
														value="@{family.father.surname, save-when='self.onBlur'}"
														width="190px" />
												</row>
												<row>
													<label
														value="eMail Address" width="100px" />
													<textbox
														constraint="no empty"
														value="@{family.father.emailAddress, save-when='self.onBlur'}"
														width="190px" />
												</row>
												<row>
													<button
														id="nextButton" label="Next"
														href="/family/next/addpage1.do" />
												</row>

												<row>
													<button
														id="addChild" label="Add Nipper" href="/family/next/addchild.do" />
												</row>

											</rows>
										</grid>
									</tabpanel>
								</tabpanels>
							</tabbox>
						</div>
					</west>
					<center title="Children">
						<div>
							<tabbox id="childrenTabbox"></tabbox>
						</div>
					</center>
					<east title="Telephone Contact(s)" size="33%"
						flex="true" maxsize="250" splittable="true" collapsible="true">
						<div>
							<listbox id="contactBox" width="350px"
								model="@{family.mother.contact}">
								<listhead sizable="true">
									<listheader label="Type"
										sort="auto" />
									<listheader label="Contact"
										sort="auto" />
									<listheader label="Emergency"
										sort="auto" />
								</listhead>
								<listitem
									self="@{each='motherContact'}">
									<listcell
										label="@{motherContact.contactType.description}" />
									<listcell>
										<textbox
											value="@{motherContact.contact}" />
									</listcell>
									<listcell>
										<checkbox
											value="@{motherContact.emergency}" />
									</listcell>
								</listitem>
							</listbox>
						</div>
					</east>
				</borderlayout>
			</center>
		</borderlayout>
	</window>
</zk>

my included page is

<?xml version="1.0" encoding="UTF-8" ?>
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" arg0="./zeroKode${arg.tabularIndex}"?>
<window id="zeroKode${arg.tabularIndex}">
	<grid fixedLayout="false">
		<columns>
			<column label="" width="15%" />
			<column label="" width="30%" />
		</columns>
		<rows>
			<row>
				<label value="Gender" />
				<combobox model="@{preSchoolReferenceData.genders}"
					selectedItem="@{family.child.gender}" readonly="true"
					mold="rounded">
					<comboitem self="@{each='childGender'}"
						label="@{childGender.description}">
					</comboitem>
				</combobox>
			</row>
			<row>
				<label value="First Name ${arg.tabularIndex}"
					width="100px" />
				<textbox constraint="no empty"
					value="@{family.child.firstName, save-when='self.onBlur'}"
					width="190px" />
			</row>
			<row>
				<label value="Middle Name" width="100px" />
				<textbox
					value="@{family.child.middleName, save-when='self.onBlur'}"
					width="190px" />
			</row>
			<row>
				<label value="Surname" width="100px" />
				<textbox constraint="no empty"
					value="@{family.child.surname, save-when='self.onBlur'}"
					width="190px" />
			</row>
			<row>
				Date Of Birth:
				<hbox>
					<datebox onSelection="self.close()" readonly="false"
						mold="rounded"
						constraint="no empty, no future: Please enter a valid Date Of Birth"
						format="dd/MM/yyyy"
						value="@{family.child.dateOfBirth, save-when='self.onChange'}" />
				</hbox>
			</row>
			<row>
				<label value="Language" />
				<combobox model="@{preSchoolReferenceData.languages}"
					selectedItem="@{family.child.language}" readonly="true"
					mold="rounded">
					<comboitem self="@{each='childLanguage'}"
						label="@{childLanguage.description}">
					</comboitem>
				</combobox>
			</row>
			<row>
				<label value="Ethnic Group" />
				<combobox model="@{preSchoolReferenceData.ethnicGroups}"
					selectedItem="@{family.child.ethnicGroup}" readonly="true"
					mold="rounded">
					<comboitem self="@{each='childEthnicGroup'}"
						label="@{childEthnicGroup.description}">
					</comboitem>
				</combobox>
			</row>
			<row>
				<label value="Religion" />
				<combobox model="@{preSchoolReferenceData.religions}"
					selectedItem="@{family.child.religion}" readonly="true"
					mold="rounded">
					<comboitem self="@{each='childReligion'}"
						label="@{childReligion.description}">
					</comboitem>
				</combobox>
			</row>
		</rows>
	</grid>
</window>

my composer is

package com.pre.school.zk.composer;

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

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Components;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.ForwardEvent;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zkplus.databind.AnnotateDataBinder;
import org.zkoss.zul.Button;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.Tab;
import org.zkoss.zul.Tabbox;
import org.zkoss.zul.Tabpanel;
import org.zkoss.zul.Tabpanels;
import org.zkoss.zul.Tabs;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.impl.InputElement;

public class ValidationComposer extends GenericForwardComposer {

	private static final long serialVersionUID = -1870580858482873118L;

	private AnnotateDataBinder binder;
	private Component childComponent;
	public boolean allFieldsValid = true;
	private Button nextButton;
	private Tabbox childrenTabbox;

	@Override
	public void doAfterCompose(Component comp) throws Exception {
		super.doAfterCompose(comp);
		addChildrenTab();
		addChildrenTab();

	}

//	public void onClick$addChild(ForwardEvent event) throws Exception {
//		System.out.println("   in ValidationComposer");
//		addChildrenTab();
//	}

	public void onCreate$win(ForwardEvent event) {
		binder = (AnnotateDataBinder) event.getTarget().getAttributeOrFellow("binder", true);
		nextButton.setDisabled(true);

	}

	@SuppressWarnings("unchecked")
	public void onOK$win(ForwardEvent event) {
		List childComponents;

		childComponents = event.getTarget().getChildren();

		childComponent = (Component) childComponents.get(0);

		if (getChildren(childComponent)) {
			nextButton.setDisabled(false);
		} else {
			nextButton.setDisabled(true);
		}

		binder.saveAll();
		addChildrenTab();

	}

	private int addChildrenTab() {

		Map<String,Integer> arguments = new HashMap<String, Integer>();
		Tabpanel tabpanel = new Tabpanel();
		Tab      tab      = new Tab("Another Child");
		tab.setSelected(true);
		
		if (childrenTabbox.getTabs() == null){
			childrenTabbox.appendChild(new Tabs());			
			childrenTabbox.appendChild(new Tabpanels());			
		}
			
		childrenTabbox.getTabs().appendChild(tab);
		
		arguments.put("tabularIndex", tab.getIndex());
		System.out.println(" tab.getIndex() = " +  tab.getIndex());
		Executions.createComponents("childTAB.zul", tabpanel, arguments);

		childrenTabbox.getTabpanels().appendChild(tabpanel);
		childrenTabbox.invalidate();
		
		return tab.getIndex();

	}

	@SuppressWarnings("unchecked")
	private boolean getChildren(Component theseChildren) {

		List<Component> componentList;

		if (theseChildren == null) {
			return false;
		}

		componentList = (List<Component>) theseChildren.getChildren();

		if ((componentList == null) || (componentList.size() == 0)) {
			return allFieldsValid;
		}

		for (Component myComponent : componentList) {

			if (myComponent instanceof Textbox) {
				((Textbox) myComponent).getValue();
			} else if (myComponent instanceof Datebox) {
				((Datebox) myComponent).getValue();
			}

			if (myComponent instanceof InputElement) {
				if (allFieldsValid) {
					allFieldsValid = ((InputElement) myComponent).isValid();
				}
			}

			getChildren(myComponent);

		}

		return allFieldsValid;

	}

}

cheers

D D

link publish delete flag offensive edit

answered 2010-05-05 19:52:35 +0800

ashishd gravatar image ashishd flag of Taiwan
1972 6

Hi dickdastardly,
Just wondering if you found a workaround for your problem? I am taking a look at your source code now and will reply asap

Thanks
- Ashish

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2010-04-14 05:47:02 +0800

Seen: 2,198 times

Last updated: May 05 '10

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