0

Datebox constraint message

asked 2012-11-23 13:06:38 +0800

Neus gravatar image Neus
1415 14

Hi,
If I have this constraint set to a datebox: "before 20121130" when I set a wrong date the error message says "Valor fuera de rango: <= 20121130". Is there a way to make the message format the date like 30/11/2012 or just 30112012 ???

Thank you!

delete flag offensive retag edit

7 Replies

Sort by » oldest newest

answered 2012-11-23 18:14:51 +0800

rdgrimes gravatar image rdgrimes
735 7

updated 2012-11-23 18:24:57 +0800

I tested this out and it works:

ZUL

<?page title="new page title" contentType="text/html;charset=UTF-8"?>
<zk>
<window title="new page title" border="normal" 
        apply="org.zkoss.bind.BindComposer"
        viewModel="@id('vm') @init('TestViewModel')">

	 <datebox id="myDate" constraint="@bind(vm.myDateConstraint)"  
                  value="@bind(vm.myDate)" />
</window>
</zk>

TestViewModel


import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;

import org.zkoss.zul.SimpleDateConstraint;

public class TestViewModel 
{
	private static final SimpleDateFormat SDF = new SimpleDateFormat("dd-MM-yyyy");
	
	private SimpleDateConstraint sdc;
	private Date constraintDate;
	private Date myDate;
	
	public Date getMyDate()
	{
		if (myDate == null)
		{
			myDate = new GregorianCalendar().getTime();
		}
		
		return myDate;
	}
	public void setMyDate(Date myDate)
	{
		this.myDate = myDate;
	}
	
        public SimpleDateConstraint getMyDateConstraint() 
        {
    	       constraintDate = new GregorianCalendar(2012, 10, 30).getTime();
    	
    	       sdc = new SimpleDateConstraint("before 20121130: " + 
                                              "Error! Date " + SDF.format(getMyDate()) + 
                                              " is before " + SDF.format(constraintDate));
    	
               return sdc;
        }
	
	public void setMyDateConstraint(SimpleDateConstraint sdc)
	{
		this.sdc = sdc;
	}
}

link publish delete flag offensive edit

answered 2012-11-29 08:39:24 +0800

Neus gravatar image Neus
1415 14

Thank you rdgrimes. It works!

link publish delete flag offensive edit

answered 2012-11-29 10:22:22 +0800

Neus gravatar image Neus
1415 14

Something more...

as you can see in this picture

constraint message is shown before format the value of the datebox. Will it be possible to format the value before the error message appears?

link publish delete flag offensive edit

answered 2012-11-29 11:49:41 +0800

Neus gravatar image Neus
1415 14

Or is there a way to clear the wrong value when the exception is thrown?

link publish delete flag offensive edit

answered 2012-11-29 12:09:46 +0800

Neus gravatar image Neus
1415 14

Or a last question...how would you manage the constraints between these dateboxes?
These are my functions. setConstraint is called from onChange event of both dateboxes. I tried two ways to do it. I show you both ways
setConstraint version 1:

/**
 * Añade una constraint a los datebox. La fecha del primer datebox no puede ser mayor a la fecha
 * del segundo y al inrevés.
 * @param dbDesde Datebox con la fecha DESDE. No puede ser mayor al segundo datebox
 * @param dbHasta Datebox con la fecha HASTA. No puede ser menor al primer datebox
 */
public static void setConstraint(Datebox dbDesde, Datebox dbHasta, Datebox dbModificado){
	MaestroLiterales ml;
	int idioma = VariablesSesion.getIdioma();
	ml = new MaestroLiterales(idioma);
	dbDesde.clearErrorMessage(true);
	dbHasta.clearErrorMessage(true);
	System.out.println("valor desde -> " + dbDesde.getValue());
	System.out.println("valor hasta -> " + dbHasta.getValue());
	//Quitamos la constraint del datebox al que se le acaba de introducir el dato
	dbModificado.setConstraint((String) null);
	dbModificado.invalidate(); //Lo repintamos porque si no no se actualiza la constraint
	//Ponemos la constraint al datebox que no se ha modificado
	if(dbModificado == dbDesde){
		setConstraintHasta(dbDesde, dbHasta, ml);
		dbHasta.getValue();
	}else if(dbModificado == dbHasta){
		setConstraintDesde(dbDesde, dbHasta, ml);
		dbDesde.getValue();
	}
	System.out.println("DBDesde constraint-> " + dbDesde.getConstraint());
	System.out.println("DBHasta constraint-> " + dbHasta.getConstraint());
	
	
	dbDesde.clearErrorMessage(true);
	dbHasta.clearErrorMessage(true);
	setConstraintHasta(dbDesde, dbHasta,ml);
	setConstraintDesde(dbDesde, dbHasta,ml);
	dbDesde.getValue();
	dbHasta.getValue();
}

