Chapter 5: Handling User Input"
(→View) |
(→View) |
||
Line 84: | Line 84: | ||
</source> | </source> | ||
* Line 4: [[ZK%20Component%20Reference/Containers/Caption|''Caption'']] can be used to build compound header with image for a ''Groupbox'' and ''Window''. | * Line 4: [[ZK%20Component%20Reference/Containers/Caption|''Caption'']] can be used to build compound header with image for a ''Groupbox'' and ''Window''. | ||
− | * Line 5: | + | * Line 5: [[ZK%20Component%20Reference/Layouts/Vlayout| ''Vlayout'']] is a light-weight layout component which arranges child components vertically without splitter, align, pack support. |
* Line 13: [[ZK_Component_Reference/Supplementary/Cell| ''Cell'']] is used inside ''Row'', ''Hbox'', or ''Vbox'' for fully controlling style and layout. | * Line 13: [[ZK_Component_Reference/Supplementary/Cell| ''Cell'']] is used inside ''Row'', ''Hbox'', or ''Vbox'' for fully controlling style and layout. | ||
− | * Line 19, 26, 31: | + | * Line 19, 26, 31: Specify <tt>constraint</tt> attribute of a input component can activate client-side validation feature. Then, the input component will show error message when input value doesn't match specified constraint rule. [[''Textbox'']] and [[''Datebox'']] has different syntax of constraint rule. |
− | * Line 49: | + | * Line 49: [[ZK%20Component%20Reference/Layouts/Hlayout| ''Hlayout'']], like ''Vlayout'', but arrange child components horizontally. |
== Display a Collection of Data == | == Display a Collection of Data == |
Revision as of 09:03, 17 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:
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
Under this approach, we implement all event handling and presentation logic in a composer instead of in <zscript/> and make a zul clear from codes. This approach make the responsibility of each role (Model, View, and Controller) more cohesive and allows you to control components directly. It is very intuitive and very flexible.
View
With the concept and technique we talked in last chapter, it should be easy to construct a form like user interface as follows:
<?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>
- Line 4: Caption can be used to build compound header with image for a Groupbox and Window.
- Line 5: Vlayout is a light-weight layout component which arranges child components vertically without splitter, align, pack support.
- Line 13: Cell is used inside Row, Hbox, or Vbox for fully controlling style and layout.
- Line 19, 26, 31: Specify constraint attribute of a input component can activate client-side validation feature. Then, the input component will show error message when input value doesn't match specified constraint rule. ''Textbox'' and ''Datebox'' has different syntax of constraint rule.
- Line 49: Hlayout, like Vlayout, but arrange child components horizontally.
Display a Collection of Data
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");
}
...
}
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());
}
}