JSF ui repeat : Array index out of range: 0 [duplicate] - jsf

I would like to know if it possible to push a value from inside a <ui:repeat> to a map, a set or a list?
I would like to pass the value of the <h:inputtext> to a set.
Code:
<ui:repeat var="_par" value="#{cmsFilterParameterHandler.normaleSuchParameter()}">
<p:outputLabel value="#{_par.bezeichnung}" />
<p:spacer width="5px" />
<p:inputText id="me" value="#{??? push me to a set ???}"/>
<br /><br />
</ui:repeat>

With a Set, it is not possible as it doesn't allow referencing items by index or key. It's however possible with a List and a Map by just specifying the list index and map key in the input value.
With a List:
private List<String> list; // +getter (no setter necessary)
#PostConstruct
public void init() {
list = createAndFillItSomehow();
}
<ui:repeat value="#{bean.list}" varStatus="loop">
<h:inputText value="#{bean.list[loop.index]}" />
</ui:repeat>
With a Map (only if your environment supports EL 2.2 or JBoss EL):
private Map<String, String> map; // +getter (no setter necessary)
#PostConstruct
public void init() {
map = createAndFillItSomehow();
}
<ui:repeat value="#{bean.map.entrySet().toArray()}" var="entry">
<h:inputText value="#{bean.map[entry.key]}" />
</ui:repeat>
Noted should be that the canonical approach is to use a List of fullworthy javabeans. Let's assume a Javabean class named Par with properties id and value which maps exactly to a par table in DB with columns id and value:
private List<Par> pars; // +getter (no setter necessary)
#PostConstruct
public void init() {
pars = createAndFillItSomehow();
}
<ui:repeat value="#{bean.pars}" var="par">
<h:inputText value="#{par.value}" />
</ui:repeat>
Either way, it works as good when using <p:inputText>, it's in no way related to PrimeFaces, it's in the context of this question merely a jQuery based JSF UI component library. Just replace h: by p: to turn it on.

I'm not sure, if I understood your requirements correctly.
I suppose the following: You need a List of Strings in some backend and an ui:repeat tag to iterate over those strings with input-fields to edit them. Maybe there are some syntax-issues, but my idea should be clear:
public class Backend {
private List<String> myStrings;
public MyStringWrapper getMyStringWrapper(int index) {
return new MyStringWrapper(index);
}
public class MyStringWrapper {
private final int index;
public MyStringWrapper(int index) { this.index = index; }
public String getContent() { return myStrings.get(index); }
public void setContent(String newContent) { myStrings.add(index, newContent); }
}
}
In the frontend you use as follows:
<ui:repeat var="_index" value="#{backend.getIndexSequence()}">
<p:inputText value="#{backend.getMyStringWrapper(_index).content}"/>
</ui:repeat>
Of course, you have to provide a getIndexSequence-method which produces a list of ints ranging from 0 to the size of the strings.

Do you mean like this?
<p:inputText id="me" value="#{_par.input}"/>
in BackBean:
public class Par implements Serializable {
private String inputText;
private String bezeichnung;
public Par()
{
}
public void setInput(String input)
{
this.inputText = input;
}
public String getInput()
{
return this.inputText
}
public void setBezeichnung(String bezeichnung)
{
this.bezeichnung = bezeichnung;
}
public String getBezeichnung()
{
return this.bezeichnung
}
}

Related

Display List<List> in <p:dataTable><p:columns>

