ZK实际应用:MVVM –与ZK客户端API一起使用

在之前的文章中,我们使用ZK的MVVM实现了以下功能:
  • 将数据加载到表中
  • 使用表单绑定保存数据
  • 删除条目并以编程方式更新视图

ZK MVVM和ZK MVC实现方式之间的主要区别是,我们不直接在controller(ViewModel)类中访问和操作UI组件。 在本文中,我们将看到如何将某些UI操作委派给客户端代码,以及如何将参数从View传递到ViewModel。

目的

为我们的简单清单CRUD功能构建更新功能。 用户可以在表中就地编辑条目,并可以选择更新或放弃所做的更改。 修改后的条目以红色突出显示。

ZK实战功能

  • ZK客户端API
  • ZK风格班
  • MVVM:将参数从视图传递到ViewModel

分步实施  

在列表框中启用就地编辑,以便我们可以编辑条目:

<listcell><textbox inplace="true" value="@load(each.name)" ...</textbox></listcell>....<listcell><doublebox inplace="true" value="@load(each.price)" ...</textbox></listcell>...
  • inplace =” true”呈现输入元素,例如Textbox,但其边框未显示为纯标签; 仅当选择输入元素时才显示边框
  • 第2、6行,“每个”指的是数据收集中的每个Item对象

编辑条目后,我们希望为用户提供更新或放弃更改的选项。
仅当用户对列表框条目进行了修改时,“更新”和“放弃”按钮才需要可见。 首先,我们定义JavaScript函数以显示和隐藏“更新”和“放弃”按钮:

<toolbar>...<span id="edit_btns" visible="false" ...><toolbarbutton label="Update" .../><toolbarbutton label="Discard" .../></span>
</toolbar><script type="text/javascript">function hideEditBtns(){jq('$edit_btns').hide();}function showEditBtns(){ jq('$edit_btns').show();}</script>...
  • 第2行,我们包装了Update and Discard ,并将可见性设置为false
  • 第9、13行中,我们定义了分别隐藏和显示“ 更新”和“ 放弃”按钮的函数
  • 第11、15行,我们使用jQuery选择器jq('$ edit_btns')检索ID为“ edit_btns”的ZK小部件; 请注意,ZK小部件ID的选择器模式为“ $”,而不是“#”

修改列表框中的条目后,我们将使“更新/丢弃”按钮可见,并使修改后的值变为红色。 单击“更新”或“放弃”按钮后,我们想再次隐藏按钮

由于这是纯UI交互,因此我们将使用ZK的客户端API:

<style>.inputs { font-weight: 600; }.modified { color: red; }
</style>
...<toolbar xmlns:w="client" >...<span id="edit_btns" visible="false" ...><toolbarbutton label="Update" w:onClick="hideEditBtns()" .../><toolbarbutton label="Discard" w:onClick="hideEditBtns()" .../></span></toolbar><script type="text/javascript">//show hide functionszk.afterMount(function(){jq('.inputs').change(function(){showEditBtns();$(this).addClass('modified');})});</script>...<listcell><doublebox inplace="true" sclass="inputs" value="@load(each.price)" ...</textbox></listcell>...
  • 第2行,我们为输入元素(文本框,Intbox,Doublebox,日期框)指定样式类,并将其分配给输入元素的sclass属性,例如。 第26行; sclass为ZK小部件定义样式类
  • 在第18〜20行,我们通过匹配它们的sclass名称获得所有输入元素,并分配一个onChange事件处理程序。 更改输入元素中的值后,“更新/丢弃”按钮将变为可见,并且修改后的值将以红色突出显示。
  • 第17行,在创建ZK小部件时运行zk.afterMount
  • 在第6行,我们指定了客户端名称空间,因此我们可以使用语法“ w:onClick”注册客户端onClick事件侦听器。 请注意,我们仍然可以注册通常在服务器上同时处理的onClick事件侦听器。
  • 第9、10行,我们为客户端分配了onClick事件监听器; hideEditBtns函数将被调用以使按钮再次不可见

