Using of a4j:commandLink; how it works? - ajax

In my project I have the facelet, which contains the following chunk of markup:
<rich:column sortable="true" sortBy="#{item.date}">
<a4j:commandLink value="#{item.dateView}"
reRender="reportTable">
<a4j:actionparam name="shown" value="#{not item.showDetails}"
assignTo="#{item.showDetails}" />
</a4j:commandLink>
</rich:column>
After I've clicked to the commandLink I have that my table is reRendered with an additional data. But I completely don't undertand how it works. I've read a corresponding manual page about one, but it is still not clear. In the manual's example we use the following tag:
<a4j:commandLink value="Get greeting" reRender="greeting" />
And after we've clicked to it we get a message "Hello %name%". Where is the String template for the "Hello %name%" message is located. In the other word, I would like to enquire where the data that I reRendered is located?

a4j:commandLink assigns (boolean) value of !item.showDetails into item.showDetails and re-render reportTable. Your additional data (which you see after click to command link) is displayed after re-rendering of table, because there is (probably rendering) condition similar to "#{item.showDetails}".

Related

How to reRender an inputText generated dynamically by a dataTable using Ajax

I'm using here in my project JSF 1.2 and the Tag <a4j:support> .
Well, i'm using here a <h:dataTable /> to print on the screen a list of financial expenses, where it's possible for the user to insert new expenses or edit the existed expenses at anytime, the value of these expenses fields (amount, balance, value) are being shown in inputTexts components.
As i'm using a <h:dataTable /> the inputTexts of it are generated automatically, so it creates dynamical inputTexts with dynamical ids. I took a look at the html source code of the page and the pattern JSF uses to generate the ids in a dynamically way is this:
id="formTemplate:tableForm:0:inputTextValue" ;
id="formTemplate:tableForm:1:inputTextValue" ;
id="formTemplate:tableForm:2:inputTextValue"
And in the xhtml page the code i used with the dataTable is this:
<h:inputText id="inputTextValue" value="#{item.value}" label="Value" styleClass="field" size="9" readonly="true" dir="RTL" style="font-size:12px;width:170px">
My business rule works like that: When the user types something in the inputTextBalance it calls the event onBlur where it automatically inserts an other value in the field "value", but to update this inputTextValue i need to do a reRender in my panel (panelDataTable), so it reRender the whole dataTable (dataTable is inside the Panel).
<h:inputText id="inputTextBalance" value="#{item.balance}" dir="RTL">
<f:convertNumber currencyCode="BRL" type="currency" />
<a4j:support event="onblur" reRender="panelDataTable" ajaxSingle="true" action="#{expenses.update}"/>
</h:inputText>
Now comes the trouble, what i need to do is to reRender only the inputTextValue instead of the panel, but these fields are generated dynamically and i can't get there ids. Like i said before, this is the pattern that JSF uses to generate the id of the fields
id="formTemplate:tableForm:0:inputTextValue" ;
id="formTemplate:tableForm:1:inputTextValue" ;
id="formTemplate:tableForm:2:inputTextValue"
But when i use any of these ids in reRender attribute, the Ajax's log returns me this message:
18:23:57,208 WARN [AjaxContext] Target component for id formTemplate:tableForm:0:inputTextValue not found
I tried this but i got the same error message: reRender="#{rich:clientId('inputTextValue')}"
The weirdest thing here is that it shows me this message of the input not found, but in the html source code the id of he inputText is the same that i've puted to reRender.
Does anybody here have already delt with this problem? Any suggestions to me?
Thank you!
you should bind the h:dataTable to a variable in your bean, in order to reach the current row index.
<h:dataTable binding="#{myManagedBean.dataTable}" ...>
then you can change a4j:support like this:
<a4j:support reRender="formTemplate:tableForm:#{myManagedBean.dataTable.rowIndex}:inputTextValue" ... />

Get the selected values from a rich:select which is inside o a4j:repeat