setConstraint version 2:
/**
 * Añade una constraint a los datebox. La fecha del primer datebox no puede ser mayor a la fecha
 * del segundo y al inrevés.
 * @param dbDesde Datebox con la fecha DESDE. No puede ser mayor al segundo datebox
 * @param dbHasta Datebox con la fecha HASTA. No puede ser menor al primer datebox
 */
public static void setConstraint(Datebox dbDesde, Datebox dbHasta, Datebox dbModificado){
	MaestroLiterales ml;
	int idioma = VariablesSesion.getIdioma();
	ml = new MaestroLiterales(idioma);
	dbDesde.clearErrorMessage(true);
	dbHasta.clearErrorMessage(true);
	System.out.println("valor desde -> " + dbDesde.getValue());
	System.out.println("valor hasta -> " + dbHasta.getValue());
	//Quitamos la constraint del datebox al que se le acaba de introducir el dato
	dbModificado.setConstraint((String) null);
	dbModificado.invalidate(); //Lo repintamos porque si no no se actualiza la constraint
	//Ponemos la constraint al datebox que no se ha modificado
	if(dbModificado == dbDesde){
		setConstraintHasta(dbDesde, dbHasta, ml);
		dbHasta.getValue();
	}else if(dbModificado == dbHasta){
		setConstraintDesde(dbDesde, dbHasta, ml);
		dbDesde.getValue();
	}
	System.out.println("DBDesde constraint-> " + dbDesde.getConstraint());
	System.out.println("DBHasta constraint-> " + dbHasta.getConstraint());
}

/**
 * Añade la constraint al datebox Hasta (su fecha no podrá ser menor que la del datebox Desde)
 * @param dbDesde Datebox con la fecha DESDE. No puede ser mayor al segundo datebox
 * @param dbHasta Datebox con la fecha HASTA. No puede ser menor al primer datebox
 */
private static void setConstraintHasta(Datebox dbDesde, Datebox dbHasta, MaestroLiterales ml){
	if(dbDesde.getValue()==null){
		//El datebox Desde está vacío. Quitamos la constraint del Hasta
		dbHasta.setConstraint((String) null);
		dbHasta.invalidate(); //Lo repintamos porque si no no se actualiza la constraint
	}else{
		//El datebox Desde tiene una fecha
		GregorianCalendar gcDesde = new GregorianCalendar();
		gcDesde.setTime(dbDesde.getValue());
		String anyo;
		String mes;
		String dia;
		anyo=String.valueOf(gcDesde.get(Calendar.YEAR));
		
		//Comprobamos que la longitud de la cadena del año sea 4 debido al formateo por parte de la anterior operacion puesto que la constraint de zk espera una cadena de 4 digitos
		if(anyo.length() < 4){
			//En el caso de que no tenga 4 digitos calculamos cuantos le faltan
			for(int i = 0; i < 4 - anyo.length(); i++ ){
				//Añadimos un 0 por cada vuelta del bucle ya que los habrá perdido al formatear la cadena
				anyo = "0" + anyo;	
			}
		}
		//Al mes tenemos que sumarle 1 porque empieza por 0 (enero es 0)
		if(String.valueOf(gcDesde.get(Calendar.MONTH)+1).length()==1){
			//Si el mes es solo un digito le añadimos el 0 delante porque para la constraint
			//necesitamos que el formato de la fecha sea yyyyMMdd
			mes = "0"+String.valueOf(gcDesde.get(Calendar.MONTH)+1);
		}else{
			//El mes ya tiene más de un dígito
			mes = String.valueOf(gcDesde.get(Calendar.MONTH)+1);
		}
		if(String.valueOf(gcDesde.get(Calendar.DATE)).length()==1){
			//Si el dia es solo un digito le añadimos el 0 delante porque para la constraint
			//necesitamos que el formato de la fecha sea yyyyMMdd
			dia = "0"+gcDesde.get(Calendar.DATE);
		}else{
			//El día ya tiene más de un dígito
			dia = String.valueOf(gcDesde.get(Calendar.DATE));
		}
		//Establecemos la constraint. after yyyyMMdd (sin separadores)
		String constraint = anyo+mes+dia;
		SimpleDateConstraint sdc = new SimpleDateConstraint("after " + constraint+": La fecha tiene que ser igual o posteriro a "+ dia+"/"+mes+"/"+anyo);
		dbHasta.setConstraint(sdc);
	}
}
/**
 * Añade la constraint al datebox Desde (su fecha no podrá ser mayor que la del datebox Hasta)
 * @param dbDesde Datebox con la fecha DESDE. No puede ser mayor al segundo datebox
 * @param dbHasta Datebox con la fecha HASTA. No puede ser menor al primer datebox
 */