定义一种将修改后的Item对象存储到集合中的方法,以便如果用户选择这样做,则可以批量更新更改:

public class InventoryVM {private HashSet<Item> itemsToUpdate = new HashSet<item>();...@Commandpublic void addToUpdate(@BindingParam("entry") Item item){itemsToUpdate.add(item);}
  • 第6行,我们将此方法注释为命令方法,以便可以从View调用它
  • 第7行, @ BindingParam(“ entry”)项目项绑定了一个名为“ entry”的任意命名的参数; 我们预计参数将为Item类型

创建一种方法来更新在视图中对数据模型所做的更改

public class InventoryVM {private List<Item> items;private HashSet<Item> itemsToUpdate = new HashSet<item>();...@NotifyChange("items")@Commandpublic void updateItems() throws Exception{for (Item i : itemsToUpdate){i.setDatemod(new Date());DataService.getInstance().updateItem(i);}itemsToUpdate.clear();items = getItems();}

对列表框条目进行修改后,请调用addToUpdate方法并将经过编辑的Item对象传递给该方法,该对象又被保存到itemsToUpdate集合

<listitem><listcell><doublebox value="@load(each.price) @save(each.name, before='updateItems')"  onChange="@command('addToUpdate',entry=each)" /></listcell>...
</listitem>
  • @save(each.name,before ='updateItems')确保除非调用updateItems(即,当用户单击“更新”按钮时),否则不保存修改后的值。

最后,当用户单击更新时,我们调用updateItems方法来更新对数据模型的更改。 如果单击“丢弃”,我们将调用getItems刷新列表框,而不进行任何更改

...<toolbarbutton label="Update" onClick="@command('updateItems')" .../><toolbarbutton label="Discard" onClick="@command('getItems')" .../>...

简而言之

