When is a f:param actually sent? - jsf

I've got the following h:commandButton:
<h:commandButton action="#{myBean.myAction}" value="Send">
<f:param name="myFlag" value="true" />
</h:commandButton>
I want to gain access to myFlag insinde a Validator, that's attached to another element with f:validator.
Unfortunately, when I want to retrieve the parameter through the FacesContext, I only get null returned.
Is it that the parameters are only sent once all validators have been invoked?

The <f:param> inside <h:commandButton> is only supported since JSF 2.0, but you're using JSF 1.2. The <f:param> is then only supported in <h:commandLink>.
<h:commandLink action="#{myBean.myAction}" value="Send">
<f:param name="myFlag" value="true" />
</h:commandLink>
There are alternatives, such as a <h:inputHidden> or <f:setPropertyActionListener> or <f:attribute> or in this case perhaps just plain <input type="hidden"> (the hidden input component and the action listener will only set their value during update model values which is later than validations phase; the attribute tag has better to be set on the component which invokes the validator). As the functional requirement is unclear, it's not possible to suggest the best alternative.
Update as per the comments, apparently all you need to know is if the particular button is pressed or not; in that case just give it and the parent form a fixed ID
<h:form id="form">
<h:commandButton id="send" ...>
this way it will have a fixed request parameter name of form:send and you could check on that in the validator:
if (externalContext.getRequestParameterMap().containsKey("form:send")) {
// Send button is pressed.
}
You can by the way also check for that in the required validators as follows:
<h:inputText ... required="#{not empty param['form:send']}" />
See also:
Action dependent requireness

Related

Send parameter to request on every action for composite component

