input component inside ui:repeat, how to save submitted values - jsf

I'm displaying a list of questions from database and for each question I have to display a list of options, in this case radio buttons.
<ui:repeat value="#{formData.questions}" var="question">
<div>
<p:outputLabel value="#{question.name}" />
<p:selectOneRadio value="#{formData.selectedOption}">
<f:selectItems value="#{formData.options}" />
</p:selectOneRadio>
</div>
</ui:repeat>
I need to save the checked option for each question.
How can I do this?

You need to associate the input value with the repeated variable var in some way. Right now you're not doing that anywhere and basically binding all input values to one and same bean property. So, when the form gets submitted, every iteration will override the bean property everytime with the value of the current iteration round until you end up getting the value of the last iteration round. This is definitely not right.
The simplest way would be to directly associate it with the object represented by var:
<p:selectOneRadio value="#{question.selectedOption}">
In your specific case, this only tight-couples the "question" model with the "answer" model. It's reasonable to keep them separated. A more proper solution in your specific case is to map it with currently iterated #{question} as key (provided that it has a proper equals() and hashCode() implementation, obviously):
<p:selectOneRadio value="#{formData.selectedOptions[question]}">
With:
private Map<Question, String> selectedOptions = new HashMap<>();
Regardless of the approach, in the action method, just iterate over it to collect them all.

Related

Omnifaces validateMultiple component only takes UIInput values, any workaround for considering UIOutput too?

So, I have an Address to validate and it has 4 input fields and 4 output fields, basically the 4 output fields are city,state,county and municipality. There are not editable, so they will be populated by zipCode lookup only. But when I validate , I need to pass in all the values, the lookup values too.
<o:validateMultiple> only takes in Input Component values, so I tried to make them h:inputText too and then disabled=true since they aren't editable, but looks like <o:validateMultiple> ignores values of disabled input components as well. So, any alternatives?
Initially I did it bu embedding all the ids with respective bindings using f:attributes on the first inputText component and used JSF validator to grab getAttributes and validated that way, which worked OK, but since validateMultiple reduces lot of that, I wanted to use this , but looks like it is not straight forward.
Something like this could have helped :
<o:validateMultiple id="myId" components="foo bar baz" validator="#{bean.validateValues}" />
<h:message for="myId" />
<h:inputText id="foo" />
<h:inputText id="bar" />
<h:inputText id="baz" />
public boolean validateValues(FacesContext context, List<UIComponent> components, List<Object> values) {
// ...
}
Any help is appreciated!
Thanks!
Use <h:inputHidden> if you need hidden inputs.

How to implement foreach in jsf?