private static void setConstraintDesde(Datebox dbDesde, Datebox dbHasta, MaestroLiterales ml){
	if(dbHasta.getValue()==null){
		//El datebox Hasta está vacío. Quitamos al contraint del Desde
		dbDesde.setConstraint((String) null);
		dbDesde.invalidate(); //Repintamos el Datebox porque si no no borra la contraint
	}else{
		//El datebox Hasta tiene una fecha
		GregorianCalendar gcHasta = new GregorianCalendar();
		gcHasta.setTime(dbHasta.getValue());
		String anyo;
		String mes;
		String dia;
		anyo=String.valueOf(gcHasta.get(Calendar.YEAR));
		//Comprobamos que la longitud de la cadena del año sea 4 debido al formateo por parte de la anterior operacion puesto que la constraint de zk espera una cadena de 4 digitos
		if(anyo.length() < 4){
			//En el caso de que no tenga 4 digitos calculamos cuantos le faltan
			for(int i = 0; i < 4 - anyo.length(); i++ ){
				//Añadimos un 0 por cada vuelta del bucle ya que los habrá perdido al formatear la cadena
				anyo = "0" + anyo;	
			}
		}
		//Al mes tenemos que sumarle 1 porque empieza por 0 (enero es 0)
		if(String.valueOf(gcHasta.get(Calendar.MONTH)+1).length()==1){
			//Si el mes es solo un digito le añadimos el 0 delante porque para la constraint
			//necesitamos que el formato de la fecha sea yyyyMMdd
			mes = "0"+String.valueOf(gcHasta.get(Calendar.MONTH)+1);
		}else{
			//El mes ya tiene más de un dígito
			mes = String.valueOf(gcHasta.get(Calendar.MONTH)+1);
		}
		if(String.valueOf(gcHasta.get(Calendar.DATE)).length()==1){
			//Si el dia es solo un digito le añadimos el 0 delante porque para la constraint
			//necesitamos que el formato de la fecha sea yyyyMMdd
			dia = "0"+gcHasta.get(Calendar.DATE);
		}else{
			//El día ya tiene más de un dígito
			dia = String.valueOf(gcHasta.get(Calendar.DATE));
		}
		//Establecemos la constraint. before yyyyMMdd (sin separadores)
		SimpleDateConstraint sdc = new SimpleDateConstraint("before " + anyo+mes+dia+": La fecha tiene que ser igual o anterior a " + dia+"/"+mes+"/"+anyo);
		dbDesde.setConstraint(sdc);
	}
}

I would really appreciate any suggestion because I've been fighting with it for a long time and I don't have anything clear!

Thank you!

link publish delete flag offensive edit

answered 2012-11-29 20:29:37 +0800

rdgrimes gravatar image rdgrimes
735 7

updated 2012-11-29 20:38:55 +0800

I have something similar with a "from" and "to" date wherein, when the from date is changed, I want to change the value and constraint of the "to" date box so that the "to" date must be after the from date and within a month thereof.

ZUL:

<row>
	<cell>
		<label value="Date From:" sclass="strongLabel" ></label>
	</cell>
	<cell colspan="4">
		<datebox id="fromDate" constraint="no future" value="@bind(vm.fromDate)" ></datebox>
		<space width="10px" ></space>					
		<label value="to:" sclass="strongLabel" ></label>
		<space width="10px" ></space>					
		<datebox id="toDate" constraint="@bind(vm.toDateConstraint)" value="@bind(vm.toDate)" ></datebox>
		<space width="5px" ></space>					
		<button id="submit" dir="reverse" 
				image="assets/images/arrow-right.png"
				label="go" onClick="@command('showCreditMemoSummary')" ></button>
	</cell>
