0

Adding error messages into a form AFTER it has passed its own validation?

asked 2012-06-13 10:54:01 +0800

davout gravatar image davout
1429 3 18

I'm using form validation on a ZUL file where for various reasons I cannot perform absolutely all the validation required until I try to persist the data in the related MVVM 'save' command method.

In this case an exception may occur when the save/persist call is made to underlying DAO tier. In this case I want to push an error message into a ZUL label that displays an element of the 'ValidationMessages' map.

How would I do that from the MVVM view class?

delete flag offensive retag edit

9 Replies

Sort by ยป oldest newest

answered 2012-06-13 17:48:06 +0800

davout gravatar image davout
1429 3 18

How do you find a ValidationContext from within a MVVM view class command method?

link publish delete flag offensive edit

answered 2012-06-14 02:18:26 +0800

dennis gravatar image dennis
3669 1 6
http://www.javaworld.com....

You cannot get ValidationContext in command method, it is too late.
You can write a inner validator in the viewModel, so this validator can share data with this viewModel, (however if the validator mark validation, the command method will not be invoked)
or you can do the validation in the command method directly.

link publish delete flag offensive edit

answered 2012-06-14 05:50:36 +0800

davout gravatar image davout
1429 3 18

Can you supply an example please?

Here's a snippet to show my context, a command method that will delete an entry,

	@Command
	@NotifyChange({ "selectedResource", "resources" })
	public void deleteEntry() {

		if (fSelectedResource.getID() == ID_UNASSIGNED) {
			getResources().remove(fSelectedResource);
			fSelectedResource = null;
		}
		else {
			Messagebox.show("Delete [" + fSelectedResource.getTitle()
					+ "] entry. Are you sure?", "Delete resource required entry",
					new Messagebox.Button[] { Messagebox.Button.YES,
							Messagebox.Button.NO }, Messagebox.QUESTION,
					new EventListener<ClickEvent>() {
						public void onEvent(ClickEvent e) {
							switch (e.getButton()) {
								case YES:
									try {
										resourceRequiredManager
												.delete(fSelectedResource.getID());
										getResources().remove(fSelectedResource);
										fSelectedResource = null;
									}
									catch (UnknownResourceRequiredException ex) {
                                                                                         // how to set validation error??!!
									}
									catch (PersistenceException ex) {
                                                                                         // how to set validation error??!!
									}
									break;
							}
						}
					});
		}

	}



You'll see in the above example where the two exceptions are trapped, I want to somehow set the validation message back into the GUI form.

link publish delete flag offensive edit

answered 2012-06-15 08:09:08 +0800

dennis gravatar image dennis
3669 1 6
http://www.javaworld.com....

updated 2012-06-15 08:16:36 +0800

