How to re-render a RichFaces component after a4j link is invoked - jboss

Hoping someone can help me with a slight hurdle I've come up against in regards to re-rendering of RichFaces components after an a4j link/button has performed it's action. A simplified version of my problem is as follows:
I have 2 output components displaying a text value which are rendered based on some value in my manager class:
<h:outputText id="on" value="ON" rendered="#{manager.isOn}" />
<h:outputText id="off" value="OFF" rendered="#{not manager.isOn}" />
I also have 2 a4j links that call some action and then re-render the above outputText components:
<a4j:commandLink ajaxSingle="true" value="Set On" action="#{manager.setOn(true)}" reRender="on,off" />
<a4j:commandLink ajaxSingle="true" value="Set Off" action="#{manager.setOn(false)}" reRender="on,off" />
What I would expect to happen is, when I click the 'Set On' button, the 'ON' outputText component would unhide, and the 'OFF outputText component would show. However, this does not happen.
Does anyone have the answer as to why this is so, and how I go about re-rendering these components after the a4j component action has completed?

Wrap the outputText components in an s:div and re-render that as follows:
<s:div id="myDiv">
<h:outputText id="on" value="ON" rendered="#{manager.isOn}" />
<h:outputText id="off" value="OFF" rendered="#{not manager.isOn}" />
</s:div>
<a4j:commandLink ajaxSingle="true" value="Set On"
action="#{manager.setOn(true)}" reRender="myDiv" />
<a4j:commandLink ajaxSingle="true" value="Set Off"
action="#{manager.setOn(false)}" reRender="myDiv" />

I agree with Gene but the best way I could find is to surround the content with
<a4j:outputpanel id="whatever_id" />
for example,
<a4j:outputpanel id="myDiv">
<h:outputText id="on" value="ON" rendered="#{manager.isOn}" />
<h:outputText id="off" value="OFF" rendered="#{not manager.isOn}" />
</a4j:outputpanel>

You rerender the parent. It doesn't have to be a Seam tag.

I suppose that your h:outputText elements on and off are not rendered at load time of the page.
RichFaces will not rerender these components later even if the value of rendered changed to true.

Related

Primefaces Form with 2 buttons dont update

I have a form that has an inputtext where the operator enters the clientid and click on "search", when the search is done the other fields in the form are populated correctly.
Then I have the button "new record" that calls a procedure that creates another object (not a customer) and needs to persist it, when the other object is created in the bean it takes every field from the form except a timestamp.
When the object is persisted only the timestamp is in the DB, all the form values are set to null.
<h:form id="myForm">
<h:outputText value="Customer number" />
<h:inputText id="cIdentidad" value="#{custBean.custID}" />
<p:commandButton process="#all" update="#all" action="#{custBean.populateFields(custBean.custID)}" value="Search" />
<p:growl />
<h:panelGrid id="newCust" columns="2" style="margin-top: 15px">
<h:outputText value="Name" />
<h:inputText id="name" value="#{custBean.name}" disabled="true"/>
<h:outputText value="more fields" />
<h:inputText id="nroAgenda" value="#{custBean.morefields}" disabled="true"/>
</h:panelGrid>
<p:commandButton process="#all" update="#all" action="#{custBean.newRecord()}" value="New record" />
</h:form>
The h:inputText's are disabled, so the value will not be submitted to the server. Maybe you're looking for readonly="true".
Also I would'nt use #all everywhere but rather #form. update="#all" has a special meaning.
Also see this answer.

Reset JSF form fields

I know a lot has been going around this topic, but all the solutions point out to creating a reset button ... is there no way of just clearing the fields and re-populating them ?
Here is what is my code
<p:commandButton id="basic" value="#{c.machine}" action="#{updateEntry.setMachine(c.machine)}" oncomplete="dlg1.show();" styleClass="ui-Machinebutton"/>
This sets the value 'machine' in 'updateEntry' and once completed launches the dialog box 'dlg1'
Dialog Box
<p:dialog id="Update_Entry" header="Update Entry" widgetVar="dlg1" modal="true" height="250" dynamic="True" resizable="False">
<h:form prependId="false" id="Update_Entry_Form" method="post" autocomplete="off">
<h:panelGrid id="update_grid" columns="2" style="margin-bottom:10px">
<f:facet name="header">
<p:messages />
</f:facet>
<h:outputLabel for="machine" value="Machine *" />
<p:inputText id="machine" value="#{updateEntry.machine}" required="true" requiredMessage="Machine is required">
<f:validateLength minimum="5" maximum="5"/>
</p:inputText>
The form loads the value fine for the first time, but it always loads the previous value even if updateEntry.machine is updated. How do i clear this off automatically ? I am using PrimeFaces
You forgot to ajax-update the dialog's content before opening. That's why it's always showing initial content as it was when the page was rendered for the first time or when the dialog was closed for the last time.
Do so accordingly:
<p:commandButton ... update=":Update_Entry">

