Building Stateless UI"
Line 33: | Line 33: | ||
We will use the simple shopping cart application as an example to introduce basic features of stateless components: | We will use the simple shopping cart application as an example to introduce basic features of stateless components: | ||
[[File:Shoppingcart.png|center]] | [[File:Shoppingcart.png|center]] | ||
+ | |||
+ | = Building UI with Richlet= | ||
+ | Building user interfaces (UI) with stateless components requires creating a StatelessRichlet and mapping a URL to that richlet. | ||
= Restful URL Mapping = | = Restful URL Mapping = |
Revision as of 08:35, 23 November 2023
Setting up
To set up stateless components in a ZK 10 application, you need to include the stateless components module and define a Dispatcher Richlet Filter in your WEB-INF/web.xml
file.
Including Required Jar
dependencies {
implementation "org.zkoss.zk:stateless:${zkVersion}"
...
}
Dispatcher Richlet Filter
<filter>
<filter-name>DispatcherRichletFilter</filter-name>
<filter-class>org.zkoss.stateless.ui.http.DispatcherRichletFilter</filter-class>
<init-param>
<param-name>basePackages</param-name>
<param-value><!-- your base packages --></param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>DispatcherRichletFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Example Application
We will use the simple shopping cart application as an example to introduce basic features of stateless components:
Building UI with Richlet
Building user interfaces (UI) with stateless components requires creating a StatelessRichlet and mapping a URL to that richlet.
Restful URL Mapping
URL mapping is similar to using RESTful API. We use @RichletMapping
to represent mapping the HTTP Request path with the GET method.
- for example, the
shoppingCart()
URL will be <protocal>:// <host name: port> /shoppingCart.
@RichletMapping("/shoppingCart")
public class DemoRichlet implements StatelessRichlet {
@RichletMapping("")
public List<IComponent> shoppingCart() {
//return ...
}
}
Composing the UI with Stateless Components
Before ZK 10, ZK components are stateful, meaning that the server holds the state. Starting from ZK 10, we provide a set of stateless components as Immutable objects. Immutable objects are constructed once and can not be changed after they are constructed. After Immutable objects are rendered, they will be destroyed. Since the component state will not be saved on the server, they consume less memory.
UI Composing
With ZK 10 stateless components, you will no longer write a zul file. You will be composing your view using the stateless components and their APIs in Java.
- ZK component having a prefix letter "I" represents an immutable component.
- We offer
of()
API for commonly used properties. withSclass()
means the setter of sclass.
// ZK 10
IButton.of("add items")
.withSclass("add-items");
// ZK 9
// equivalent idea as above.
Button button = new Button("add items");
button.setSclass("add-items");
Event Wiring
To wire an event listener, you need to declare the ActionHandler method, with an annotation @Action
.
- The method should be public.
- The parameter of
@Action
should be one of event types. - Wire the action handler with the target component by
withAction(ActionHandler action)
.
// ActionHandler method
@Action(type = Events.ON_CLICK) // Wiring event
public void addItem() {
...
}
public IComponent demo() {
return IButton.of("add items").withSclass("add-items")
.withAction(this::addItem);
}
Obtain Widget State
Since a server no longer holds a component's state, we provide @ActionVariable
to access component attributes and state sent from the client.
@ActionVariable(targetId = ActionTarget.SELF, field = "id")
retrieves the value from thefield
of a component with thetargetId
on the client.ActionTarget.SELF
means it targets the component associates to the event itself.
@Action(type = Events.ON_CLICK)
public void addItem(@ActionVariable(targetId = ActionTarget.SELF, field = "id") String orderId) {
}
Update Widget State
To update the widget state, we provide several APIs in UiAgent
. The state will be updated to the client immediately.
- The following example will add the specified child component as the last child to the locator.
@Action(type = Events.ON_CLICK)
public void addItem(@ActionVariable(targetId = SELF, field = "id") String orderId) {
UiAgent.getCurrent().appendChild(Locator.ofId("shoppingBagRows"), addShoppingBagItem(parseUuid(orderId)));
}
Example Application
You can download the shopping cart demo project.