0

create Tabboxes "On The Fly"

asked 2010-04-09 05:50:42 +0800

dickdastardly gravatar image dickdastardly
168 1 5

Dear ZK Forum

should i know this?

I have an app that collects a families details

Thats two parents and 1 or more children

each childs details are entered in a tabbox

so i need to dynamically create 1 or more tabboxes

As tabbox doesnt support data models

how can i do this?
is it possible to do?

Warm regards

Dick Dastardly

delete flag offensive retag edit

14 Replies

Sort by ยป oldest newest

answered 2010-04-11 03:49:46 +0800

dickdastardly gravatar image dickdastardly
168 1 5

Can no one help ?

p l e a s e

DD

link publish delete flag offensive edit

answered 2010-04-11 08:27:36 +0800

msrednsi gravatar image msrednsi
106 2

Review docs and api, please. ZK lets you create components programatically. Here are some lines of code to add tabs to a tabbox

Asume you have a zul page with a tabbox with id="tabbox", use Components.wirevariables() on, for example, afterCompose() (look at smalltalks about autowiring), then

Tabpanel tabpanel= new Tabpanel();
Tabtab= new Tab( title );
tabbox.getTabs().appendChild( tab );
tabbox.getTabpanels().appendChild(tabpanel);

You can do this wherever you want, zk will update you the ui. For example, when pressing a button.
It's easy, just modify the zul page using its components and properties. No secrets.

Hole that helps

link publish delete flag offensive edit

answered 2010-04-12 23:16:35 +0800

dickdastardly gravatar image dickdastardly
168 1 5

Thanks for that

got the tabs being added dynamically

Now im stuck on how to bind the instances of the child list to each tab?

As i am using spring 3 i have already created and bound the data objects to the zk page

however as the user can dynamically add children i need to get access to the child List and resize it,

then bind the newly created instance to the new tab.

whats the cleanest way of doing this?

Sorry but the small talks i've looked at dont help!

DD

link publish delete flag offensive edit

answered 2010-04-15 11:17:29 +0800

dickdastardly gravatar image dickdastardly
168 1 5

I've generated the components using Executions.createComponents

however i cannot get the data backing model to be bound to the input fields

How do you do this?

My included page has its own binder,

Also I cannot see how to use the tabindex value to control the iteration of the backing arraylist

Is this something i should be able to work out for myself?

have i let myself down? :-(

can no one help me?

DD

link publish delete flag offensive edit

answered 2010-04-15 23:59:47 +0800

tmillsclare gravatar image tmillsclare
799 2 5 30

Hey dickdastardly, can you show me some of your code. It would really help to see your ZUL file and how you implemented the bindings.

link publish delete flag offensive edit

answered 2010-04-16 05:16:46 +0800

dickdastardly gravatar image dickdastardly
168 1 5

Dear tmillsclare

heres my composer
main zul page
and included zul page for each tab within tabbox

what i am after is that the backing child list (a java arraylist) has each instances set by the associated tabindex within the tabbox.
also

a new tab and tab panel can be added when the user clicks the "add child" button.

I have managed to get a new tab and tab panel to be added to the tabbox, however i cannot get the data model to bind to the input & output fields

did i mention i was using spring 3.0?

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;

	}

}

heres the main page is here

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

and the subpage included for each new tab in tabbox

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

link publish delete flag offensive edit

answered 2010-04-17 11:56:43 +0800

dickdastardly gravatar image dickdastardly
168 1 5

I am feeling unloved and ignored by the zk forum!

is there no one that can put me out of my misery?

Muttley, Do Something!!!!!!!!!!!!! :-)

link publish delete flag offensive edit

answered 2010-04-19 02:07:33 +0800

tmillsclare gravatar image tmillsclare
799 2 5 30

@DD

Don't worry I love you and I will help you try and find the pigeon :).

I think the answer to your prayers may be here. Please try and use this function on your root component after creation with "createComponents" and it should iterate through them all and bind the data.

If not, please try iterating through the component list yourself.

link publish delete flag offensive edit

answered 2010-04-19 12:50:46 +0800

dickdastardly gravatar image dickdastardly
168 1 5

Dear tmillsclare

Im feeling the love :-)

i'll give

loadComponent(Component comp)
          Load values from the data bean properties to all attributes of a specified UI component.

a go ...

however i can feel a "Drat and Double Drat" coming on :-(

D. Dastardly

link publish delete flag offensive edit

answered 2010-04-23 02:55:00 +0800

dickdastardly gravatar image dickdastardly
168 1 5

WAH HAY tmillsclare

no "Drat" or indeed "Double Drat"

it works N I C E

Now i have one last outstanding problem....

Now that i can both dynamically create tabpanel(s) in my tabbox and bind the backing beans to the ui components
i now need to use the tabindex to control which instance of the child array (arrayList actually but how is counting!!!)
is bound on each individual tab


thanks again for helping

Yours

Dick D

	private int addChildrenTab() {
		
		AnnotateDataBinder tabboxBinder;
		Component tabComponent;

		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());
		tabComponent = Executions.createComponents("childTAB.zul", tabpanel, arguments);

		childrenTabbox.getTabpanels().appendChild(tabpanel);
		childrenTabbox.invalidate();
		tabboxBinder = new AnnotateDataBinder(tabComponent);
		tabboxBinder.loadAll();
		
		return tab.getIndex();

	}

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-09 05:50:42 +0800

Seen: 1,403 times

Last updated: Jul 30 '10

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