ViewModel"

From Documentation
m (replace tt with code (via JWB))
 
(9 intermediate revisions by 6 users not shown)
Line 1: Line 1:
 
{{ZKDevelopersReferencePageHeader}}
 
{{ZKDevelopersReferencePageHeader}}
 +
{{Deprecated | url=[http://books.zkoss.org/zk-mvvm-book/8.0/viewmodel/index.html zk-mvvm-book/8.0/viewmodel]|}}
  
 
=What is ViewModel=
 
=What is ViewModel=
Line 5: Line 6:
 
ViewModel is an '''abstraction of Model'''. It extracts the necessary data to be displayed on the View from one or more Model classes. Those data are exposed through getter and setter method like JavaBean's property.  
 
ViewModel is an '''abstraction of Model'''. It extracts the necessary data to be displayed on the View from one or more Model classes. Those data are exposed through getter and setter method like JavaBean's property.  
  
ViewModel is also a '''Model of the View'''. It contains the View's state (e.g. selection, enablement) that might change during user interaction. For example, if a button is enabled when a user selects an item of a listbox. ViewModel shall store the state of the button's enablement and implement the logic to enable the button.   
+
ViewModel is also a '''Model of the View'''. It contains the View's state (e.g. selection, enabled status) that might change during user interaction. For example, if a button is enabled when a user selects an item of a listbox. ViewModel shall store the state of the button's enabled status and implement the logic to enable the button.   
  
Although ViewModel stores the View's states, it contains no reference to UI components. It can not access any UI components directly. Hence, there is a data binding mechanism to synchronize data between View and ViewModel. After developers define the binding relationship between View (UI component) and ViewModel, the data binding mechanism synchronize the data automatically. This makes ViewModel and View loose coupled.
+
Although ViewModel stores the View's states, it contains no reference to UI components. It can not access any UI components directly. Hence, there is a data binding mechanism to synchronize data between View and ViewModel. After developers define the binding relationship between View (UI component) and ViewModel, the data binding mechanism synchronize the data automatically. This makes ViewModel and View loosely coupled.
  
  
[[File:Mvvm-databinding-role.png]]
+
[[File:Mvvm-databinding-role.png | center]]
  
  
Line 18: Line 19:
  
  
[[File:Mvvm-event-command-reload.png]]
+
[[File:Mvvm-event-command-reload.png | center]]
  
  
Line 41: Line 42:
 
return name;
 
return name;
 
}
 
}
public voic setName(String name){
+
public void setName(String name){
 
this.name = name;
 
this.name = name;
 
}
 
}
Line 57: Line 58:
 
= Reference a ViewModel in a ZUL =
 
= Reference a ViewModel in a ZUL =
  
We can bind ZK UI component to a ViewModel by setting its '''viewModel''' attribute, and that component becomes the '''Root View Component''' for the ViewModel. All child components of this Root View Component can acces the same ViewModel and its properties. To bind a ViewModel, we have to apply a composer called '''org.zkoss.bind.BindComposer''', it will create a binder for the ViewModel and instantiate the ViewModel's class. Then we set '''viewModel''' attribute with ViewModel's id in <tt> @id </tt> ZK Bind annotation and a ViewModel's full-qualified class name in <tt> @init </tt>.  We use the id to reference ViewModel's properties, e.g. vm.name. We'll explain ZK bind syntax in detail at subsections of [[ZK Developer's Reference/MVVM/DataBinding]].
+
We can bind ZK UI component to a ViewModel by setting its '''viewModel''' attribute, and that component becomes the '''Root View Component''' for the ViewModel. All child components of this Root View Component can access the same ViewModel and its properties. To bind a ViewModel, we have to apply a composer called '''org.zkoss.bind.BindComposer''', it will create a binder for the ViewModel and instantiate the ViewModel's class. Using ZK Bind annotations then we set '''viewModel''' attribute with the ViewModel's id in <code>@id</code> and the ViewModel's full-qualified class name in <code>@init</code>.  The id is used to reference ViewModel's properties, e.g. vm.name, whilst the full-qualified class name is used to instantiate the ViewModel object itself. We'll explain ZK Bind annotation syntax in detail at subsections of [[ZK Developer's Reference/MVVM/DataBinding]].
  
 
<source lang="xml">
 
<source lang="xml">
  
<window apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('foo.MyViewModel')">
+
<window apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('foo.MyViewModel')">
  
 
     <label value="@bind(vm.name)"/>
 
     <label value="@bind(vm.name)"/>
     <button onClick="@command('newOrder')" />
+
     <button onClick="@command('newOrder')" label="New Order" />
 
</window>
 
</window>
  

Latest revision as of 15:05, 12 January 2022

Stop.png This article is out of date, please refer to zk-mvvm-book/8.0/viewmodel for more up to date information.

What is ViewModel

ViewModel is an abstraction of Model. It extracts the necessary data to be displayed on the View from one or more Model classes. Those data are exposed through getter and setter method like JavaBean's property.

ViewModel is also a Model of the View. It contains the View's state (e.g. selection, enabled status) that might change during user interaction. For example, if a button is enabled when a user selects an item of a listbox. ViewModel shall store the state of the button's enabled status and implement the logic to enable the button.

Although ViewModel stores the View's states, it contains no reference to UI components. It can not access any UI components directly. Hence, there is a data binding mechanism to synchronize data between View and ViewModel. After developers define the binding relationship between View (UI component) and ViewModel, the data binding mechanism synchronize the data automatically. This makes ViewModel and View loosely coupled.


Mvvm-databinding-role.png


ViewModel acts like a Controller in MVC, so the data binding mechanism forwards events to ViewModel's handlers. The handlers are ViewModel's method with specific Java annotation. We call such a method Command of the ViewModel. These methods usually manipulate data of the ViewModel, like deleting an item. Data binding mechanism also supports binding a UI component's event with a ViewModel's command. Firing the component's event will trigger the execution of bound command, invoking the annotated method.

During the execution of command, it usually changes the data of ViewModel. The developer should specify what properties change to be notified through Java annotation.


Mvvm-event-command-reload.png


the UI sometimes has to display data in a different format from original one in the Model. The converting logic shall be implemented in ViewModel or developers can adopt a more reusable element converter that we will talk about in a later section.

Validation will also be performed before saving data into ViewModel. If validation fails, the data will not be saved to ViewModel.

ViewModel with Annotation

In ZK, ViewModel can be simply a POJO, and it knows nothing about View's visual elements which means it should not hold any reference to UI components. The data binding mechanism handles communication and synchronization between View and ViewModel. Developers have to specify command and data dependency of a ViewModel with ZK provided Java annotation, then data binding mechanism will know how to interact with the ViewModel.

Creating a ViewModel is like creating a POJO, and it exposes its properties like JavaBean through setter and getter methods.


public class MyViewModel{
	private String name;
	
	public String getName(){
		return name;
	}
	public void setName(String name){
		this.name = name;
	}

	@NotifyChange({"selected","orders"})
	@Command
	public void newOrder(){
		//manipulate data
	}
}

Reference a ViewModel in a ZUL

We can bind ZK UI component to a ViewModel by setting its viewModel attribute, and that component becomes the Root View Component for the ViewModel. All child components of this Root View Component can access the same ViewModel and its properties. To bind a ViewModel, we have to apply a composer called org.zkoss.bind.BindComposer, it will create a binder for the ViewModel and instantiate the ViewModel's class. Using ZK Bind annotations then we set viewModel attribute with the ViewModel's id in @id and the ViewModel's full-qualified class name in @init. The id is used to reference ViewModel's properties, e.g. vm.name, whilst the full-qualified class name is used to instantiate the ViewModel object itself. We'll explain ZK Bind annotation syntax in detail at subsections of ZK Developer's Reference/MVVM/DataBinding.

<window apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('foo.MyViewModel')">

    <label value="@bind(vm.name)"/>
    <button onClick="@command('newOrder')" label="New Order" />
</window>



Subsections:



Last Update : 2022/01/12

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.