I have a composite component, which has an id I would like to send as a parameter when executing one of many posiible actions inside the composite component. I know I can use something like;
<h:form id="testForm">
<p:commandButton value="#{testReqBean.label}"
actionListener="#{testReqBean.perform()}"
process="#this or #form" update="#form" ajax="true" >
<f:param value="#{cc.attrs.id}" name="CC-Id" />
</p:commandButton>
</h:form>
now, imagine I have many forms or buttons with specific actions inside the composite component... is there a way to define the parameter I want to send in the request just once ? I mean not adding an f:param inside each form/button (depending on the process #form or #this) but one for the whole composite component?
Thanks in advance!
Maybe one solution would be to use viewparam but this only works if you can add a request parameter.
<f:metadata>
<f:viewParam value="#{your_bean.your_property_name}" name="request_param"/>
</f:metadata>
The only problem here is that whoever implements your composite component would have to set the above when needed, but it still an abstraction to this problem of having to set the same property for all components in same page.
I gather that the <h:form> is enclosed in the composite component itself.
Just use a plain HTML hidden input field.
<h:form>
<input type="hidden" name="CC-Id" value="#{cc.attrs.id}" />
...
<p:commandButton />
<p:commandButton />
<p:commandButton />
...
</h:form>
Unrelated to the concrete problem, having an entire form in a composite is kind of strange. This is then food for read: When to use <ui:include>, tag files, composite components and/or custom components?

Reset inputText after Button Click with JSF

Is it possible to reset the value of an inputText after clicking on the commandButton in JSF? The inputText UIElement provides the method ResetValue so I tried something like this:
<h:inputText id="measurementadd" binding="#{inputTextMeasurement}">
<f:validateRegex pattern="[a-zA-Z ]*"/>
<f:ajax event="keyup" render="measurementaddmessage submit" execute="#this"/>
<h:inputText>
<p:commandButton id="submit" action="#{Bean.addMeasurement(inputTextMeasurement.value)}"
value="submit" update="dataTable measurementadd measurementaddmessage"
disabled="#{empty inputTextMeasurement.value or facesContext.validationFailed }" >
<f:ajax event="mouseup" execute="#{inputTextMeasurement.resetValue()}" />
</p:commandButton>
<h:messages for="measurementadd" id="measurementaddmessage"/>
But after clicking the Button the inputTextMeasurement doesn't reset it's value.
Does someone know a good workaround for this?
I'm searching for a solution without JS and JAVA, so a realization in JSF would be very cool.
Your mistake is here in the execute attribute:
<f:ajax event="mouseup" execute="#{inputTextMeasurement.resetValue()}" />
The execute attribute should represent a space separated collection of client IDs to include in the process/decode of the ajax request. However, you specified a listener method there.
You need the listener attribute instead:
<f:ajax listener="#{inputTextMeasurement.resetValue()}" />
(and I omitted event as it defaults here to click which is already the right one)
Interesting detail is that the other <f:ajax> in the same piece of code used the exeucte attribute the right way.
Unrelated to the concrete problem, have you looked at <p:resetInput>? This saves an ajax listener method in the bean. Replace the whole <f:ajax> with
<p:resetInput target="measurementadd" />
Why dont we just use
<input type="Reset"/>
This one is works fine for me! ???
I have solved my problem as below
<p:commandButton id="submit" action="#{Bean.addMeasurement(inputTextMeasurement)}">
Sending back bean UIInput component. Get and Reset value in back bean.
public void addMeasurement(UIInput
String msr = (String) inputTextMeasurement.getValue()
inputTextMeasurement.resetValue();
}

How to access POST parameters when validation failed

I need to show the response page depending on some of the input fields. E.g. the tabid inputHidden below:
#{controllerBean.tabId}
...
<h:form id="edit">
<h:inputHidden value="#{controllerBean.tabId}" id="tabid" />
<h:inputText value="#{controllerBean.name}" id="name" />
</h:form>
But when some other input in the same form has validation error (e.g. the "name" inputText). The "controllerBean.tabId" value will not be assigned because JSF returns at validation stage.
I still need the tabId to show the page correctly and having 2 ideas in mind:
#{param['edit:tabid']}
or use binding:
#{tabId.value}
<h:inputHidden value="#{controllerBean.tabId}" id="tabid" binding="tabId" />
My question is, which of these 2 is the better or Best Practice? Or there are even better ways to do this?
update:
Note. In my specific case, the tabid is set by client javascript.
Server reply with a few items in the html.
Javascript put these items into different tabs on the page.
One of the tabs POST data to server with the current tabid in the form.
So my server need to know the tabid to show the response page with the correct tab selected.
You can add a lifecycle event listener to the component and pick the value from it. I'm going to recommend the preValidate listener:
<h:form id="edit">
<h:inputHidden value="#{controllerBean.tabId}" id="tabid">
<f:event type="preValidate" listener="#{controller.grabTabId}"/>
</h:inputHidden>
<h:inputText value="#{controllerBean.name}" id="name" />
</h:form>
This registers the listener to fire just before the validation phase of the request. You'll now have a listener defined in your backing bean to look like:
public void grabTabId(ComponentSystemEvent cse){
//obtain a reference to the component
HtmlInputHidden hiddenElement = (HtmlInputHidden)cse.getComponent();
//get the value from the component.
String hiddenValue = hiddenElement.getValue();
}
<h:form id="edit">
<h:inputHidden value="#{controllerBean.tabId}" id="tabid" />
<h:inputText value="#{controllerBean.name}" id="name" >
<p:ajax process="tabid" immediate="true" event="keyup" />
</h:inputText>
</h:form>
The above code will do is when the user put some value the value will be processed and will be set the managedBean. that what you want I think.
Another non-perfect way of accomplishing this is to move the validation logic to your action method. If validation fails, you just stop processing (and add an applicable FacesMessage). You just need to be aware that all model values will have been updated, and you can clear them if necessary.
Since updating model values on failed validation goes against the JSF lifecycle, I think any solution will be somewhat of a hack.

Pass an input value directly as action method argument

Is there a way to do pass an input value as a action's parameter without using managed properties?
i.e.
<h:form>
<h:inputText id="input" />
<h:commandButton action="#{someBean.doSome(input)}" />
</h:form>
Yes, it's during the form submit already there in the JSF component state. Just bind the input component to the view by binding attribute, which will reference an UIInput instance, which in turn has a getValue() method for the very purpose of retrieving the input value (so that you can pass it as action method argument):
<h:form>
<h:inputText ... binding="#{input}" />
<h:commandButton ... action="#{someBean.doSome(input.value)}" />
</h:form>
The properness of this approach is however highly questionable and depends on concrete functional requirements. This approach is namely basically tight-coupling the view with the model and therefore considered a bad practice.
See also:
How to send form input values and invoke a method in JSF bean
How does the 'binding' attribute work in JSF? When and how should it be used?

Seam validation question - check for at least one field filled

I have a situation in my form that the user must fill at least one of the fields. Using "required" command, i cannot do that. What is the best way to validate this in seam ? i dont want to use javascript.
Thanks!
Just let the required attribute depend its outcome on the presence of the other input fields in the request parameter map.
<h:form id="form">
<h:inputText id="input1" value="#{bean.input1}" required="#{empty param['form:input2'] and empty param['form:input3']}" />
<h:inputText id="input2" value="#{bean.input2}" required="#{empty param['form:input1'] and empty param['form:input3']}" />
<h:inputText id="input3" value="#{bean.input3}" required="#{empty param['form:input1'] and empty param['form:input2']}" />
</h:form>
Alternatively you could also make use of component binding and use UIInput#getValue() to check the value of the previous components and UIInput#getSubmittedValue() to check them for the yet-to-be-validated components (components are processed in the order as they appear in the component tree). This way you don't need to hardcode client ID's. You only need to ensure that binding names doesn't conflict with existing managed bean names.
<h:form>
<h:inputText binding="#{input1}" required="#{empty input2.submittedValue and empty input3.submittedValue}" />
<h:inputText binding="#{input2}" required="#{empty input1.value and empty input3.submittedValue}" />
<h:inputText binding="#{input3}" required="#{empty input1.value and empty input2.value}" />
</h:form>
JSF2 will let you do a form-level validation. For now, you'll have to make do with either:
Validate in a Bean after form
submission and populate a
FacesMessage to the user if it fails.
Add a validator to one field and in
that validator load in the other
fields and check their values.
If you dont want to use required attribute or javascript, then there are two ways.
One of them is creating a validator, but in my opinion that is too overkill.
I would just check if the input is null or empty in your bean.
if ("".equals(theFieldYouWantToCheck) || theFieldYouWantToCheck == null) {
//Either throw exception or return "false" so that you can handle it
}
If you are using RichFaces then you could perform the validation as follows (see http://mkblog.exadel.com/ria/richfaces-ria/richfaces-built-in-client-functions/):
<h:form id="form">
<h:inputText id="input1" value="#{bean.input1}" />
<h:inputText id="input2" value="#{bean.input2}"
required="#{empty rich:findComponent('input1').submittedValue}"
requiredMessage="At least one of the fields input1 and input2 must be filled."/>
</h:form>
Note that the expression rich:findComponent('input1') is equivalent to uiComponent['input1']. The reason is that Seam provides the dynamic map uiComponent to look up UI components.

Resources