</row>

ViewModel:

	public SimpleDateConstraint getToDateConstraint()
	{
		Calendar futureDate = new GregorianCalendar();
		futureDate.setTime(fromDate);
		futureDate.add(Calendar.MONTH, 1);
		
		toDateConstraint = 
				new SimpleDateConstraint("between " + CONSTRAINT_DATE.format(fromDate) + " and " + CONSTRAINT_DATE.format(futureDate.getTime()));

		return toDateConstraint;
	}

	public void setToDateConstraint(SimpleDateConstraint constraint)
	{
		toDateConstraint = constraint;
	}

	public Date getFromDate()
	{
		// First time, set to component preference definition.		
		if (fromDate == null)
		{
			Calendar now = getNow();			
			fromDate = now.getTime();

			if (componentPreference != null)
			{
				if (componentPreference.getFromValueAgo().compareTo(0L) == 0)
				{
					fromDate.setTime(now.getTimeInMillis() - (2 * MS_PER_DAY));
				} else
				{
					long prefMS = componentPreference.getFromValueAgo() * ((long) MS_PER_DAY);
					fromDate.setTime(now.getTimeInMillis() - prefMS);
				}
			} else
			{
				fromDate.setTime(now.getTimeInMillis() - (2 * MS_PER_DAY));
			}
		}

		return fromDate;
	}

	public void setFromDate(Date fromDate)
	{
		this.fromDate = fromDate;
		
		// Adjust to date based on from date.
		Calendar futureDate = new GregorianCalendar();
		futureDate.setTime(getToDateConstraint().getBeginDate());
		futureDate.add(Calendar.DATE, 2);
		toDate = futureDate.getTime();
		
	}

	public Date getToDate()
	{
		// First time, set to component preference definition.
		if (toDate == null)
		{
			Calendar now = getNow();			
			toDate = now.getTime();

			if (componentPreference != null)
			{
				if (componentPreference.getToValueAgo().compareTo(0L) == 0)
				{
					toDate.setTime(now.getTimeInMillis());
				} else
				{
					long prefMS = componentPreference.getToValueAgo() * ((long) MS_PER_DAY);
					toDate.setTime(now.getTimeInMillis() - prefMS);
				}
			}
		}

		return toDate;
	}

	public void setToDate(Date toDate)
	{
		this.toDate = toDate;
	}

The key here is that, in the setFromDate() method, I change the toDateConstraint and force the toDate itself to a value that is after the fromDate. This triggers the BindComposer to update the ZUL toDate box with the appropriate value and constraint.

Note that, if you do it this way, you completely avoid the ability of the user to select an incorrect date range.

link publish delete flag offensive edit

answered 2012-11-30 08:40:57 +0800

Neus gravatar image Neus
1415 14

But you are always changing the To Date when user changes the From?I think sometimes it will be annoying. So I think change it only when the date is wrong. But it doesn't solve my problem.
Imagine this situation:
User set "From Date" to 23/11/2012, the constraint is set to "To Date". But he can also write to "To Date" a wrong date like 21/11/2012. If he writes it, the exception caused by the constraint is thrown. But in the datebox still appears the date he wrotes (21/11/2012).
Then he decied the wrong date is the one set in "From". So he canges it to 20/11/2012. He thinks that now the period is correct. But the reality is that as the exception has been thrown "To Datebox" doesn't have the value he entered.
With your code I undestand that as user has changed From Date, To Date will be automatically changed.
In my thoughts although user sees in screen a correct period "To Date" will be changed because as the exception has been thrown the datebox really doesn't have the value set. Then user will be annoyed because he has entered a correct period but the application has changed it.
(I know maybe it's difficult to understand my explanation hehe)
So my solution will be...If the exception is thrown the value also has to be set or if the exception is thrown as the datebox won't have the value, clean the text! But I don't know how to do any of it

Correct me if I'm wrong :)

Thank you!

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-11-23 13:06:38 +0800

Seen: 235 times

Last updated: Nov 30 '12

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