Inconsistent primefaces commandbutton behaviour

Using the following code I get an behaviour that I can't explain.
The autocomplete method works fine to select an object.
It updates the panel below as expected.
But then the two buttons (New Airport, Save Airport) are not firing the backing bean listener.
However if I click on one of the buttons before using the autocomplete to load an object, the listener gets fired.
<h:form id="arptForm">
<p:autoComplete minQueryLength="3"
value="#{airportHandler.theAirportNames}" effect="fade"
completeMethod="#{airportHandler.autoComplete}"
forceSelection="true" converter="airportNamesConverter"
var="airport" itemLabel="#{airport.icaoName}" itemValue="#{airport}"
maxResults="#{airportHandler.maxAutoCompleteResults}">
<f:ajax event="itemSelect"
listener="#{airportHandler.airportChanged}" render="#form" />
<p:column style="width:80%">
<h:outputText
value="#{airport.icaoName} - #{airport.iataName} - #{airport.airportName} (#{airport.cityName})" />
</p:column>
</p:autoComplete>
<p:spacer width="20" height="20" />
<p:commandButton id="newAirport" value="New Airport"
icon="ui-icon-newwin" actionListener="#{airportHandler.newAirport}"
update="#form" />
<p:spacer width="20" height="20" />
<p:commandButton id="saveAirport" value="Save Airport"
icon="ui-icon-newwin" actionListener="#{airportHandler.saveAirport}"/>
<p:separator />
<p:outputPanel id="allArptData">
<p:panel id="airportBasics" header="Airport Basics"
toggleable="true" toggleSpeed="500"
rendered="#{airportHandler.theAirport != null}">
<ui:include src="airportbasics.xhtml" />
</p:panel>
<p:panel id="airportRunways" header="Airport Runways"
toggleable="true" toggleSpeed="500"
rendered="#{airportHandler.theAirport != null}">
<ui:include src="airportrunways.xhtml" />
</p:panel>
</p:outputPanel>
</h:form>
Can you explain what happens ?
Thanks
As you said you should not the nest forms that is not correct. Also when you put everything inside a one main form that means you are mixing the processes while submitting that form. There can be lot's of forms per a page like autocomplete form or profile information form etc.
When you do sth. about autocomplete actually you want to submit things about autocomplete not about other buttons so simply seperate them. That does not mean you should have forms for each component but just seperate your page into main sections.

JSF Buttons in forms sometimes don't perform action

I have problem with organizing forms. When I make one form some buttons (or any other components making ajax calls) don't perform action but they do perform update. When I split the form into two new ones the buttons start working.
In this case buttons and autocomplete don't work.
<h:form styleClass="question-#{cc.attrs.question.id}">
...
<p:commandButton value="add answer" update="#form" action="#{questionEditorBean.addAnswer}" />
<p:commandButton value="save" update="#(.question-#{cc.attrs.question.id})" action="#{cc.attrs.onSave}" oncomplete="#{cc.attrs.onCancel}" />
<p:commandButton value="cancel" onclick="#{cc.attrs.onCancel}" />
<p:autoComplete value="#{questionEditorBean.newTag}" id="tagSelect" completeMethod="#{tagBean.completeTag}" dropdown="true"
var="t" itemLabel="#{t.name}" itemValue="#{t}" converter="#{tagConverter}" forceSelection="true">
<p:ajax event="itemSelect" action="#{action}" update="#form"/>
</p:autoComplete>
</h:form>
When I split the form everything works.
<h:form styleClass="question-#{cc.attrs.question.id}">
...
<p:commandButton value="add answer" update="#form" action="#{questionEditorBean.addAnswer}" />
<p:commandButton value="save" update="#(.question-#{cc.attrs.question.id})" action="#{cc.attrs.onSave}" oncomplete="#{cc.attrs.onCancel}" />
<p:commandButton value="cancel" onclick="#{cc.attrs.onCancel}" />
</h:form>
<h:form>
<p:autoComplete value="#{questionEditorBean.newTag}" id="tagSelect" completeMethod="#{tagBean.completeTag}" dropdown="true"
var="t" itemLabel="#{t.name}" itemValue="#{t}" converter="#{tagConverter}" forceSelection="true">
<p:ajax event="itemSelect" action="#{action}" update="#form"/>
</p:autoComplete>
</h:form>
I don't have nested forms. I am running to this problem all the time. I don't understand this behaviour and I don't want to split buttons and components into more forms when they should be conceptually together. Is there a solution?
You could try giving the form an id and set prependId="false", as in this example:
<h:form id="ccForm" prependId="false">
Then you add the form id to all update targets.
<p:ajax event="itemSelect" action="#{action}" update="ccForm:tagSelect" />
This way you make explicit what are the update targets inside your composite component.
Also I noticed that you're trying to use styleClass as an id in your form, and trying to update it. Following this way I suggested, make its update property look like this:
<p:commandButton value="save" update="ccForm:question-#{cc.attrs.question.id}" action="#{cc.attrs.onSave}" oncomplete="#{cc.attrs.onCancel}" />
I hope it helps.