I am using a a4j:repeat control to iterate throughtout a Map<Object, List<MyType>> list. The XHTML page displays both h:outputText and rich:select controls.
I loop throughout a Map<String, List<Items>> instance, to show a master-detail tables. In the h:outputText I show the master description and the rich:select shows the detail.
The code is as follows:
customer.xhtml
<a4j:repeat value="#{masterManagedBean.listMasterItems.entrySet().toArray()}"
var="itemsVar">
<h:outputText value="#{itemsVar.key}" />
<rich:select enableManualInput="true">
<f:selectItems value="#{itemsVar.value}" id="itemsMenu"
var="itemsVarSelect"
itemLabel="#{itemsVarSelect.descriptionItems}"
itemValue="#{itemsVarSelect.idItems}" />
</rich:select>
</a4j:repeat>
This snippet works perfect. But, I don't have any idea how to gain the selected value from every rich:select generated by the repeater. Please guidance me to solve this issue.
Basically I would suggest not to use the datastructure Map<String,List> for the described case. Why not changing the Structure into a normal List of objects (List<SelectionObject>) with the SelectionObject-class holding:
name/label
possible values (as List or Array)
selected value
So the JSF code would look something like
<a4j:repeat value="#{masterManagedBean.listMasterItems}"
var="itemsVar">
<h:outputText value="#{itemsVar.label}" />
<rich:select enableManualInput="true" value="#{itemsVar.selectedValue}">
<f:selectItems value="#{itemsVar.possibleValues}" id="itemsMenu"
var="itemsVarSelect"
itemLabel="#{itemsVarSelect.descriptionItems}"
itemValue="#{itemsVarSelect.idItems}" />
</rich:select>
</a4j:repeat>
Any preparations/building for this object structure can be done e.g. in getListMasterItems (use some caching), the retrieval of the users data is done in the action of your submit-button, anyway. Just iterate through the list and read out the `selectedValue. If the answer is usable/helpful, please consider an upvote, confirm if it worked out for you.
Hope it helps...

<f:ajax> executing different forms

So I have 2 forms and a command button with f:ajax attached on it. I want to execute the second form on click on button but it seems that it ignores when I'm passing the form's id on execute attribute. But when I replace it with 'execute=":form1"' it runs correctly(the information from the form is sent to server). Can someone tell me why won't work with the id of second form, or how can I achieve this: with one button to execute any form i want from the page.( as it is now no information is sent to server, only the listener is called).
Code bellow:
<h:form id="form1">
<h:panelGrid id="inputSection" >
<h:inputText id="input1" value="#{counterMB.number1}" />
<h:inputText id="input2" value="#{counterMB.number2}" />
</h:panelGrid>
<h:outputLabel id="sumResponse2" value="#{counterMB.sum}" />
</h:form>
<h:form id="form2">
<h:panelGrid id="inputSection" >
<h:inputText id="input1" value="#{counterMB.number1}" />
<h:inputText id="input2" value="#{counterMB.number2}" />
</h:panelGrid>
<h:outputLabel id="sumResponse2" value="#{counterMB.sum}" />
</h:form>
<h:commandButton value="Sum numbers">
<f:ajax event="click" execute=":form2" listener="#{counterMB.sum}" render=":form2 :form1"/>
</h:commandButton>
Update:
so to be more explicit: from what I have read I can use ajax to update/refresh etc some parts of a page instead of refreshing the whole page. What i have tried to do is group some components in different forms and execute a form at a time to see how it behaves. It works perfectly if I use the id of first group(form) but doesn't work at all if I use the id of the second form(it calls the action but doesn't submit any data from any form). I don't understand why. (PS for those who claim i lack some knowledge : this is the reason of asking questions isn't it? I'm trying to learn some new stuff)
It seems that you are lacking basic knowledge of how jsf works. A command button must be inside a form. And it's not possible to submit 2 forms with one single button.
The attribute execute of f:ajax tells which components to process, for example if you have 2 input texts, you can process only one and ignore the other using this attribute. but it's not possible to do what you are trying to do.
It doesn't really make sense to submit 2 forms and execute a single action method once.. there's no point in having 2 forms. why don't you put everything inside a single form?
In your current solution, you use a h:commandButton outside of any h:form - this is a little bit against HTML and JSF, so don't count on it. What I would suggest is
if you use Richfaces, put a a4f:jsFunction in every form and trigger the resulting Javascript from anywhere
if you use Primefaces, put a p:remoteCommand in every form and trigger the resulting javascript from anywhere
if you neither use any of them, put a <h:commandButton /> in every form, set the style hidden and use javascript to submit the form.
Hope it helps...

Multiple h:inputTextarea to single back-end variable

I'm trying to create a comment page with a variable set of comments (layed out via o:tree, thanks BalusC) that anyone can reply to. I'm displaying the h:inputTextArea via p:inplace, so there are multiple textinputareas per page with multiple commandbutton replies. I'm trying to map the command button to a single back-end variable from a specific textinputarea so that every textinputarea isn't processed each time the command button is pressed.
Edit: Code example
<o:tree value="#{xPost.post.comments.treeModel}" var="comment" varNode="node">
<o:treeNode>
<o:treeNodeItem>
<p:panel>
<h:outputText value="#{comment.commentText}" />
<p:inplace label="Reply">
<br/>
<p:editor value="#{post.newComment}" />
<p:commandButton action="#{post.saveComment('#{comment.ID'})}" value="Comment" ajax="false" />
</p:inplace>
<o:treeInsertChildren />
</p:panel>
</o:treeNodeItem>
</o:treeNode>
</o:tree>
To add to this, I'm using hibernate validation, which to my knowledge can only validate via annotations:
#NotBlank(message="Please enter a comment.")
#Length(min=1, max=10000, message="A comment must be between 1 and 10,000 characters.")
#SafeHtml(message="Invalid Rich Text.")
private String newComment = "";
So from the code above, when I have 2+ p:editor, each editor is being processed and populating the same back-bean variable. How do I force a commentButton to only validate a specific inputBox/p:editor and set the backing-bean variable.
Thank you for your help.
Just give each editor its own form. In other words, move the <h:form> from outside the <o:tree> to inside the <o:treeNodeItem>. This will ultimately render multiple forms with each its own editor and button.
You need to provide your source details for people to give you more help
In your case, I'm guessing the following should do the trick:
<ui:repeat var="comment" ...> // or equivalent like o:tree
<h:inputText value="#{comment.message} .../>
<h:commandButton actionListener="#{bean.updateMessage}">
<f:setPropertyActionListener from="#{comment}" to="#{bean.commentBeingProcessed}"/>
<!-- Or alternatively, you can set the comment object on to the command button
and receive it on the server side as event.getComponent().getAttribute("comment")
<f:attribute name="comment" value="#{comment}"/>
-->
</h:commandButton>
</ui:repeat>
Hope that helps.

Richfaces dataTable works fine, but ExtendedDataTable is not showing data

We are using Richfaces 4.1.0, and I am trying to use an extendedDataTable. I started (for simplicity's sake) with dataTable. The code below works fine, and shows my data in a table, as expected.
<rich:dataTable value="#{recipientBean.recipientList}" var="recipient" selectionMode="none" id="recipientTable">
<rich:column sortable="false" id="col_1" label="Name">
<f:facet name="header">
<h:outputText value="Name" id="name" />
</f:facet>
<h:outputText value="#{recipient.name}" id="rec_name" />
</rich:column>
<!-- More columns below, removed for post brevity -->
</rich:dataTable>
We are expecting a large number of records, so we would like the table to be scrollable. I thought that I could just change the dataTable to extendedDataTable, however, when I do that, no data shows up at all.
I just started to inspect the element in Chrome, and all of a sudden the data showed up. So when I inspect the element, I see the values in the html, but they don't display when the page loads.
Could this be a style issue? An attribute that is missing (something that is needed for extendedDataTable, but not needed for dataTable)?
What else am I missing?
EDIT: I do have this extendedDataTable inside a rich:tabPanel. When I remove the rich:tabPanel it displays correctly (but I really need the tabPanel). Is this a known issue?
EDIT2: It does display correctly if it is on the first tab of the rich:tabPanel.
I found a bug report on the joss site. The work around was to use the switch type of Ajax instead of client for the tab panel.
If it still doesn't work after switching to ajax switchType you may try to use redirect instead of forward, when you navigate to the page with rich:extendedDataTable. To achieve this you may e.g. add ?redirect-faces=true to the page URL.

Resources