Howto skip Form validation for a Reload

Hi,

we have a simple page where i can edit my applications users.

The users are listet by a datatable and every row holds a radiobutton with the users id. After clicking on one of this buttons the selected users data should be loaded into my form. All worked well ... until i introduced validation in my form (some required="true" and one email validation). PS: I磎 using MyFaces + Tomahawk.

When I click on my radiobutton, the form gets submitted and validation fails when the form is empty. Due to this validation errors my INVOCE_APPLICATION phase is never called --> my business logic where i load the users data is never executed.

How can i solve this problem?

My idea was to add a phase listener after PROCESS_VALIDATIONS phase where i search for a special named hidden field (e.g. id="do_not_validate") an set the valid state of all invalid components to true (valid) if this field exists. But this does not work at all.

Here my code withoud the hidden field thing:

One interesting point is, that input.setValid( true ) seems not to work, but input.setRequired(false) does it磗 job.

package de.example.jsf.utils;

import java.util.Iterator;

import javax.faces.component.UIComponent;

import javax.faces.component.UIInput;

import javax.faces.component.UIViewRoot;

import javax.faces.context.FacesContext;

import javax.faces.event.PhaseEvent;

import javax.faces.event.PhaseId;

import javax.faces.event.PhaseListener;

import org.apache.log4j.Logger;

publicclass SkipValidationListenerimplements PhaseListener

{

final Loggerlog= Logger.getLogger( this.getClass() );

public SkipValidationListener()

{

}

publicvoid beforePhase( PhaseEvent pe )

{

}

publicvoid afterPhase( PhaseEvent pe )

{

log.info("Try to skip all validation" );

FacesContext cx = JSFUtil.getFacesContext();

UIViewRoot root = cx.getViewRoot();

Iterator it = cx.getClientIdsWithMessages();

while ( it.hasNext() )

{

String id = (String) it.next();

log.info("clientID: " + id );

UIComponent c = root.findComponent( id );

UIInput input = (UIInput) c;

if ( input.isValid() )

log.info("Status valid (" + id +")" );

else

log.info("Status invalid (" + id +")" );

input.setValid(true );

input.saveState( cx );

}

}

public PhaseId getPhaseId()

{

return PhaseId.PROCESS_VALIDATIONS;

}

}

Best regards

[3919 byte] By [zzza] at [2007-11-27 9:47:57]
# 1
Have you tried using the immediate attribute for the radio buttons?
RaymondDeCampoa at 2007-7-13 0:01:09 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 2
Hello, yes i tried that, validation is skipped.The problem is, that in that case the INVOKE_APPLICATION phase is skipped, too. So i have no chance to load my data into the form.
zzza at 2007-7-13 0:01:09 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 3
Setting immediate to true should not skip the Invoke Application phase.
RaymondDeCampoa at 2007-7-13 0:01:09 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 4

Oh, sorry. My fault.

But now i have another problem:

because the selectoneradio tag has no actionListener property (because it磗 no action control) i implemented a invisible commandbutton. When clicking on the radiobutton i call the buttons javascript click() method to simulate a buttonclick and call its actionlistener method. But the model is not updated when i use immediate="true" on the button.

How can i get the value of the radiobuttons?

<div style="visibility: hidden;position: absolute;z-index: 1000;">

<t:commandButton immediate="true" id="btnLoad" actionListener="#{BenutzerkontenBacking.loadBenutzer}" value="Laden"></t:commandButton>

</div>

.

.<some code>

.

<t:selectOneRadio id="radio" forceId="true" forceIdIndex="false" value="#{BenutzerkontenBacking.bnId}" onmouseup="(document.getElementById('mainfrm:content:btnLoad')).click();">

<f:selectItem itemValue="#{crow.bnId}" itemLabel=""/>

</t:selectOneRadio>

zzza at 2007-7-13 0:01:09 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 5

> Oh, sorry. My fault.

>

> But now i have another problem:

>

> because the selectoneradio tag has no actionListener

> property (because it磗 no action control) i

> implemented a invisible commandbutton. When clicking

> on the radiobutton i call the buttons javascript

> click() method to simulate a buttonclick and call its

> actionlistener method. But the model is not updated

> when i use immediate="true" on the button.

> How can i get the value of the radiobuttons?

Do don't need the value of the radio button, correct? What you really want is the bean that corresponds to the row that was clicked, correct? The dataTable component was designed to help you with this. Google for BalusC's dataTable component page for details.

RaymondDeCampoa at 2007-7-13 0:01:09 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 6

Hi,

this page describes my problem (see the possible solutions):

http://wiki.apache.org/myfaces/How_The_Immediate_Attribute_Works

I decided to use solution 2, to access the components directly:

so I ... :

1. set the commandbutton immediate="true"

2. set the selectoneradio to immediate="true"

3. created 2 component properties in my backing bean (selectoneradio and seledtitem)

4. set the binding attribute of the components to this bean properties

5. wrote some code to access the components inside my actionlistener method

But the getValue() on these properties is always null.

<t:commandButton immediate="true" id="btnLoad" actionListener="#{BenutzerkontenBacking.loadBenutzer}" value="Laden"></t:commandButton>

.

<some code>

.

<t:selectOneRadio binding="#{BenutzerkontenBacking.radiocomponent}" immediate="true" id="radio" forceId="true" forceIdIndex="false" value="#{BenutzerkontenBacking.bnId}" onmouseup="(document.getElementById('mainfrm:content:btnLoad')).click();">

<f:selectItem binding="#{BenutzerkontenBacking.selectItem}" itemValue="#{crow.bnId}" itemLabel=""/>

</t:selectOneRadio>

Here some details from the backing bean:

HtmlSelectOneRadioradiocomponent;

UISelectItemselectItem;

.

<some code>

.

public void loadBenutzer( ActionEvent event )

{

log.info( "Lade Benutzer mit id " + getBnId() );

Benutzer b;

try

{

Integer id_to_load = null;

if ( getBnId() == null )

{

log.info( "Wert aus RadioButton: " + radiocomponent.getValue() );

if( radiocomponent.getValue() != null )

id_to_load = (Integer) radiocomponent.getValue();

else

{

log.info( "Wert aus RadioButton (SelectItem): " + radiocomponent.getValue() );

if( selectItem.getValue() != null )

id_to_load = (Integer)selectItem.getValue();

}

}

else

id_to_load = getBnId();

.

<rest of code>

.

Do you see an error ?

Thank you very much

zzza at 2007-7-13 0:01:09 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 7

Hi,

good news: ... It works ... :-)

Like RaymondDeCampo already said, goggle for BalusC磗 dataTable solved my problem.

Here is a good tutorial for handling dataTables:

http://balusc.xs4all.nl/srv/dev-jep-dat.html

My problem was, that i placed a commandbutton outside the datatable and executed the click event on this button via javascript after an onclick on my radiobuttons.

The solutions is, to place the radiobutton inside a commandlink (inside the datatable), then you can access the rowdata via component binding.

Thanks RaymondDeCampo

zzza at 2007-7-13 0:01:09 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 8
Good work.
BalusCa at 2007-7-13 0:01:09 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 9
I appreciate the thanks but I think BalusC deserves some too for hosting his JSF knowledge base.
RaymondDeCampoa at 2007-7-13 0:01:10 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...