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

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...

Related

Ajax rendering "freezes" for a while when updating h:selectManyListbox with 10.000 items

I am using Mojarra JSF (v2.2.10) with Spring (v3.2.5) for a small admin-console on a tomcat (also Twitter Bootstrap for styling).
Basically there is a multiple select box which I can add new entries to via textbox and button. I can also remove entries by selecting them and clicking the remove button.
Here is the relevant code piece:
<h:form>
<h:outputLabel for="selectedEntries" value="Selected entries" />
<h:selectManyListbox id="selectedEntries" value="#{myBean.entriesToRemove}">
<f:ajax/>
<f:selectItems value="#{myBean.selectedEntries}" />
</h:selectManyListbox>
<h:commandButton action="#{myBean.addEntriesToSelection}" value="Add">
<f:ajax render="selectedEntries entriesInput" />
</h:commandButton>
<h:commandButton action="#{myBean.removeEntriesFromSelection}">
<f:ajax render="selectedEntries entriesInput" />
</h:commandButton>
<h:outputLabel for="entriesInput" value="Input" />
<h:inputTextarea id="entriesInput" value="#{myBean.entriesInput}">
<f:ajax/>
</h:inputTextarea>
The fields "entriesToRemove" and "selectedEntries" are simple String Lists and the field "entriesInput" is a String.
Everything works just fine, but when the "selectedEntries" list grows to say 10.000 entries, I hit a performance problem: When I try to add a new entry into this overgrown list, the page freezes for about 30 seconds before it renders the updated list. The same goes for removing an entry. This freeze however does not occur in the method "addEntriesToSelection" but rather afterwards, when the backing bean fields are already updated. So I assume this has something to do with the rendering of the page.
Does anybody have a clue, how I could solve this problem? Is this maybe Mojarra- or JSF-specific?
This is a client side problem, not a server side problem. Some browsers, particularly MS Internet Explorer, are known to be laggy when updating the HTML DOM tree with an "insane" amount of new HTML elements. Certainly 10.000 listbox items is "insane". Google e.g. also doesn't show all those million potential matches at once when you open the search homepage. Instead, it shows an autocomplete-capable input field allowing you to find and filter the relevant data.
Consider turning that listbox into a search/autocomplete input field.

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" ... />

Using of a4j:commandLink; how it works?

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}".

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.

JSF2: Is there any way to use a4j:param with rich:select or h:selectOneMenu

Is it possible to use with dropdown menus or is it also dependent on the parent object implementing ActionSource as the f:setPropertyActionLister is?
Ideally I would have done something like the following:
<h:selectOneMenu value="#{myCustomBean.selectedItemIndex}">
<f:selectItems value="#{adminLetterAdminBean.missingSettings}" var="n" itemValue="#{n.id}" itemLabel="#{n.name}"/>
<f:setPropertyActionListener value="42" target="#{adminLetterAdminBean.someProperty}" />
<a4j:ajax />
</rich:select>
However this does not work because h:selectOneMenu does not implement javax.faces.component.ActionSource. The page does not render and it gives me a friendly stack trace to tell me about this dependency.
Not seeing anything in the Richfaces documentation about this constraint, I tried the following:
<h:selectOneMenu value="#{myCustomBean.selectedItemIndex}">
<f:selectItems value="#{adminLetterAdminBean.missingSettings}" var="n" itemValue="#{n.id}" itemLabel="#{n.name}"/>
<a4j:param assignTo="#{adminLetterAdminBean.someProperty}" value="42" name="randomRequestParamName"/>
<a4j:ajax />
</rich:select>
This does not blow up, but it also does not set the property. I was wondering if there is a set a (or multiple) properties in a similar fashion.
a4j:param can only be nested inside an action component such as a4j:commandButon, a4j:commandLink and a4j:jsFunction. You can also use it with the standard button/link components.
I had a similiar problem. My page has to transfer information about the autocomplete before the autocomplete request is done. I achieved this by using jsFunction. My autocomplete looks like:
<rich:autocomplete mode="ajax" showButton="true" value="#{conf.fieldValue}"
autocompleteMethod="#{BackingBean.search.autocomplete}"
minChars="3" onfocus="sendInfo('#{conf.label}')">
</rich:autocomplete>
Depending on conf.label (conf is a forEach variable) different data is fetched by the backing bean in the autocomplete method.
The transfer of this information is done by jsFunction (just after the autocomplete declaration):
<a4j:jsFunction name="sendInfo">
<a4j:param name="param1" assignTo="#{BackingBean.search.currentAutocomplete}"/>
</a4j:jsFunction>
Just, when the user puts the focus on a specific autocomplete "sendInfo" is executed with one parameter which is bound to the backing bean.

Resources