  • 在MVVM模式下,我们努力使ViewModel代码独立于任何View组件
  • 由于我们没有直接引用ViewModel代码中的UI组件,因此可以使用ZK的客户端API将UI操作(在示例代码中,显示/隐藏,样式更改)代码委托给客户端
  • 我们可以在ZK客户端使用jQuery选择器和API
  • 我们可以使用@BindingParam轻松地将参数从View传递到ViewModel

接下来,在处理MVVM验证器和转换器之前,我们将详细介绍ZK样式。  

ViewModel(动作中的ZK [0]〜[3]):

public class InventoryVM {private List<Item> items;private Item newItem;private Item selected;private HashSet<Item> itemsToUpdate = new HashSet<Item>();public InventoryVM(){}//CREATE@NotifyChange("newItem")@Commandpublic void createNewItem(){newItem = new Item("", "",0, 0,new Date());}@NotifyChange({"newItem","items"})@Commandpublic void saveItem() throws Exception{DataService.getInstance().saveItem(newItem);newItem = null;items = getItems();}@NotifyChange("newItem")@Commandpublic void cancelSave() throws Exception{newItem = null;}//READ@NotifyChange("items")@Commandpublic List<Item> getItems() throws Exception{items = DataService.getInstance().getAllItems();for (Item j : items){System.out.println(j.getModel());}Clients.evalJavaScript("zk.afterMount(function(){jq('.inputs').removeClass('modified').change(function(){$(this).addClass('modified');showEditBtns();})});"); //how does afterMount work in this case?return items;}//UPDATE@NotifyChange("items")@Commandpublic void updateItems() throws Exception{for (Item i : itemsToUpdate){i.setDatemod(new Date());DataService.getInstance().updateItem(i);}itemsToUpdate.clear();items = getItems();}@Commandpublic void addToUpdate(@BindingParam("entry") Item item){itemsToUpdate.add(item);}//DELETE@Commandpublic void deleteItem() throws Exception{if (selected != null){String str = "The item with name \""+selected.getName()+"\" and model \""+selected.getModel()+"\" will be deleted.";Messagebox.show(str,"Confirm Deletion", Messagebox.OK|Messagebox.CANCEL, Messagebox.QUESTION, new EventListener<Event>(){@Overridepublic void onEvent(Event event) throws Exception {if (event.getName().equals("onOK")){DataService.getInstance().deleteItem(selected);items = getItems();BindUtils.postNotifyChange(null, null, InventoryVM.this, "items");}}});} else {Messagebox.show("No Item was Selected");} }public Item getNewItem() {return newItem;}public void setNewItem(Item newItem) {this.newItem = newItem;}public Item getselected() {return selected;}public void setselected(Item selected) {this.selected = selected;}
}

视图(ZK处于活动状态[0]〜[3]):

<zk><style>.z-toolbarbutton-cnt { font-size: 17px;} .edit-btns {border: 2pxsolid #7EAAC6; padding: 6px 4px 10px 4px; border-radius: 6px;}.inputs { font-weight: 600; } .modified { color: red; }</style><script type="text/javascript">function hideEditBtns(){ jq('$edit_btns').hide(); }function showEditBtns(){ jq('$edit_btns').show(); }zk.afterMount(function(){ jq('.inputs').change(function(){$(this).addClass('modified'); showEditBtns(); }) });</script><window apply="org.zkoss.bind.BindComposer"viewModel="@id('vm') @init('lab.sphota.zk.ctrl.InventoryVM')"xmlns:w="client"><toolbar width="100%"><toolbarbutton label="Add"onClick="@command('createNewItem')" /><toolbarbutton label="Delete"onClick="@command('deleteItem')"disabled="@load(empty vm.selected)" /><span id="edit_btns" sclass="edit-btns" visible="false"><toolbarbutton label="Update" onClick="@command('updateItems')" w:onClick="hideEditBtns()"/><toolbarbutton label="Discard"onClick="@command('getItems')" w:onClick="hideEditBtns()" /></span></toolbar><groupbox mold="3d"form="@id('itm') @load(vm.newItem) @save(vm.newItem, before='saveItem')"visible="@load(not empty vm.newItem)"><caption label="New Item"></caption><grid width="50%"><rows><row><label value="Item Name" width="100px"></label><textbox value="@bind(itm.name)" /></row><row><label value="Model" width="100px"></label><textbox value="@bind(itm.model)" /></row><row><label value="Unit Price" width="100px"></label><decimalbox value="@bind(itm.price)"format="#,###.00" constraint="no empty, no negative" /></row><row><label value="Quantity" width="100px"></label><spinner value="@bind(itm.qty)"constraint="no empty,min 0 max 999: Quantity Must be Greater Than Zero" /></row><row><cell colspan="2" align="center"><button width="80px" label="Save" mold="trendy"onClick="@command('saveItem')"  /><button width="80px" label="Cancel" mold="trendy"onClick="@command('cancelSave')" /></cell></row></rows></grid></groupbox><listbox selectedItem="@bind(vm.selected)" model="@load(vm.items) "><listhead><listheader label="Name" sort="auto" hflex="2" /><listheader label="Model" sort="auto" hflex="1" /><listheader label="Quantity" sort="auto" hflex="1" /><listheader label="Unit Price" sort="auto" hflex="1" /><listheader label="Last Modified" sort="auto" hflex="2" /></listhead><template name="model"><listitem><listcell><textbox inplace="true" width="110px" sclass="inputs"value="@load(each.name) @save(each.name, before='updateItems')"onChange="@command('addToUpdate',entry=each)"></textbox></listcell><listcell><textbox inplace="true" width="110px" sclass="inputs" value="@load(each.model) @save(each.model, before='updateItems')"onChange="@command('addToUpdate',entry=each)" /></listcell><listcell><intbox inplace="true" sclass="inputs" value="@load(each.qty) @save(each.qty, before='updateItems')"onChange="@command('addToUpdate',entry=each)" /></listcell><listcell><doublebox inplace="true" sclass="inputs" format="###,###.00" value="@load(each.price) @save(each.price, before='updateItems')"onChange="@command('addToUpdate',entry=each)" /></listcell><listcell label="@load(each.datemod)" /></listitem></template></listbox></window>
</zk>
  • ZK客户端参考
  • ZK开发人员参考:@BindingParam

参考: ZK in Action [3]:MVVM –与我们的JCG合作伙伴 Lance Lu的ZK Client API一起在Tech Dojo博客上工作。


翻译自: https://www.javacodegeeks.com/2012/07/zk-in-action-mvvm-working-together-with.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372127.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

终极JPA查询和技巧列表–第1部分

我们可以在Internet上找到一些JPA“如何做”&#xff0c;在本博客的此处&#xff0c;教您如何使用JPA执行多项任务。 通常&#xff0c;我看到有人问有关使用JPA进行查询的问题。 通常&#xff0c;为了回答此类问题&#xff0c;提供了几个链接&#xff0c;以尝试找到该问题的解决…

Spring集成–第2节–更多世界

这是Spring Integration Session 1的后续活动 第一部分是使用Spring Integration的简单Hello World应用程序。 我想通过考虑其他一些方案来进一步介绍它。 因此&#xff0c;对Hello World应用程序的第一个更改是添加网关组件。 要快速重新访问较早的测试程序&#xff0c;请执行…

oracle 会话实例,返璞归真:Oracle实例级别和会话级别的参数设置辨析

杨廷琨(yangtingkun)云和恩墨 CTO高级咨询顾问&#xff0c;Oracle ACE 总监&#xff0c;ITPUB Oracle 数据库管理版版主参数文件是Oracle数据库文件中级别最低&#xff0c;也是最基本的文件&#xff0c;但是也是数据库实例启动第一个涉及的文件。如果参数文件缺失或者某些参数设…

在多节点集群中运行Cassandra

这篇文章收集了我在多节点中设置Apache Cassandra集群的步骤。 在设置集群时&#xff0c;我已经参考了Cassandra Wiki和Datastax文档。 详细介绍了以下过程&#xff0c;分享了我建立群集的经验。 设置第一个节点 添加其他节点 监视集群– nodetool &#xff0c; jConsole &am…

Oracle 添加 scott 示例用户

学习SQL有一段时间了&#xff0c;但是也忘记的差不多了&#xff0c;今天有赶紧复习复习&#xff0c;然后发现一个问题&#xff0c;为啥之前看的视频教程&#xff0c;马士兵用的Oracle有scott用户和那些表格&#xff0c;而我的没有&#xff1f;难道是Oracle取消了&#xff1f;然…

win8oracle10g安装报错,Win8电脑安装Oracle 10g提示程序异常终止的解决方法

有win8系统用户反映说在安装Oracle 10g的时候&#xff0c;选择高级安装之后&#xff0c;就弹出一个窗口&#xff0c;提示程序异常终止&#xff0c;发生内部错误&#xff0c;导致Oracle 10g安装失败&#xff0c;该怎么解决这样的问题呢&#xff1f;下面随小编一起来看看Win8电脑…

<avatar: frontiers of pandora>技术overview

https://www.eurogamer.net/digitalfoundry-2023-avatar-frontiers-of-pandora-and-snowdrop-the-big-developer-tech-interview https://www.youtube.com/watch?vLRI_qgVSwMY&t394s 主要来自euro gamer上digital foundry对于avatar的开发团队Massive工作室的采访&#xf…

iOS 启动连续闪退保护方案

版权声明&#xff1a;本文由刘笑江原创文章&#xff0c;转载请注明出处: 文章原文链接&#xff1a;https://www.qcloud.com/community/article/79 来源&#xff1a;腾云阁 https://www.qcloud.com/community 一.引言 “如果某个实体表现出以下任何一种特性&#xff0c;它就具备…

实战Java内存泄漏问题分析 -- hazelcast2.0.3使用时内存泄漏 -- 2

hazelcast 提供了3中方法调用startCleanup:第一种是在ConcuurentMapManager的构造函数中&#xff0c;通过调用node的executorManager中的ScheduledExecutorService来创建每秒运行一次cleanup操作的线程&#xff08;代码例如以下&#xff09;。因为这是ConcuurentMapManager构造…

@SuppressLint(NewApi)和@TargetApi()的区别

转自&#xff1a;http://blog.csdn.NET/wbshuang09/article/details/44920549在Android代码中&#xff0c;我们有时会使用比我们在AndroidManifest中设置的android:minSdkVersion版本更高的方法&#xff0c;此时编译器会提示警告&#xff0c;解决方法是在方法上加上SuppressLin…

零基础自学编程前需要知道的知识

你是否适合编程?学习编程后能做什么?如何选择编程语言?有哪些免费的线上学习网站推荐?今天这篇好文将那些自学编程前需要了解和思考的问题都记录下来&#xff0c;希望能给那些刚刚开始或正准备自学编程的朋友们带去一些启发。 你是否适合自学编程 自学编程会是一个漫长而艰…

Eclipse设置黑色主题

1点击help--->install new software 2输入 http://eclipse-color-theme.github.com/update 3下载安装eclipse color theme插件如下图 4完成后点击windows--->preferences------>Appearance下多了一个Color Theme 5,点击选择喜欢的主题即可&#xff0c;也可以自己下载主…

wcf rest系列文章

http://www.cnblogs.com/artech/archive/2012/02/15/wcf-rest.html 需要注意的是&#xff0c;发布的服务&#xff0c;可以在web behavior中指定显示help页面。 http://localhost/ApplicationName/ServiceName.svc/help 需要注意的是&#xff0c;访问.svc的页面一定不要多加/;否…

登录:应用程序错误通知

几个月前&#xff0c;当我进行大型应用程序重构时&#xff0c;发现用于记录日志的基于log4j的代码确实令人讨厌&#xff0c;重复了数百次&#xff1a; if (LOG.isDebugEnabled()) {LOG.debug("Logging some stuff " stuff); }我想摆脱isXXXEnabled&#xff0c;这就…

如何分析线程转储–线程堆栈跟踪

本文是“ 线程转储”分析系列的第5部分。 到目前为止&#xff0c;您已经了解了线程的基本原理以及它们与Java EE容器和JVM的交互。 您还学习了HotSpot和IBM Java VM的不同线程转储格式。 现在是您深入分析过程的时候了。 为了使您能够从线程转储中快速识别问题模式&#xff0c;…

设计模式学习笔记(十三:原型模式)

1.1概述 用原型实例指定创建对象的种类&#xff0c;并且通过复制这些原型创建新的对象。这就是原型模式的定义。 在某些情况下&#xff0c;可能不希望反复使用类的构造方法创建许多对象&#xff0c;而是希望使用该类创建一个对象后&#xff0c;以该对象为原型得到该对象的若干个…

翻译的一篇关于学习编程语言的小文章

Top programming languages to get a job in Toronto in 2017 在程序开发人员和软件工程师中最容易被提及的问题之一就是&#xff1a;“我要学的下一门编程语言该是谁&#xff1f;” 我想去选一个编程语言&#xff0c;我希望你能给我一些关于经常使用到的编程语言的建议&#x…

从linux内核启动,学习Linux内核启动过程:从start_kernel到init

一、实验步骤&#xff1a;1&#xff1a;运行menuos&#xff1a;a)cd LinuxKernel/b)qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img启动后启动了MenuOS。2:使用gdb调试跟踪menuos内核启动和运行过程&#xff1b;a)qemu -kernel linux-3.18.6/arch/x86/bo…

linux强制回收内存,Linu系统cache强制回收

LINUX的内存管理机制&#xff0c;一般情况下不需要特意去释放已经使用的cache。Cache机制的存在&#xff0c;使得Linux对磁盘的读写速度是有较大的好处的。 在 Linux 操作系统中&#xff0c;当应用程序需要读取文件中的数据时&#xff0c;操作系统先分配一些内存&#xff0c;将…

Google API:如何访问Google Analytics(分析)数据?

在深入研究Google Analytics&#xff08;分析&#xff09;API之前&#xff0c;了解一些Google Analytics&#xff08;分析&#xff09;术语及其关系总是很有用的。 Google帐户&#xff1a;要访问Google Analytics&#xff08;分析&#xff09;&#xff0c;用户将需要一个Google…