h:inputText inside a4j:repeat - jsf

I have a List of strings in my object, and I was hoping to be able to edit them with an a4j:repeat.
Below is my code:
<a4j:repeat value="#{Controller.object.stringList}" var="item" >
<h:panelGrid columns="2">
<h:outputLabel value="ID:" />
<h:inputText value="#{item}" />
</h:panelGrid>
</a4j:repeat>
My problem is that the values of the items never get changed when I submit my form. I've had a look at the livedemo but even after adding the UpdateBean, it still didn't work.
Any ideas?

The objects in your repeat need to follow the bean standard if you want to write back to them. I'm guessing that they are just Strings in your example?
Try this:
public class StringBean {
private String value;
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
along with:
<h:inputText value=#{item.value} />

Related

How to avoid exception, <c:if> and <c:catch>

I'm trying to render a page, but there is the possibility that some EL Expressions will generate some exceptions.
So I tryed first of all, to sorround by block with a < c:if> in such the way that it shows the code only by checking the critical condition.
But I saw that in case of "error" my page was redirected again as a "HTTP 500 - Internal Server Error".
So I tought that maybe the EL Expression inside the block where computed in any case, also if the < c:if> block where not shown. So I sorrounded my block with a < c:catch> as i read that this block will catch the exceptions. So I also added on all the methods the declaration "throws Exception".
But, again, when the critical condition is not respected, my page will be redirect to the 500 Error page.
I post my XHTML code:
<c:if test="#{!partyBean.emptySet}">
<c:catch>
<p:panel id="panel" style="margin-bottom:10px;">
<f:facet name="header" >
<h:outputLabel value="#{partyBean.currentparty.name}" />
</f:facet>
<f:facet name="actions">
<p:commandButton id="asktojoin" styleClass="ui-panel-titlebar-icon "
action="#{joinRequestBean.askForParty(partyBean.currentparty)}" value="Ask to Join"/>
</f:facet>
<f:facet name="footer" >
<p:commandButton id="pr" action="#{partyBean.previus()}" value="previousParty" rendered="#{partyBean.hasPrevious()}">
</p:commandButton>
<p:commandButton id="nx" style="margin-right:10px" action="#{partyBean.next()}" value="nextParty" rendered="#{partyBean.hasNext()}">
</p:commandButton>
</f:facet>
<h:panelGrid columns="2">
<h:outputLabel value="Symbol:" />
<h:graphicImage value="#{('/partysymbols/'.concat(partyBean.currentparty.symbol))}" width="200" height="171" />
<h:outputLabel for="program" value="Program:" />
<h:outputLabel id="program" value="#{partyBean.currentparty.program}" />
<h:link id="partyname" outcome="memberlist" value="memberlist">
<f:param name="partyname" value="#{partyBean.currentparty.name}" />
</h:link>
</h:panelGrid>
</p:panel>
</c:catch>
</c:if>
<c:if test="#{partyBean.emptySet}">
<h1>There are no parties at the moment</h1></c:if>
</h:form>
</h:body>
And my bean:
#ManagedBean(name="partyBean")
#SessionScoped
public class PartyBean {
#EJB
private PartyManagerLocal ejb;
private PartyDTO[] party;
int i=0;
#PostConstruct
private void init() {
i=0;
refresh();
}
private void refresh(){
Object[] list_o = ejb.getListOfParty().toArray();
party = new PartyDTO[list_o.length];
for(int i=0;i<list_o.length;i++){
party[i]=(PartyDTO)list_o[i];
}
if(i>=list_o.length)
i=list_o.length;
}
public boolean isEmptySet() {
refresh();
return party.length==0;
}
public String next() throws Exception{
refresh();
if(i<party.length-1)
i++;
return "partyview.xhtml?faces-redirect=true";
}
public String previus() throws Exception{
refresh();
if(i>0)
i--;
return "partyview.xhtml?faces-redirect=true";
}
public boolean hasPrevious(){
return i>=1;
}
public boolean hasNext(){
return i<party.length-1;
}
public PartyDTO getCurrentparty() throws Exception{
return party[i];
}
}
I apologize to show to you my whole code, but i have no idea about where is the mistake. Then I also apologize about my horrible code, but at the moment i just need that it works.
The critical condition is that my array should be not empty. Could happen that my Array will be empty but in that case, i need to advise the user about it, instead redirect to the 500 Error page.
Thankyou in advance,
Samuele
You could encapsulate what you want conditionally by surrounding the code in a panelGroup and using the rendered attribute.
Example
<h:panelGroup rendered="#{PartyBean.isEmptySet}">
<!-- Code inside here... -->
<!-- This will render if isEmptySet returns true -->
</h:panelGroup>

values not getting passed from datatable to dialog box

<p:column>
<p:commandButton id="selectButton" update="#(form)" oncomplete="userDialog.show()" icon="ui-icon-search" title="View">
<f:setPropertyActionListener value="#{book}" target="#{CreateBookBean.selectedUser}" />
</p:commandButton>
</p:column>
</p:dataTable>
</p:outputPanel>
<p:dialog header="User Detail" modal="true" widgetVar="userDialog" width="200" height="175">
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="fname" value="First Name: " />
<h:outputText id="fname" value="#{CreateBookBean.selectedUser.fname}" />
<h:outputLabel for="lname" value="Last Name: " />
<h:outputText id="lname" value="#{CreateBookBean.selectedUser.lname}" />
<h:outputLabel for="mobileno" value="mobile no: " />
<h:outputText id="mobileno" value="#{CreateBookBean.selectedUser.mobileno}" />
</h:panelGrid>
</p:dialog>
i came across this example recently.
the datatable is properly getting updated with the values i enter. but when i want to display it in the dialog box its not displaying anything.
and i actually don understand why value="#{CreateBookBean.selectedUser.fname}" is used instead of value="#{CreateBookBean.fname}".
here is my java code
public class CreateBookBean {
private Book book = new Book();
private List<Book> books = new ArrayList<Book>();
private Book selectedUser;
public String reinit() {
book = new Book();
return null;
}
setters and getters are included here
}
Lets split this question in two parts.
First:
When you want to display updated values (e.g. with a h:outputText), you need to update this element. Updating this element means, it will fetch the current value of it's backing bean.
Do it like this:
<p:commandButton ... update="idToUpdate1, idToUpdate2, ..." >
In order to get the idToUpdate check Naming Container in JSF2/PrimeFaces.
If you have many components which need an update, I would recomment grouping them into one NamingContainer (e.g. p:outputPanel). So you only have to update the NamingContainer, and not every single component.
Second:
#CreateBookBean.selectUser.fname means: "Fetch the CreateBookBean, fetch it's property selectUser and fetch the property of selectUser called fname".
In this case you would have these class layouts:
public class CreateBookBean {
private Book selectedUser;
....
public Book getSelectedUser() {
return this.selectedUser;
}
}
public class Book {
private String fname;
....
public String getFname() {
this.fname;
}
}
#CreateBookBean.fname means: "Fetch the CreateBookBean, fetch it's property fname".
In this case you would have this class layout:
public class CreateBookBean {
private String fname;
....
public String getFname() {
return this.fname;
}
}
According to this code you posted, i guess that the CreateBookBean has a property called selectedUser (the code reveals it: target="#{CreateBookBean.selectedUser}"), and the selectUser has a property fname.
Use the Update attribute in the button your using to display the dialog box, for example, <p:commandButton update="dialogBoxId" . . ./> in order to display the items from your datatable.

JSF h:selectOneMenu is never set even when using f:ajax

I want to implement a filtering facility in a JSF web application as follows: The users can add as many filters as they want. They can also delete them. So I am having a dataTable of filters. Each row consists of one h:selectOneMenu which has an ajax “change” event in order to make a second h:selectOneMenu visible in the same row. The options of the second h:selectOneMenu are calculated dynamically according to the selected option of the first.
The problem is that the value of second h:selectOneMenu is never set to the back-end object even if I added an ajax event. However the value of the first h:selectOneMenu is set.
I have the following fragment of code in an .xhtml page:
<h:form id="filterForm">
<h:dataTable id="filterTable" value="#{filterManager.filters}" var="filter">
<h:column>
<h:outputLabel value="#{msgs.filterBy}:" for="availableFilters" />
<h:selectOneMenu id="availableFilters" value="#{filter.filter}">
<f:selectItems value="#{filterManager.getProperties(typeSelector.typeSelected)}" />
<f:ajax event="change" render=":filterForm" />
</h:selectOneMenu>
</h:column>
<h:column>
<h:panelGroup id="filterValuesPanel" >
<h:outputLabel value="#{msgs.value}:" for="filterValues" rendered="#{!filter.filterEmpty}" />
<h:selectOneMenu value="#{filter.value}" id="filterValues" rendered="#{!filter.filterEmpty}" >
<f:selectItems value="#{filterManager.getPossibleAnswers(filter)}" />
<f:ajax event="change" render=":filterForm" />
</h:selectOneMenu>
</h:panelGroup>
</h:column>
<h:column>
<h:commandButton value="#{msgs.delete}" title="#{msgs.deleteFilter}">
<f:ajax event="click" listener="#{filterManager.removeFilter(filter)}" render=":filterForm" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:commandButton value="#{msgs.addNewFilter}">
<f:ajax event="click" listener="#{filterManager.addNewFilter}" render=":filterForm" />
</h:commandButton>
</h:form>
I have a bean called “FilterManager” which has a ViewScoped. Important parts are shown below:
#ManagedBean
#ViewScoped
public class FilterManager implements Serializable {
private List<Filter> filters; // it has a getter
private int currentFilterId;
public void addNewFilter(AjaxBehaviorEvent event) {
this.currentFilterId++;
this.filters.add(Filter.getEmptyFilter(this.currentFilterId));
}
public void removeFilter(Filter filter) {
this.filters.remove(filter);
}
...
}
The Filter class is a normal class (not a bean) and is shown below:
public class Filter implements Serializable {
private int id;
private String filter;
private String value;
public String getFilter() {
return filter;
}
public void setFilter(String theFilter) {
if (theFilter != null && !theFilter.isEmpty())
this.filter = theFilter;
}
public String getValue() {
return value;
}
public void setValue(String theValue) {
this.value = theValue;
}
public boolean isFilterEmpty() {
return this.filter == null || this.filter.isEmpty();
}
...
}
Notice that TypeSelector is a SessionScoped bean which has a typeSelected property along with getter and setter.
The problem is: filter.filter is set correctly whereas filter.value is never set. I can't find the problem so I need your help please. Apologies for all this code but I needed to provide you with all the necessary details.
Thanks in advance!
Okay guys that was my fault. I had a bug in FilterManager.getPossibleAnswers(Filter filter) method. Basically, at the end of the method, I was setting filter.value to the first element of List unconditionally. Eg instead of writing
if (filter.getValue() == null || filter.getValue().isEmpty()) {
SelectItem first = answers.get(0);
filter.setValue((String) first.getValue());
}
I just wrote:
SelectItem first = answers.get(0);
filter.setValue((String) first.getValue());
Although filter.value was updating as normal, the value was changing back to default (first element in list) during re-rendering of dataTable component.

Adding values from multiple inputs to the arraylist

I' have a simple problem with adding values from inputs to the ArrayList.
I have a POJO like this:
public class Person {
private String firstName;
private String lastName;
private List<String> friends=new ArrayList<>();
//getters and setters
then Backing bean:
public class backingBean{
Person p=new Person();
public void addPerson(){
for(String friend:p.getFriends)
System.out.println(friend);
}
}
and the view
<h:form>
<fieldset>
<h:panelGrid columns="2">
<h:outputText value="Name" />
<h:inputText value="{backingBean.person.firstName}"/>
<h:outputText value="LastName" />
<h:inputText value="#{backingBean.person.lastName}"/>
<h:outputText value="Friends" />
<h:inputText value="#{backingBean.person.friends}" />
<h:inputText value="#{backingBean.person.friends}" />
</h:panelGrid>
<h:commandButton value="Add"
action="#{backingBean.addPerson}" />
</fieldset>
</h:form>
When I try to addPerson I get this error:
summary=(Conversion Error setting value...
I don't understand why convert String to String?
You can't bind value of h:inputText to ArrayList (without converter). When you submit form (by clicking button) JSF tries to call setFriends(String) and this is where this Exception occurs. Try to figure out what you are trying to achieve with these two h:inputText elements.
if you want to add 2 friends, just create only 2 different variables in backing bean as :
private String friend1;
private String friend2;
and then add them in addPerson like this:
List<String> friends=new ArrayList<String>();
friends.add(friend1);
friends.add(friend2);
p.setFriends(friends);
Not tested can be some bugs.
EDIT:
And if this not satisfies you, you can look at this #BalusC ANSWER

How to maintain/save row values when generating a new row?

i have the following bean:
public class MyBean {
public ArrayList<ReportRow> getReportRows()
{
return reportRows;
}
private final ArrayList<ReportRow> reportRows =
new ArrayList<ReportRow>(Arrays.asList(
new ReportRow("","")
));
public ArrayList<ReportRow> getOrderList() {
return reportRows;
}
public String addAction() {
ReportRow row = new ReportRow("", "");
reportRows.add(row);
return null;
}
public class ReportRow{
String reportColumnName;
String reportColumnDesc;
public ReportRow(String reportColumnName,String reportColumnDesc) {
this.reportColumnName=reportColumnName;
this.reportColumnDesc=reportColumnDesc;
}
public String getReportColumnName()
{
return reportColumnName;
}
public void setReportColumnName(String reportColumnName)
{
this.reportColumnName = reportColumnName;
}
public String getReportColumnDesc()
{
return reportColumnDesc;
}
public void setReportColumnDesc(String reportColumnDesc)
{
this.reportColumnDesc = reportColumnDesc;
}
}
}
jsf page:
<t:dataTable value="#{myBean.reportRows}" var="o"
id="reportColumnsTable" styleClass="standardTable" headerClass="standardTable_Header"
rowStyleClass="#{myBean.viewDelayedRsd}"
>
<h:column>
<t:outputLabel value="Column name:"></t:outputLabel>
<t:inputText id="ReportColumnName" value="#{o.reportColumnName}" required="true">
</t:inputText>
</h:column>
<h:column>
<t:outputLabel value="Column Desc:"></t:outputLabel>
<t:inputText id="ReportColumnDesc" value="#{o.reportColumnDesc}" >
</t:inputText>
</h:column>
<h:column>
<h:outputLink value="#add"><h:outputText value="Add"/>
<a4j:support ajaxSingle="true" event="onclick" action="#{rprtBean.addAction}"
reRender="reportColumnsTable,msgPanel" />
</h:outputLink>
</h:column>
</t:dataTable>
problem is that when i click on add, it generates a new row, and clear the old one, and i want to maintain the values of old row, any ideas ?
You're using a <h:outputLink> instead of a <h:commandLink>. The <h:outputLink> doesn't submit the form at all, it fires a plain GET request. The <a4j:support> won't work properly inside a <h:outputLink>. Replace it by a <h:commandLink>:
<h:commandLink value="Add" action="#{rprtBean.addAction}">
<a4j:support reRender="reportColumnsTable,msgPanel" ajaxSingle="true" />
</h:commandLink>
Then, you need to ensure that you preserve the data model for subsequent request in case that your bean is request scoped. There are several ways to achieve this:
Set either Tomahawk datatable's preserveDataModel to true:
<t:dataTable preserveDataModel="true">
Or save the bean state in the view scope. Add the following tag somewhere in the page:
<t:saveState value="#{myBean}" />
or since you're also using RichFaces/Ajax4jsf:
<a4j:keepAlive beanName="myBean" />
i just used the a4j command link and everything worked fine.

Resources