How do I create ofer_has_location objects (join object from location and ofer) using the current ofer and the selected items from the h:selectManyCheckBox
<h:selectOneMenu id="companyidCompany"
value="#{oferController.selected.companyidCompany}"
title="#{bundle.CreateOferTitle_companyidCompany}"
required="true"
requiredMessage="#{bundle.CreateOferRequiredMessage_companyidCompany}">
<f:ajax event="valueChange" execute="companyidCompany"
render="locationCollection" />
<f:selectItems value="#{companyController.itemsAvailableSelectOne}"/>
</h:selectOneMenu>
<h:outputLabel value="#{bundle.CreateOferLabel_locationCollection}"
for="locationCollection" />
<h:selectManyListbox id="locationCollection" value="locations"
title="#{bundle.CreateOferTitle_locationCollection}">
<c:forEach items="locations">
<f:selectItems var="locations"
value="#{oferController.selected.companyidCompany.locationCollection}" />
</c:forEach>
</h:selectManyListbox>
What you need to do in order to achieve 'connected elements' functionality:
Have two elements ( <h:selectOneMenu> and <h:selectManyLisBox> in your case), where the second one will be dependent on the selected option(s) of the first one. The second element must have an id in order to be rerendered afterwards.
Every HTML select element (that's rendered by both JSF tags of your choice) will have a set of options that are not supposed to be created via iterative element like <c:forEach> (though, it is in fact possible), but rather via the <f:selectItem>/<f:selectItems> tags (thus, remove your iterative tag in comment).
When values in the components are bound not as plain Strings, or primitive wrappers (Integer, etc.), but rather as model objects (YourClass objects, etc.), then you need to tell JSF two things: how can it print option's value from your class and how can it reconstruct an object from request parameter that is a string. For this you need to implement Converter, that is, explain JSF how to do the abovementioned transformations. Use this answer and BalusC's blog as reference points. Note the appropriate syntax for <f:selectItems itemValue="..."> here.
Model values bound by these two components also need to represent your classes, just in a same way as selected items' values. For <h:selectOneMenu> it is value="#{}"; for <h:selectManyListbox> it is value="#{}" with YourClass selectOneMenuValue and List<YourClass> selectManyListboxValues or YourClass[] selectManyListboxValues bean properties respectively.
Population of second select will be handled via <f:ajax> tag. As contents need to be calculated 'on the fly', the right spot to make it is within its listener attribute (i.e. to have List<YourClass> contentsOfSecondListbox = createListboxValues(YourClass oneMenuSelectedOption);) . As you'd desire to rerender the second element, specify its client id in render attribute of <f:ajax>. Example here.
In case you are binding, for example, to String/String[] values, you won't need the converter parts.
Try to go through it step by step to find out your errors and correct them.

Get row number in p:dataTable of dynamic element

I'm curious about how to get the row number of an element inside the <p:dataTable>.
<p:dataTable id="userDataTable" value="#{bean.rows}" rowIndexVar="rowIndex">
<p:column headerText="RowCounter">
<p:commandLink id="row#{rowIndex+1}" actionListener="#{bean.getRows}">
<h:outputText value="Show Row #{rowIndex+1}" />
</p:commandLink>
</p:column>
</p:dataTable>
Bean:
public void getRows(ActionEvent ae) {
System.out.println(ae.getComponent().getId().toString());
}
Always prints row1, no matter which <p:commandLink> is clicked. What am I missing?
As to your concrete problem, the id attribtue of a JSF component is evaluated during view build time. However, the #{rowIndex} is only set during view render time. Thus, at the moment the id attribute is evaluated, the #{rowIndex} is nowhere been set and defaults to 0. This problem has essentially exactly the same grounds as already answered and explained here: JSTL in JSF2 Facelets... makes sense? Note thus that there's only one <p:commandLink> component, not multiple. It's just that it's been reused multiple times during generating HTML (everytime with the same component ID!).
To fix it, just use id="row" instead. The dynamic ID makes no sense in this particular case. JSF would already automaticlaly prepend the row index (check generated HTML output to see it). I'm not sure why exactly you incorrectly thought that you need to manually specify the row index here, so it's hard to propose the right solution as there are chances that you actually don't need it at all. See also How can I pass selected row to commandLink inside dataTable?
For the case you really need the row index, here's how you could obtain it:
Integer rowIndex = (Integer) ae.getComponent().getNamingContainer().getAttributes().get("rowIndex");
The UIComponent#getNamingContainer() returns the closest naming container parent which is in your particular case the data table itself, in flavor or UIData which in turn has thus the rowIndex property. You can alternatively also do so, which is a bit more self documenting:
UICommand commandLink = (UICommand) ae.getComponent();
UIData dataTable = (UIData) commandLink.getNamingContainer();
Integer rowIndex = dataTable.getRowIndex();

jsf inputtext doesn't show value from bean

I have the follow situation:
I have a bean that send to form some data, but only in outputlabel the data from the bean is displayed.
I tried to use primefaces, but the same problems persist.
my code:
<h:outputLabel value="#{Bean.name}" id="name2" />
<h:inputText value="#{Bean.name}" id="name" />
<p:inputText value="#{Bean.name}" id="name3" />
Any idea why?
You should have given the bean's code also, to help us better analyze the problem.
Normally you should check for the following:
Check whether you are specifying a correct bean name. Normally
bean's name is same as that of class, except that first letter
should be lowercase. In your case it should be #{bean.name} or else,
specify your custom name with #Named("Bean").
Check whether the getters and setters such as getName() are properly
provided. It may happen that you might have reset the name property in
your bean in the get method itself. Because of which first time it
shows you properly in outputLabel and then in next call to getName it may give you null or empty String. To check this, try put your inputText tag first, and check.
I solve my problem.
When I tried show the values, I was trying recover data from database by pass an ajax action. So, When I clicked at button to retrieve the datas, some of my inputText were set as a required. And because this the data is just displaying into label and not inside of inputtext with required. But because ajax, the request were not called correctly.
When I remove the required from inputtext, it works fine.

pass parameter from f:selectItems in h:selectOneListbox

I have a selectOneListbox that, when clicked, should pass an additional parameter (id) to the server. As it is now, the user sees a list of names and when they select one I can get the name. But, each name also has a unique id associated with it that I don't want the user to see - how can I pass the unique id of the selected name to the backing bean without the user ever seeing it? Is it possible? I was trying to figure out how to use the f:param but I don't see how that will work here.
<h:selectOneListbox id="listBox" value="#{ScheduleMB.clients}" size="5"
rendered="#{ScheduleMB.showClients}" >
<f:selectItems value="#{ScheduleMB.clientList}" var="c"
itemLabel="#{c.lastName} #{', '} #{c.firstName}" itemValue="#{c.lastName}" />
<f:ajax event="click" listener="#{ScheduleMB.clickListener}"
render="group" />
</h:selectOneListbox>
The <f:param> serves a different purpose. Even if the <f:param> was possible, it would still end up being visible in the generated HTML output. The enduser would just do rightclick and View Source and then see the IDs being definied as option values.
Your best bet is to retrieve the ID from the DB based on a different unique identifier, perhaps the unique combination of firstname+lastname.
It does by the way not make any sense to me why you would like to hide the ID from the output. It'd be so much easier if you used that as option value, even more if you used a converter so that you can just pass the whole #{c} as option value. The enduser can't spoof/change it in any way. JSF will revalidate the submitted value against the list of available options (which are definied in server side anyway).

Resources