I am trying to display below list of list of object in datatable. But nothing is showing up. Help is very much appreciated!
public class TimrsDisplayBean {
private static final long serialVersionUID = 1L;
private String teamName = "";
private String teamType = "";
private boolean reported;
private boolean noProd;
private boolean missing;
public String getTeamName() {
return teamName;
}
public void setTeamName(String teamName) {
this.teamName = teamName;
}
public String getTeamType() {
return teamType;
}
public void setTeamType(String teamType) {
this.teamType = teamType;
}
public boolean getReported() {
return reported;
}
public void setReported(boolean reported) {
this.reported = reported;
}
public boolean getNoProd() {
return noProd;
}
public void setNoProd(boolean noProd) {
this.noProd = noProd;
}
public boolean getMissing() {
return missing;
}
public void setMissing(boolean missing) {
this.missing = missing;
}
}
XHTML FILE
<p:dataTable value="#{dashboardMBean.timrsDisplayDataList}" var="var" rowIndexVar="row"
styleClass="large-card-datatable alternatingRowTable no-border nowrap">
<f:facet name="header">
<span class="updateDate"> </span>
</f:facet>
<p:column headerText="Type" value=" #{dashboardMBean.timrsDisplayDataList[0]}" columnIndexVar="i">
#{var[i].teamType}
</p:column>
<p:column headerText="Type" value=" #{dashboardMBean.timrsDisplayDataList[0]}" columnIndexVar="i">
#{var[i].teamName}
</p:column>
Please support full code parts if possible. Your datatable tag doesn't even finish.
Beside that, it seems like you've done too much work. Did you try to calculate the row indices by yourself? Not needed. The basic column definiton is more comfortable. Use your defined variable var to name each element/row as shown in the Primefaces showcase:
http://www.primefaces.org/showcase/ui/data/datatable/basic.xhtml
In your case, it will be something like
<p:column headerText="Type">
<h:outputText value="#{var.teamType}"/>
</p:column>
Plus, as Jasper De Vries said correctly, there is no attribute called columnIndexVar. Remove it to prevent strange behaviour.
If this is not enough, you need to share some more code of your ManagedBean. Not sure if your posted java class represent your Bean, but if so, you need to declare it as a ManagedBean like
#ManagedBean(name = "timrsDisplayBean)
#SessionScoped
public class TimrsDisplayBean {
I hope this helps!

How to set submitted values of <h:inputText> inside <ui:repeat> into map, set or list

I would like to know if it possible to push a value from inside a <ui:repeat> to a map, a set or a list?
I would like to pass the value of the <h:inputtext> to a set.
Code:
<ui:repeat var="_par" value="#{cmsFilterParameterHandler.normaleSuchParameter()}">
<p:outputLabel value="#{_par.bezeichnung}" />
<p:spacer width="5px" />
<p:inputText id="me" value="#{??? push me to a set ???}"/>
<br /><br />
</ui:repeat>
With a Set, it is not possible as it doesn't allow referencing items by index or key. It's however possible with a List and a Map by just specifying the list index and map key in the input value.
With a List:
private List<String> list; // +getter (no setter necessary)
#PostConstruct
public void init() {
list = createAndFillItSomehow();
}
<ui:repeat value="#{bean.list}" varStatus="loop">
<h:inputText value="#{bean.list[loop.index]}" />
</ui:repeat>
With a Map (only if your environment supports EL 2.2 or JBoss EL):
private Map<String, String> map; // +getter (no setter necessary)
#PostConstruct
public void init() {
map = createAndFillItSomehow();
}
<ui:repeat value="#{bean.map.entrySet().toArray()}" var="entry">
<h:inputText value="#{bean.map[entry.key]}" />
</ui:repeat>
Noted should be that the canonical approach is to use a List of fullworthy javabeans. Let's assume a Javabean class named Par with properties id and value which maps exactly to a par table in DB with columns id and value:
private List<Par> pars; // +getter (no setter necessary)
#PostConstruct
public void init() {
pars = createAndFillItSomehow();
}
<ui:repeat value="#{bean.pars}" var="par">
<h:inputText value="#{par.value}" />
</ui:repeat>
Either way, it works as good when using <p:inputText>, it's in no way related to PrimeFaces, it's in the context of this question merely a jQuery based JSF UI component library. Just replace h: by p: to turn it on.
I'm not sure, if I understood your requirements correctly.
I suppose the following: You need a List of Strings in some backend and an ui:repeat tag to iterate over those strings with input-fields to edit them. Maybe there are some syntax-issues, but my idea should be clear:
public class Backend {
private List<String> myStrings;
public MyStringWrapper getMyStringWrapper(int index) {
return new MyStringWrapper(index);
}
public class MyStringWrapper {
private final int index;
public MyStringWrapper(int index) { this.index = index; }
public String getContent() { return myStrings.get(index); }
public void setContent(String newContent) { myStrings.add(index, newContent); }
}
}
In the frontend you use as follows:
<ui:repeat var="_index" value="#{backend.getIndexSequence()}">
<p:inputText value="#{backend.getMyStringWrapper(_index).content}"/>
</ui:repeat>
Of course, you have to provide a getIndexSequence-method which produces a list of ints ranging from 0 to the size of the strings.
Do you mean like this?
<p:inputText id="me" value="#{_par.input}"/>
in BackBean:
public class Par implements Serializable {
private String inputText;
private String bezeichnung;
public Par()
{
}
public void setInput(String input)
{
this.inputText = input;
}
public String getInput()
{
return this.inputText
}
public void setBezeichnung(String bezeichnung)
{
this.bezeichnung = bezeichnung;
}
public String getBezeichnung()
{
return this.bezeichnung
}
}

Using a Enum with a ActionParam

I am using the following piece of code in my JSF 2.0 with RichFaces 4.0. I have a managed bean that has an enum. Now i want to assign the value of the enum via an ActionParam. How can I do this? Here is the code:
<a4j:commandLink id="pendingTransactions"
action="#{tellerBean.getPendingTransactions}" value="Show Pending"
styleClass="button category-btn">
<a4j:actionparam name="first" value=""
assignTo="" />
</a4j:commandLink>
and my managed bean:
#ManagedBean
#SessionScoped
public class TellerBean implements Serializable{
public enum TransactionType {
PENDING,PROCESSED,ALL
}
private static final long serialVersionUID = -321111;
private String recipientID;
private String recipientName;
private String transactionAmount;
private TransactionType transactionType;
public String getRecipientID() {
return recipientID;
}
public void setRecipientID(String recipientID) {
this.recipientID = recipientID;
}
public String getRecipientName() {
return recipientName;
}
public void setRecipientName(String recipientName) {
this.recipientName = recipientName;
}
public String getTransactionAmount() {
return transactionAmount;
}
public void setTransactionAmount(String transactionAmount) {
this.transactionAmount = transactionAmount;
}
public void searchTransactions() {}
public TransactionType getTransactionType() {
return transactionType;
}
public void setTransactionType(TransactionType transactionType) {
this.transactionType = transactionType;
}
public void getTransactions() {}
}
Now I want to assign the value of the transactionType variable to an Enum value. How can I do this?
I don't know what you want to do with the variable or how you want to display it, so here's a generic example.
First of all, the JSF page must be able to 'iterate' over the enum to discover the possible values. I'm using h:selectOneMenu as an example which is filled using f:selectItems. f:selectItems expects a List<> as input so we need to create a method in the TellerBean:
public List<TransactionType> getTransactionTypes()
{
List<TransactionTypes> tt = new ArrayList<TransactionType>();
for (TransactionType t : TransactionType.values())
{
tt.add(new TransactionType(t, t.toString()))
}
return tt;
}
Then for an example JSF page:
<h:form>
<h:selectOneMenu value="#{tellerBean.transactionType}">
<f:selectItems value="#{tellerBean.transactionTypes}"/>
</h:selectOneMenu>
<h:commandButton value="Submit" action="#{tellerBean.someMethod}"/>
</h:form>
The JSF page should display a drop-down list with the values of the enum. When clicking the button labeled "Submit" it executes someMethod() in TellerBean. Of course this doesn't work because the method doesn't exist, but it's just an example. ;-)

DataModel must implement org.primefaces.model.SelectableDataModel when selection is enabled.

I'm trying to create a DataTable with Multiple Row Selection but i'm getting an error here's the link of the tutorial http://www.primefaces.org/showcase/ui/datatableRowSelectionMultiple.jsf :
Here's my xhtml:
<p:dataTable border="1" value="#{projectAdminisrationMB.projectNoUsersList}"
var="userObj"
selection="#
{projectAdminisrationMB.selectedUsers}"
selectionMode="multiple" rowIndexVar="rowIndex"binding="#{table2}">
<p:column id="column3">
<f:facet name="header">
<h:outputText value=" user "></h:outputText>
</f:facet>
<h:outputText value="#{userObj.name}"/>
/
<h:outputText value="#{userObj.lastName}"></h:outputText>
<h:outputText value="#{userObj.firstName}"></h:outputText>
</p:column>
<f:facet name="footer">
<p:commandButton id="addProjectUser" value=" Add " onclick="dlg1.show()" />
<p:commandButton id="deleteProjectUser" value=" Delete " />
</f:facet>
</p:dataTable>
Managed Bean :
#ManagedBean
#SessionScoped
public class ProjectAdminisrationMB implements Serializable {
private static final long serialVersionUID = 1L;
private String projectName;
private List <User> projectUsersList;
private List<User> projectNoUsersList;
private List<User> selectedUsers;
private String projectAdmin;
public ProjectAdminisrationMB() {
super();
AdministrationProjectFinal administrationProjectFinal =new
AdministrationProjectFinal();
this.projectUsersList=administrationProjectFinal.getUserList();
this.projectNoUsersList=administrationProjectFinal.getNotUserList();
}
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public List<User> getProjectUsersList() {
return projectUsersList;
}
public void setProjectUsersList(List<User> projectUsersList) {
this.projectUsersList = projectUsersList;
}
public String getProjectAdmin() {
return projectAdmin;
}
public void setProjectAdmin(String projectAdmin) {
this.projectAdmin = projectAdmin;
}
public List<User> getProjectNoUsersList() {
return projectNoUsersList;
}
public void setProjectNoUsersList(List<User> projectNoUsersList) {
this.projectNoUsersList = projectNoUsersList;
}
public List<User> getSelectedUsers() {
return selectedUsers;
}
public void setSelectedUsers(List<User> selectedUsers) {
this.selectedUsers = selectedUsers;
}
}
i'm getting this error:
javax.faces.FacesException: DataModel must implement
org.primefaces.model.SelectableDataModel when selection is enabled.....
just add this attribute rowKey to the datatable tag :
<p:dataTable border="1" value="#{projectAdminisrationMB.projectNoUsersList}"
var="userObj"
rowKey="#{userObj.name}"selection="#{projectAdminisrationMB.selectedUsers}"
selectionMode="multiple" rowIndexVar="rowIndex"
binding="#{table2}">
You can get this error if you try to add a new item to the underlying list and forget to assign a value to that new item's rowKey.
Alternatively to rowKey you can wrap your data in a custom model which really implements org.primefaces.model.SelectableDataModel. This is helpful if
all of your your classes have the same kind of #Id (e.g. a long) and can implement the same interface (e.g. EjbWithId)
you want to add additional functionalities to your data which are not domain specific and don't belong e.g. User.
The interface may be something like this:
public interface EjbWithId
{
public long getId();
public void setId(long id);
}
Then a generic implementation of SelectableDataModel for all your classes can be used:
public class PrimefacesEjbIdDataModel <T extends EjbWithId>
extends ListDataModel<T> implements SelectableDataModel<T>
{
public PrimefacesEjbIdDataModel(List<T> data)
{
super(data);
}
#Override public T getRowData(String rowKey)
{
List<T> list = (List<T>) getWrappedData();
for(T ejb : list)
{
if(ejb.getId()==(new Integer(rowKey))){return ejb;}
}
return null;
}
#Override public Object getRowKey(T item) {return item.getId();}
}
In your #ManagedBean:
private PrimefacesEjbIdDataModel<User> dmUser; //+getter
dmUser = new PrimefacesEjbIdDataModel<User>(administrationProjectFinal.getUserList());
first check whether you've added
rowKey="#{userObj.id}"
then you need to have the data table List set in filteredValue attribute of your data table in xhtml, instead of value.

JSF UIRepeat and PostBack

I have a simple page where a I use <ui:repeat> and it gets the value from a backing bean.
The initial request will give it an empty list. The postback then will invoke an action that will change the model behind the <ui:repeat> but it is not rendered?!
I debugged through it and I saw that the <ui:repeat> evaluates the value at restore view phase but thats it. When it reaches render response it does not use the latest value from my bean. Is that the expected behavior?
How can I make that work? Do I have to write my own repeat tag?
I can't really tell what could be the problem without some of your code, but these are the basics:
Backing bean:
public class ObjectService{
private DataModel objectDataModel;
private List<Object> objectList;
private Pagination paginationHelper;
private ObjectDao objectDao = new ObjectDao();
private String queryOption;
public void setQueryOption(String queryOption){
this.queryOption = queryOption;
}
public String getQueryOption(){
return this.queryOption;
}
public <E> PaginationHelper getPagination(final List<E> list) {
pagination = new PaginationHelper(10) {
#Override
public int getItemsCount() {
return list.size();
}
#Override
public DataModel createPageDataModel() {
return new ListDataModel(list);
}
};
return pagination;
}
public void setPagination(PaginationHelper pagination) {
this.pagination = pagination;
}
public List<Object> getObjectList(){
this.objectList = objectDao.readObjectsWhere(queryOption);
return this.objectList;
}
public void setObjectList(List<Object> objectList){
this.objectList = objectList;
}
public DataModel getObjectDataModel(){
if (objectDataModel == null) {
objectDataModel = getPagination(getObjectList()).createPageDataModel();
}
return objectDataModel;
}
public void setObjectDataModel(DataModel objectDataModel){
this.objectDataModel = objectDataModel
}
public String changeModel(){
objectDataModel = null;
return null;
}
}
XHTML page:
...
<h:form>
<fieldset>
<label>
<span>Option:</span>
<h:inputText value="#{objectService.queryOption}" />
</label>
<h:commandButton action="#{objectService.changeModel}" value="request data" />
</fieldset>
<ui:repeat value="#{objectService.objectDataModel}" var="objectVar">
<h:outputLabel value="#{objectVar.property1}" />
<h:outputLabel value="#{objectVar.property2}" />
<h:outputLabel value="#{objectVar.property3}" />
</ui:repeat>
</h:form>
...

Resources