Why the form id prefix in the h:message output?

I'm currently trying simple validation using required="true"
<h:form>
<h:messages globalOnly="true"/>
<h:panelGrid>
<h:panelGrid columns="3">
<f:facet name="header">
Login Application Sample
</f:facet>
<h:outputLabel for="UserId" value="User Id" />
<h:inputText id="UserId" value="#{userBean.userId}" required="true" />
<h:message for="UserId"/>
<h:outputLabel for="Password" value="Password" />
<h:inputSecret id="Password" value="#{userBean.password}" required="true" />
<h:message for="Password" />
<f:facet name="footer">
<h:commandButton value="Login" action="#{userBean.login}"/>
<h:commandButton type="reset" value="Reset"/>
</f:facet>
</h:panelGrid>
</h:panelGrid>
</h:form>
Leaving the fields blank, and then clickin on the login button, these error messages will display on the right side of each field :
j_idt7:UserId: Validation Error: Value is required.
j_idt7:Password: Validation Error: Value is required.
This is what I expected, but I don't want to display the form id prefix of 'j_idt7:'. I read book examples, they don't output the form id prefix. What I want is :
UserId: Validation Error: Value is required.
Password: Validation Error: Value is required.
What should I do to skip displaying the form id prefix in the component specific messages ?
I'm currently testing JSF 2 in glassfish v3.
The message label defaults to component's client ID, exactly the one as you can see in generated HTML output via rightclick, View Source. That j_id7 is in this particular case the client ID of the parent <form> element. If you give the JSF component a fixed ID like <h:form id="login"> then the labels will become login:UserId and login:Password respectively.
You can however use the input component's label attribute to override it altogether so that the message label will be shown exactly as you intented.
<h:inputText ... label="User ID" />
<h:inputSecret ... label="Password" />
If the input component's label attribute is present, then it will be used instead of the client ID. Using prependId="false" as suggested by other answers has disadvantages. Don't do that.
A completely different alternative is to use requiredMessage (or converterMessage or validatorMessage) attribute for this, but this doesn't allow parameterizing messages and thus you'd have to hardcode the labels and such.
<h:inputText ... label="User ID is required." />
<h:inputSecret ... label="Password is required." />
See also:
Change the default message "Validation Error: Value is required" to just "Value is required"
Getting the component id on the error validation message
How to parameterize requiredMessage attribute in composite component?
Noted should be that it's indeed awkward to have labels duplicated like this:
<h:outputLabel for="userId" value="User ID" ... />
<h:inputText id="userId" ... label="User ID" />
<h:outputLabel for="password" value="Password" ... />
<h:inputSecret id="password" ... label="Password" />
If you happen to use JSF utility library OmniFaces, then you can use <o:outputLabel> to let JSF transparently set the label attribute of the associated component:
<o:outputLabel for="userId" value="User ID" ... />
<h:inputText id="userId" ... />
<o:outputLabel for="password" value="Password" ... />
<h:inputSecret id="password" ... />
If you use MyFaces and the bean validation framework (JSR303) try to define a MessageBundle with a key javax.faces.validator.BeanValidator.MESSAGE
faces-config.xml
<application>
<message-bundle>ApplicationMessages</message-bundle>
</application>
ApplicationMessages.properties
#javax.faces.validator.BeanValidator.MESSAGE={1}: {0}
javax.faces.validator.BeanValidator.MESSAGE={0}
Details
You need to override these messages from JSF.
You can have a messages.properties file in your classpath
Messages.properties
javax.faces.component.UIInput.REQUIRED=Field must be entered.
Faces-config.xml
<application>
<message-bundle>Messages</message-bundle>
<locale-config>
<default-locale>en</default-locale>
</locale-config>
</application>
Have a look at this Article
If you care to see the HTML source from your browser, you will find out that the id of your input field is <form-id>+":"+<input-field-id>, in your case, j_idt7:UserId:. Try to give your <h:form> some meaningful id in order to make some sense out of it. You can read about JSF IDs here. In case you don't like it, you can turn it off by modifying your form tag to something like this,
<h:form prependId = false> // its true by default.
But that might turn out to be problematic, as pointed out by BalusC here.
Furthermore, it seems like you have never configured any validation messages yourself. Which in turn ends up with this message. Hence, a message.properties file is needed to have a control over message and show something more appropriate. Even then the field name should not be the part of the message, to make those validation message generic to avoid repetition. See BalusC's answer regarding the use of label attribute inside the <h:inputText>.
Where you are writing required = true, there you can define requiredMessage = "My Message" for any input type.
e.g.
<h:inputText autocomplete="false" id = "CellNumber" label="Cell Number" required="true" requiredMessage="Cell Number Required" maxlength="10" value="#{userManagedBean.cellNumber}" >