Command Binding"

From Documentation
m ((via JWB))
 
(5 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
{{ZKDevelopersReferencePageHeader}}
 
{{ZKDevelopersReferencePageHeader}}
 +
{{Deprecated | url=[http://books.zkoss.org/zk-mvvm-book/8.0/data_binding/command_binding.html zk-mvvm-book/8.0/data_binding/command_binding]|}}
 +
  
 
= Overview =
 
= Overview =
Command binding is a mechanism for hooking up a UI component's event such as button's onClick to ViewModel's Command<ref> [[ZK Developer's Reference/MVVM/ViewModel/Commands]] </ref> without writing code. This binding is established by <tt> @command </tt> with command's name in a  ZUL. We can only bind one event to only one Command but can bind multiple events to the same Command.
+
Command binding is a mechanism for hooking up a UI component's event such as button's onClick to ViewModel's Command<ref> [[ZK Developer's Reference/MVVM/ViewModel/Commands]] </ref> without writing code. This binding is established by <code>@command</code> with command's name in a  ZUL. We can only bind one event to only one Command but can bind multiple events to the same Command.
  
Command's name is the name of ViewModel's method with Java annotation <tt> @Command </tt> by default. You can also specify a Command's name in <tt> @Command </tt>'s element.
+
Command's name is the name of ViewModel's method with Java annotation <code>@Command </code> by default. You can also specify a Command's name in <code>@Command</code>'s element.
  
 
'''Command method example'''
 
'''Command method example'''
<source lang="java" high="5,14">
+
<source lang="java" highlight="5,14">
 
public class OrderVM {
 
public class OrderVM {
 
   
 
   
Line 30: Line 32:
  
 
'''Command binding example'''
 
'''Command binding example'''
<source lang="xml" high="2,3,9,10">
+
<source lang="xml" highlight="2,3,9,10">
  
 
<toolbar>
 
<toolbar>
Line 47: Line 49:
  
 
</source>
 
</source>
* When clicking "Save" button or menuitem, the binder will invoke <tt> saveOrder() </tt> in a ViewModel.
+
* When clicking "Save" button or menuitem, the binder will invoke <code>saveOrder()</code> in a ViewModel.
  
  
Line 54: Line 56:
  
 
== Empty Command ==
 
== Empty Command ==
If we specify command name with an '''empty string literal''' or evaluation result of EL inside <tt> @command() </tt> is '''null''', the binder will ignore that command. It's handy if you want to do nothing in some cases. For example:
+
If we specify command name with an '''empty string literal''' or evaluation result of EL inside <code>@command()</code> is '''null''', the binder will ignore that command. It's handy if you want to do nothing in some cases. For example:
  
 
'''Empty command'''
 
'''Empty command'''
Line 71: Line 73:
 
   since 6.5.1
 
