Smalltalk-draft"
Line 6: | Line 6: | ||
= Overview = | = Overview = | ||
− | |||
− | |||
[https://reactjs.org/ React] is a JavaScript library for building user interfaces. We can use React as a front-end UI and use ZK as a pure backend. In this small talk, I will show you how to integrate React with ZK using the [https://books.zkoss.org/zk-mvvm-book/8.0/data_binding/client_binding_api.html client binding API] step by step. | [https://reactjs.org/ React] is a JavaScript library for building user interfaces. We can use React as a front-end UI and use ZK as a pure backend. In this small talk, I will show you how to integrate React with ZK using the [https://books.zkoss.org/zk-mvvm-book/8.0/data_binding/client_binding_api.html client binding API] step by step. | ||
Line 15: | Line 13: | ||
= Load data from ZK = | = Load data from ZK = | ||
− | We need to create a View Model to use the client binding feature in React. | + | We need to create a View Model to use the client binding feature in React. |
== Create a ViewModel (VM) in ZK == | == Create a ViewModel (VM) in ZK == | ||
Line 46: | Line 44: | ||
== Set Client Binding Annotations == | == Set Client Binding Annotations == | ||
+ | In order to get the <code>vm.products</code> from the client, we need to add some annotation to the IndexVM. | ||
+ | |||
+ | '''IndexVM.java''' | ||
+ | <source lang="java" high="2,5"> | ||
+ | @NotifyCommands({ | ||
+ | @NotifyCommand(value = "getProducts", onChange = "_vm_.products") | ||
+ | }) | ||
+ | @ToServerCommand({"tipProducts", "placeOrder"}) | ||
+ | @ToClientCommand({"getProducts"}) | ||
+ | @VariableResolver(DelegatingVariableResolver.class) | ||
+ | public class IndexVM { | ||
+ | // omitted | ||
+ | </source> | ||
+ | * LIne 2: Add a <code>@NotifyCommand</code> and listen to <code>_vm_.products</code> changes (<em>_vm_</em> means the VM object) | ||
+ | * Line 5: Register a client command so the client can call <code>getProducts</code>. ZK client binding uses whitelist so no command is allowed to be called from the client by default. | ||
+ | |||
+ | Once we set, we can get the property from the client. Let's see how we get the <code>products</code> from ZK. | ||
+ | |||
+ | == Use Client-Binding API in React == | ||
+ | |||
+ | First, we need to use the ViewModel in zul, and create a root element for React. | ||
+ | |||
+ | '''index.zul''' | ||
+ | <source lang="xml" high="2, 3"> | ||
+ | <zk xmlns:n="native"> | ||
+ | <div id="main" viewModel="@id('vm') @init('react.vm.IndexVM')"> | ||
+ | <n:div id="root"/> | ||
+ | </div> | ||
+ | </zk> | ||
+ | </source> | ||
+ | * Line 2: The <code>id</code> property is needed for client binding to get the correct VM. | ||
+ | * Line 3: We have created a native DIV element for React to render. | ||
+ | |||
+ | We can use [http://books.zkoss.org/zk-mvvm-book/8.0/data_binding/client_binding_api.html#on-clientside binder.after] to get products from ZK. | ||
+ | |||
+ | <source lang="js"> | ||
+ | zkbind.$('$main').after('getProducts', function (data) { | ||
+ | // the data is vm.products | ||
+ | // and this function will be called each time vm.products is changed | ||
+ | }); | ||
+ | </source> | ||
The react-shopping-cart loads JSON data a server. A method <code>fetchProducts</code> initiates <code>axios.get</code> to make an AJAX request. | The react-shopping-cart loads JSON data a server. A method <code>fetchProducts</code> initiates <code>axios.get</code> to make an AJAX request. | ||
Line 59: | Line 98: | ||
</source> | </source> | ||
− | We can use client binding API to request with ZK instead. | + | We can use client binding API to request with ZK instead. I wrote a utility class to handle it for convenience. |
+ | |||
+ | '''zkBinder.js''' | ||
+ | <source lang="js"> | ||
+ | function getBinder(name) { | ||
+ | return window.zkbind && window.zkbind.$(name); | ||
+ | } | ||
+ | |||
+ | export default { | ||
+ | after(name, event, callback) { | ||
+ | let binder = getBinder(name); | ||
+ | if (binder) { | ||
+ | binder.after(event, callback); | ||
+ | return true; | ||
+ | } | ||
+ | return false; | ||
+ | }, | ||
+ | // omitted | ||
+ | </source> | ||
+ | |||
+ | By default, ZK uses one-way binding, so the function is bound to the property. To simulate a one-time request, I need to trigger a command first, the command just notifies ZK that it changes (but actually not) in order to trigger <code>@NotifyCommand</code> | ||
+ | |||
+ | '''react-shopping-cart/src/services/shelf/actions.js''' | ||
+ | <source lang="js"> | ||
+ | export const fetchProducts = (filters, sortBy, callback) => dispatch => { | ||
+ | return axios | ||
+ | .get(productsAPI) | ||
+ | .then(res => { | ||
+ | let { products } = res.data; | ||
+ | // omitted | ||
+ | </source> | ||
= Submit data to ZK = | = Submit data to ZK = |
Revision as of 04:08, 7 January 2020
Rudy Huang, Engineer, Potix Corporation
January, 2020
ZK 9.0.0
Overview
React is a JavaScript library for building user interfaces. We can use React as a front-end UI and use ZK as a pure backend. In this small talk, I will show you how to integrate React with ZK using the client binding API step by step.
For convenience, I use an open-source React demo project react-shopping-cart to demonstrate.
Load data from ZK
We need to create a View Model to use the client binding feature in React.
Create a ViewModel (VM) in ZK
We created an IndexVM.java
and defined a property "products". The products
property is loaded from a database.
IndexVM.java
@VariableResolver(DelegatingVariableResolver.class)
public class IndexVM {
// omitted
@WireVariable
private ProductService productService;
private List<ProductDto> products;
// omitted
@Init
public void init() {
products = productService.getProducts();
}
public List<ProductDto> getProducts() {
return products;
}
// omitted
- Line 11: We use Spring + Hibernate to communicate with the database. A service instance is needed to be injected in the VM by adding a
@WireVariable
annotation. - Line 14: Declare getter only here so ZK knows
products
is a readonly property of a VM.
Set Client Binding Annotations
In order to get the vm.products
from the client, we need to add some annotation to the IndexVM.
IndexVM.java
@NotifyCommands({
@NotifyCommand(value = "getProducts", onChange = "_vm_.products")
})
@ToServerCommand({"tipProducts", "placeOrder"})
@ToClientCommand({"getProducts"})
@VariableResolver(DelegatingVariableResolver.class)
public class IndexVM {
// omitted
- LIne 2: Add a
@NotifyCommand
and listen to_vm_.products
changes (_vm_ means the VM object) - Line 5: Register a client command so the client can call
getProducts
. ZK client binding uses whitelist so no command is allowed to be called from the client by default.
Once we set, we can get the property from the client. Let's see how we get the products
from ZK.
Use Client-Binding API in React
First, we need to use the ViewModel in zul, and create a root element for React.
index.zul
<zk xmlns:n="native">
<div id="main" viewModel="@id('vm') @init('react.vm.IndexVM')">
<n:div id="root"/>
</div>
</zk>
- Line 2: The
id
property is needed for client binding to get the correct VM. - Line 3: We have created a native DIV element for React to render.
We can use binder.after to get products from ZK.
zkbind.$('$main').after('getProducts', function (data) {
// the data is vm.products
// and this function will be called each time vm.products is changed
});
The react-shopping-cart loads JSON data a server. A method fetchProducts
initiates axios.get
to make an AJAX request.
react-shopping-cart/src/services/shelf/actions.js
export const fetchProducts = (filters, sortBy, callback) => dispatch => {
return axios
.get(productsAPI)
.then(res => {
let { products } = res.data;
// omitted
We can use client binding API to request with ZK instead. I wrote a utility class to handle it for convenience.
zkBinder.js
function getBinder(name) {
return window.zkbind && window.zkbind.$(name);
}
export default {
after(name, event, callback) {
let binder = getBinder(name);
if (binder) {
binder.after(event, callback);
return true;
}
return false;
},
// omitted
By default, ZK uses one-way binding, so the function is bound to the property. To simulate a one-time request, I need to trigger a command first, the command just notifies ZK that it changes (but actually not) in order to trigger @NotifyCommand
react-shopping-cart/src/services/shelf/actions.js
export const fetchProducts = (filters, sortBy, callback) => dispatch => {
return axios
.get(productsAPI)
.then(res => {
let { products } = res.data;
// omitted
Submit data to ZK
Download the Source
You can access the complete source at github.
Other Front-End Frameworks Integrations
- Angular
- Vue.js
Comments
Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License. |