The case you try to resolve is not a 'validation', it is kind of error handling (so it shouldn't use validation concept).
and, since you are using Messagebox to show a message to show up a confirm window, which means, it goes zk MVC(onEvent) way, it is not controlled by the MVVM binder, directly.
I have some example for you how to do this kind case in MVVM only or MVVM + UI(MVC) togehter.

link publish delete flag offensive edit

answered 2012-06-15 08:10:18 +0800

dennis gravatar image dennis
3669 1 6
http://www.javaworld.com....
the first one, is the basic of MVVM, no many ui effect. the cod like following.
<hbox>
	<window title="Base case" border="1" apply="org.zkoss.bind.BindComposer" 
		viewModel="@id('vm') @init('org.zkoss.mvvm.examples.confirm_delete.ConfirmDeleteBase')">
		<vbox>
			<listbox model="@bind(vm.items)"
				selectedItem="@bind(vm.selected)" width="200px">
				<template name="model" >
					<listitem>
						<listcell label="@load(each)" />
					</listitem>
				</template>
			</listbox>
		</vbox>
		<label value="@load(vm.message)" />
		<hbox>
			<button label="delete" disabled="@load(empty vm.selected)" onClick="@command('delete')" />
		</hbox>
	</window>
</hbox>
package org.zkoss.mvvm.examples.confirm_delete;

import java.util.ArrayList;
import java.util.List;

import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.NotifyChange;

public class ConfirmDeleteBase {

	List<String> items = new ArrayList<String>();
	
	String selected;
	
	String message;
	
	public ConfirmDeleteBase(){
		items.add("A");
		items.add("B");
		items.add("C");
	}
	
	public List<String> getItems(){
		return items;
	}

	public String getSelected() {
		return selected;
	}

	public void setSelected(String selected) {
		this.selected = selected;
	}
	
	public String getMessage() {
		return message;
	}
	
	@Command @NotifyChange({"message","items","selected"})
	public void delete(){
		if(selected==null){
			message = "You have to select an item";
		}else{
			try{
				if(daoDelete(selected)){
					items.remove(selected);
					message = selected + " was deleted";
					selected = null;
				}else{
					message = selected + " wasn't deleted";
				}
			}catch(Exception x){
				message = x.getMessage();
			}
		}
	}
	
	protected boolean daoDelete(String data){
		if("B".equals(selected)){
			throw new RuntimeException("Oops, I simulate delete "+data+" fial here");
		}
		return true;
	}
}

link publish delete flag offensive edit

answered 2012-06-15 08:12:41 +0800

dennis gravatar image dennis
3669 1 6
http://www.javaworld.com....

updated 2012-06-15 08:18:29 +0800

then here if we want to handle confirm status/message, we have to create some data in MVVM model.
<hbox>
	<window title="Case 1" border="1" apply="org.zkoss.bind.BindComposer" 
		viewModel="@id('vm') @init('org.zkoss.mvvm.examples.confirm_delete.ConfirmDelete1')">
		<vbox>
			<listbox model="@bind(vm.items)"
				selectedItem="@bind(vm.selected)" width="200px">
				<template name="model" >
					<listitem>
						<listcell label="@load(each)" ></listcell>
					</listitem>
				</template>
			</listbox>
		</vbox>
		<label value="@load(vm.message)" ></label>
		<hbox>
			<button label="delete" disabled="@load(empty vm.selected)" 
				onClick="@command(vm.needToConfirm?'showConfirm':'delete')" ></button>
		</hbox>
		<window title="Confirm " mode="modal" visible="@load(not empty vm.confirmMessage)" border="1" width="300px">
			<vbox hflex="1" pack="center" align="center" style="padding:10px">
				<label value="@load(vm.confirmMessage)"></label>
				<hlayout> 
					<button label="Delete" onClick="@command('delete')" ></button>
					<button label="Cancel" onClick="@command('cancelConfirm')" ></button>
				</hlayout>
			</vbox>
		</window>
	</window>
</hbox>
package org.zkoss.mvvm.examples.confirm_delete;

import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.NotifyChange;

public class ConfirmDelete1 extends ConfirmDeleteBase{

	
	String confirmMessage;
	
	public String getConfirmMessage(){
		return confirmMessage;
	}
	
	@Command @NotifyChange("confirmMessage")
	public void cancelConfirm(){
		confirmMessage = null;
	}
	
	@Command @NotifyChange("confirmMessage")
	public void showConfirm(){
		confirmMessage = "Do you really want to delete "+selected;
	}
	
	@Override
	@Command @NotifyChange({"message","items","selected","confirmMessage"})
	public void delete(){
		super.delete();
		confirmMessage = null;
		//clean confirmMessage and notify
	}
	
	public boolean isNeedToConfirm(){
		//simulate C doesn't need to be confirm
		if("C".equals(selected)){
			return false;
		}
		return true;
	}	
}

link publish delete flag offensive edit

answered 2012-06-15 08:14:59 +0800

dennis gravatar image dennis
3669 1 6
http://www.javaworld.com....

updated 2012-06-15 08:15:36 +0800

the 2nd example, it combines MVVM + UI, the code is more clear then MVVM only, but it will has UI instance in the viewmodel.
<hbox>
	<window title="Case 1" border="1" apply="org.zkoss.bind.BindComposer" 
		viewModel="@id('vm') @init('org.zkoss.mvvm.examples.confirm_delete.ConfirmDelete2')">
		<vbox>
			<listbox model="@bind(vm.items)"
				selectedItem="@bind(vm.selected)" width="200px">
				<template name="model" >
					<listitem>
						<listcell label="@load(each)" ></listcell>
					</listitem>
				</template>
			</listbox>
		</vbox>
		<label value="@load(vm.message)" ></label>
		<hbox>
			<button label="delete" disabled="@load(empty vm.selected)" 
				onClick="@command(vm.needToConfirm?'showConfirm':'delete')" ></button>
		</hbox>
	</window>

</hbox>
package org.zkoss.mvvm.examples.confirm_delete;

import org.zkoss.bind.Binder;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Messagebox.ClickEvent;

public class ConfirmDelete2 extends ConfirmDeleteBase{

	
	@Command
	public void showConfirm(@ContextParam(ContextType.BINDER) final Binder binder){
		Messagebox.show("Do you really want to delete "+selected,"Confirm",
				new Messagebox.Button[] { Messagebox.Button.YES,Messagebox.Button.NO },
				Messagebox.QUESTION,new EventListener<ClickEvent>() {
			public void onEvent(ClickEvent event) throws Exception {
				switch (event.getButton()) {
					case YES:
						//if you call super.delete here, since original zk event is not control by binder
						//the change of viewmodel will not update to the ui.
						//so, I post a delete to trigger to process it in binder controll.
						binder.postCommand("delete", null);
				}
			}
		});
	}
	
	@Override
	protected boolean daoDelete(String data){
		try{
			super.daoDelete(data);
			return true;
		}catch(Exception x){
			Messagebox.show(x.getMessage());
		}
		return false;
	}
	
	public boolean isNeedToConfirm(){
		//simulate C doesn't need to be confirm
		if("C".equals(selected)){
			return false;
		}
		return true;
	}	
}

link publish delete flag offensive edit

answered 2012-06-15 12:28:54 +0800

davout gravatar image davout
1429 3 18

In my ZUL file I have...

<panel title="@load(vm.viewTitle)" height="100%" width="100%"
	apply="org.zkoss.bind.BindComposer"
	viewModel="@id('vm') @init('com.eis.zk.plan.entity.detail.PlanEntityResourceEditVM')"
	binder="@init(queueName='DataAreaQueue')" validationMessages="@id('vmsgs')">


Is it possible to access the 'vmsgs' variable from the Model View class?

link publish delete flag offensive edit

answered 2012-06-18 04:56:50 +0800

dennis gravatar image dennis
3669 1 6
http://www.javaworld.com....

updated 2012-06-18 04:57:12 +0800

it is not a public object and I suggest you create your own message object in you viewmodel and control your self if you want show message for a command execution.

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2012-06-13 10:54:01 +0800

Seen: 302 times

Last updated: Jun 18 '12

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More