   since 6.5.1
  
We can apply '''<tt>@DefaultCommand</tt>''' to mark a method as a default command method which is invoked only if a command binding doesn't match any other command methods. When a binder receives a command, it starts to find ViewModel's command methods by matching its name. Only if the binder cannot find a matched method, it invokes default command method.  
+
We can apply '''<code>@DefaultCommand</code>''' to mark a method as a default command method which is invoked only if a command binding doesn't match any other command methods. When a binder receives a command, it starts to find ViewModel's command methods by matching its name. Only if the binder cannot find a matched method, it invokes default command method.  
  
 
Assume that there are only two command methos in the below ViewModel. If we trigger a command "exit", a binder invokes the default command method  
 
Assume that there are only two command methos in the below ViewModel. If we trigger a command "exit", a binder invokes the default command method  
<tt>defaultAction()</tt> because it cannot find a command method named "exit".
+
<code>defaultAction()</code> because it cannot find a command method named "exit".
  
 
'''ViewModel with default command method'''
 
'''ViewModel with default command method'''
<source lang="java" high="8">
+
<source lang="java" highlight="8">
 
public class OrderVM {
 
public class OrderVM {
  
Line 94: Line 96:
 
= Command Execution =
 
= Command Execution =
  
A command execution is a mechanism of ZK Bind where it performs a method call on the ViewModel. It binds to a component's event and when a binding event comes, binder will follow the life-cycle to complete the execution. There are 6 phases in the <tt>COMMAND</tt> execution: <tt>VALIDATION</tt>, <tt>SAVE-BEFORE</tt>, <tt>LOAD-BEFORE</tt>, <tt>EXECUTE</tt>, <tt>SAVE-AFTER</tt>, <tt>LOAD-AFTER</tt>.
+
A command execution is a mechanism of ZK Bind where it performs a method call on the ViewModel. It binds to a component's event and when a binding event comes, binder will follow the life-cycle to complete the execution. There are 6 phases in the <code>COMMAND</code> execution: <code>VALIDATION</code>, <code>SAVE-BEFORE</code>, <code>LOAD-BEFORE</code>, <code>EXECUTE</code>, <code>SAVE-AFTER</code>, <code>LOAD-AFTER</code>.
  
 
===Saving and Loading in Command Execution===
 
===Saving and Loading in Command Execution===
  
You could save multiple values to ViewModel at the same time before or after the <tt>EXECUTE</tt> phase (i.e., call the ViewModel's command method) by using the <tt>@save(expression, before|after='a-command')</tt> syntax (use this syntax, the value will not be saved immediately after being edited by user). You can also load values to a component before or after the <tt>EXECUTE</tt> phase by using the <tt>@load(expression, before|after='a-command')</tt> syntax.
+
You could save multiple values to ViewModel at the same time before or after the <code>EXECUTE</code> phase (i.e., call the ViewModel's command method) by using the <code>@save(expression, before|after='a-command')</code> syntax (use this syntax, the value will not be saved immediately after being edited by user). You can also load values to a component before or after the <code>EXECUTE</code> phase by using the <code>@load(expression, before|after='a-command')</code> syntax.
  
 
===Validation in Command Execution===
 
===Validation in Command Execution===
  
Validation is also included in the command execution. It is performed in the <tt>VALIDATION</tt> phase before any other phases. If there are multiple save bindings that depend on the same command, all validators of binding will be called in the <tt>VALIDATION</tt> phase. If a validator said invalid; the execution will be broken, and ignored in the remaining phases.
+
Validation is also included in the command execution. It is performed in the <code>VALIDATION</code> phase before any other phases. If there are multiple save bindings that depend on the same command, all validators of binding will be called in the <code>VALIDATION</code> phase. If a validator said invalid; the execution will be broken, and ignored in the remaining phases.
  
 
===Phases of Command Execution===
 
===Phases of Command Execution===
Line 110: Line 112:
 
[[File:Mvvm-command-execution.png | center | 300px ]]
 
[[File:Mvvm-command-execution.png | center | 300px ]]
  
*When a bound ZK event enters the binder, the <tt>COMMAND</tt> phase will be invoked and all phases within the <tt>COMMAND</tt> phase will start to execute one by one
+
*When a bound ZK event enters the binder, the <code>COMMAND</code> phase will be invoked and all phases within the <code>COMMAND</code> phase will start to execute one by one
*In the <tt>VALIDATION</tt> phase, binder first collects all the properties that needs to be verified. Then, it calls each validator of save-binding that is related to this command. In each call to a validator, binder provides a new <tt>ValidationContext</tt> which contains the main property and other collected properties. This means, you can do dependent validation with collected properties, for example, checking whether the shipping date is larger than the creation date. If any validator reports invalid by calling <tt>ValidationContext.setInvalid ()</tt>, binder ignores all subsequent phases and loads other properties that has been notified for a change.
+
*In the <code>VALIDATION</code> phase, binder first collects all the properties that needs to be verified. Then, it calls each validator of save-binding that is related to this command. In each call to a validator, binder provides a new <code>ValidationContext</code> which contains the main property and other collected properties. This means, you can do dependent validation with collected properties, for example, checking whether the shipping date is larger than the creation date. If any validator reports invalid by calling <code>ValidationContext.setInvalid ()</code>, binder ignores all subsequent phases and loads other properties that has been notified for a change.
*In the <tt>SAVE-BEFORE</tt> phase, binder calls all the save-binding that is relative to the command and mark "before" to save the value to the expression
+
*In the <code>SAVE-BEFORE</code> phase, binder calls all the save-binding that is relative to the command and mark "before" to save the value to the expression
*In the <tt>LOAD-BEFORE</tt> phase, binder calls all the load-binding that is relative to the command and mark "before" to load the value from expression to the component
+
*In the <code>LOAD-BEFORE</code> phase, binder calls all the load-binding that is relative to the command and mark "before" to load the value from expression to the component
*In the <tt>EXECUTE</tt> phase, binder calls the command method of the ViewModel. For example, if the command is "saveOrder", it will try to find a method that has annotation <tt>@Command('saveOrder')</tt> or a method which is named <tt>saveOrder()</tt> with <tt>@Command()</tt> of the viewModel, and then call it. If there is no method to execute, it complains with an exception.
+
*In the <code>EXECUTE</code> phase, binder calls the command method of the ViewModel. For example, if the command is "saveOrder", it will try to find a method that has annotation <code>@Command('saveOrder')</code> or a method which is named <code>saveOrder()</code> with <code>@Command()</code> of the viewModel, and then call it. If there is no method to execute, it complains with an exception.
*In the <tt>SAVE-AFTER</tt> phase, binder calls all the save-binding that is relative to the command and mark "after" to save the value to the expression
+
*In the <code>SAVE-AFTER</code> phase, binder calls all the save-binding that is relative to the command and mark "after" to save the value to the expression
*In the <tt>LOAD-AFTER</tt> phase, binder calls all the load-binding that is relative to the command and mark "after" to load the value from expression to component
+
*In the <code>LOAD-AFTER</code> phase, binder calls all the load-binding that is relative to the command and mark "after" to load the value from expression to component
  
  
Line 124: Line 126:
  
 
=Version History=
 
=Version History=
{{LastUpdated}}
+
 
{| border='1px' | width="100%"
+
{| class='wikitable' | width="100%"
 
! Version !! Date !! Content
 
! Version !! Date !! Content
 
|-
 
|-

Latest revision as of 07:35, 8 July 2022

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


Overview

Command binding is a mechanism for hooking up a UI component's event such as button's onClick to ViewModel's Command[1] without writing code. This binding is established by @command with command's name in a ZUL. We can only bind one event to only one Command but can bind multiple events to the same Command.

Command's name is the name of ViewModel's method with Java annotation @Command by default. You can also specify a Command's name in @Command's element.

Command method example

public class OrderVM {
 
    // create and add a new order to a list
    // command name is set to method name by default
    @Command
    public void newOrder(){
        Order order = new Order();
        getOrders().add(order);
        selected = order;//select the new one
    }
 
    // save an order
    // command name is specified
    @Command('save')
    public void saveOrder(){
        orderService.save(selected);
    }
}


Command binding example

	<toolbar>
		<button label="New" onClick="@command('newOrder')" />
		<button label="Save" onClick="@command('save')" />
	</toolbar>

	<menubar>
		<menu label="Order">
			<menupopup >
				<menuitem label="New"  onClick="@command('newOrder')"/>
				<menuitem label="Save"  onClick="@command('save')"/>
			</menupopup>
		</menu>
	</menubar>
  • When clicking "Save" button or menuitem, the binder will invoke saveOrder() in a ViewModel.


You can pass parameters to a command method. Please refer MVVM/Advance/Parameters.


Empty Command

If we specify command name with an empty string literal or evaluation result of EL inside @command() is null, the binder will ignore that command. It's handy if you want to do nothing in some cases. For example:

Empty command

<button onClick="@command(empty vm.selection?'add':''"/>

<button onClick="@command(empty vm.selection?'save':null"/>


Default Command

 since 6.5.1

We can apply @DefaultCommand to mark a method as a default command method which is invoked only if a command binding doesn't match any other command methods. When a binder receives a command, it starts to find ViewModel's command methods by matching its name. Only if the binder cannot find a matched method, it invokes default command method.

Assume that there are only two command methos in the below ViewModel. If we trigger a command "exit", a binder invokes the default command method defaultAction() because it cannot find a command method named "exit".

ViewModel with default command method

public class OrderVM {

    @Command
    public void newOrder(){
    ...
    }
  
    @DefaultCommand
    public void defaultAction(){
    ...
    }
}

Command Execution

A command execution is a mechanism of ZK Bind where it performs a method call on the ViewModel. It binds to a component's event and when a binding event comes, binder will follow the life-cycle to complete the execution. There are 6 phases in the COMMAND execution: VALIDATION, SAVE-BEFORE, LOAD-BEFORE, EXECUTE, SAVE-AFTER, LOAD-AFTER.

Saving and Loading in Command Execution

You could save multiple values to ViewModel at the same time before or after the EXECUTE phase (i.e., call the ViewModel's command method) by using the @save(expression, before|after='a-command') syntax (use this syntax, the value will not be saved immediately after being edited by user). You can also load values to a component before or after the EXECUTE phase by using the @load(expression, before|after='a-command') syntax.

Validation in Command Execution

Validation is also included in the command execution. It is performed in the VALIDATION phase before any other phases. If there are multiple save bindings that depend on the same command, all validators of binding will be called in the VALIDATION phase. If a validator said invalid; the execution will be broken, and ignored in the remaining phases.

Phases of Command Execution

Following is the phases of a Command Execution:

Mvvm-command-execution.png
  • When a bound ZK event enters the binder, the COMMAND phase will be invoked and all phases within the COMMAND phase will start to execute one by one
  • In the VALIDATION phase, binder first collects all the properties that needs to be verified. Then, it calls each validator of save-binding that is related to this command. In each call to a validator, binder provides a new ValidationContext which contains the main property and other collected properties. This means, you can do dependent validation with collected properties, for example, checking whether the shipping date is larger than the creation date. If any validator reports invalid by calling ValidationContext.setInvalid (), binder ignores all subsequent phases and loads other properties that has been notified for a change.
  • In the SAVE-BEFORE phase, binder calls all the save-binding that is relative to the command and mark "before" to save the value to the expression
  • In the LOAD-BEFORE phase, binder calls all the load-binding that is relative to the command and mark "before" to load the value from expression to the component
  • In the EXECUTE phase, binder calls the command method of the ViewModel. For example, if the command is "saveOrder", it will try to find a method that has annotation @Command('saveOrder') or a method which is named saveOrder() with @Command() of the viewModel, and then call it. If there is no method to execute, it complains with an exception.
  • In the SAVE-AFTER phase, binder calls all the save-binding that is relative to the command and mark "after" to save the value to the expression
  • In the LOAD-AFTER phase, binder calls all the load-binding that is relative to the command and mark "after" to load the value from expression to component


References

Version History

Version Date Content
6.0.0 February 2012 The MVVM was introduced.



Last Update : 2022/07/08

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