Chapter 5: Handling User Input"

From Documentation
Line 12: Line 12:
  
 
= MVC Approach =  
 
= MVC Approach =  
 +
 +
== View ==
 +
 +
<source lang='xml' high='4'>
 +
 +
<?link rel="stylesheet" type="text/css" href="/style.css"?>
 +
<window apply="org.zkoss.tutorial.chapter5.mvc.ProfileViewController"
 +
border="normal" hflex="1" vflex="1" contentStyle="overflow:auto">
 +
<caption src="/imgs/profile.png" sclass="fn-caption" label="Profile (MVC)"/>
 +
<vlayout>
 +
<grid width="500px">
 +
<columns>
 +
<column align="right" hflex="min"/>
 +
<column/>
 +
</columns>
 +
<rows>
 +
<row>
 +
<cell sclass="row-title">Account :</cell>
 +
<cell><label id="account"/></cell>
 +
</row>
 +
<row>
 +
<cell sclass="row-title">Full Name :</cell>
 +
<cell><textbox id="fullName" constraint="no empty: Plean enter your full name" width="200px"/></cell>
 +
</row>
 +
<row>
 +
<cell sclass="row-title">Email :</cell>
 +
<cell><textbox id="email" constraint="/.+@.+\.[a-z]+/: Please enter an e-mail address" width="200px"/></cell>
 +
</row>
 +
<row>
 +
<cell sclass="row-title">Birthday :</cell>
 +
<cell><datebox id="birthday" constraint="no future" width="200px"/></cell>
 +
</row>
 +
<row>
 +
<cell sclass="row-title">Country :</cell>
 +
<cell>
 +
<listbox id="country" mold="select" width="200px">
 +
<template name="model">
 +
<listitem label="${each}" />
 +
</template>
 +
</listbox>
 +
</cell>
 +
</row>
 +
<row>
 +
<cell sclass="row-title">Bio :</cell>
 +
<cell><textbox id="bio" multiline="true" hflex="1" height="200px" /></cell>
 +
</row>
 +
</rows>
 +
</grid>
 +
<hlayout>
 +
<button id="saveProfile" label="Save"/>
 +
<button id="reloadProfile" label="Reload"/>
 +
</hlayout>
 +
</vlayout>
 +
</window>
 +
</source>
  
 
== Display a Collection of Data ==
 
== Display a Collection of Data ==

Revision as of 10:11, 16 January 2013

Target Application

This chapter we will demonstrate a common scenario: collecting user input in form-based page. The target application looks as follows:

Tutorial-ch5-app.png

There is a personal profile form with 5 different fields. Click the "Save" button saves users input and click the "Reload" button loads previous saved data back to the form. We will show how to implement these functions in both MVC and MVVM approach.

MVC Approach

View

<?link rel="stylesheet" type="text/css" href="/style.css"?>
<window apply="org.zkoss.tutorial.chapter5.mvc.ProfileViewController" 
	border="normal" hflex="1" vflex="1" contentStyle="overflow:auto">
	<caption src="/imgs/profile.png" sclass="fn-caption" label="Profile (MVC)"/>
	<vlayout>
		<grid width="500px">
			<columns>
				<column align="right" hflex="min"/>
				<column/>
			</columns>
			<rows>
				<row>
					<cell sclass="row-title">Account :</cell>
					<cell><label id="account"/></cell>
				</row>
				<row>
					<cell sclass="row-title">Full Name :</cell>
					<cell><textbox id="fullName" constraint="no empty: Plean enter your full name" width="200px"/></cell>
				</row>
				<row>
					<cell sclass="row-title">Email :</cell>
					<cell><textbox id="email" constraint="/.+@.+\.[a-z]+/: Please enter an e-mail address" width="200px"/></cell>
				</row>
				<row>
					<cell sclass="row-title">Birthday :</cell>
					<cell><datebox id="birthday" constraint="no future" width="200px"/></cell>
				</row>
				<row>
					<cell sclass="row-title">Country :</cell>
					<cell>
						<listbox id="country" mold="select" width="200px">
							<template name="model">
								<listitem label="${each}" />
							</template>
						</listbox>
					</cell>
				</row>
				<row>
					<cell sclass="row-title">Bio :</cell>
					<cell><textbox id="bio" multiline="true" hflex="1" height="200px" /></cell>
				</row>
			</rows>
		</grid>
		<hlayout>
			<button id="saveProfile" label="Save"/>
			<button id="reloadProfile" label="Reload"/>
		</hlayout>
	</vlayout>
</window>

Display a Collection of Data

Tutorial-ch5-collection.png
public class ProfileViewController extends SelectorComposer<Component>{
	...
	@Wire
	Listbox country;

	@Override
	public void doAfterCompose(Component comp) throws Exception{
		super.doAfterCompose(comp);
		
		ListModelList<String> countryModel = new ListModelList<String>(CommonInfoService.getCountryList());
		country.setModel(countryModel);
		
		refreshProfileView();
	}

	...
}


Handle Events in a Composer

public class ProfileViewController extends SelectorComposer<Component>{

	//wire components
	@Wire
	Label account;
	@Wire
	Textbox fullName;
	@Wire
	Textbox email;
	@Wire
	Datebox birthday;
	@Wire
	Listbox country;
	@Wire
	Textbox bio;

	@Listen("onClick=#saveProfile")
	public void doSaveProfile(){
		UserCredential cre = authService.getUserCredential();
		User user = userInfoService.findUser(cre.getAccount());
		if(user==null){
			//TODO handle un-authenticated access 
			return;
		}
		
		//apply component value to bean
		user.setFullName(fullName.getValue());
		user.setEmail(email.getValue());
		user.setBirthday(birthday.getValue());
		user.setBio(bio.getValue());
		
		Set<String> selection = ((Selectable)country.getModel()).getSelection();
		if(!selection.isEmpty()){
			user.setCountry(selection.iterator().next());
		}else{
			user.setCountry(null);
		}
		
		userInfoService.updateUser(user);
		
		Clients.showNotification("Your profile is updated");
	}
	...
}


<source lang="java"> public class ProfileViewController extends SelectorComposer<Component>{


//wire components @Wire Label account; @Wire Textbox fullName; @Wire Textbox email; @Wire Datebox birthday; @Wire Listbox country; @Wire Textbox bio;

... @Listen("onClick=#reloadProfile") public void doReloadProfile(){ refreshProfileView(); }

private void refreshProfileView() { UserCredential cre = authService.getUserCredential(); User user = userInfoService.findUser(cre.getAccount()); if(user==null){ //TODO handle un-authenticated access return; }

//apply bean value to UI components account.setValue(user.getAccount()); fullName.setValue(user.getFullName()); email.setValue(user.getEmail()); birthday.setValue(user.getBirthday()); bio.setValue(user.getBio());

((Selectable)country.getModel()).addToSelection(user.getCountry()); } }