I have an object that represents a service provider. In that object I have this hashmap
private Map<MetaDataKeys, String> metaData;
The "MetaDatatKeys" is a enum that looks like this,
public enum MetaDataKeys {
PROVIDER_NAME, PROVIDER_CONTACT_NAME, PROVIDER_SERVICE_RADIUS;
}
I would like to display the hashmap key/value pairs in a datatable or similar for editing, something along the lines of,
<p:dataTable id="providerDatatable" var="infoMap" value="#{editUserBean.editUser.metaData}">
<p:column><h:outputText value="#{infoMap.key.metaData}"/></p:column>
<p:column><h:inputText value="#{infoMap.key.value}"/></p:column>
</p:dataTable>
In my backing bean "editUser" is the object that contains the map.
what is the best way to go about this? I have not been successful in even getting the table to render and populate with values. In searching most examples use a string or a primitive for the key.
You should make iteration in the datatable by Map.entrySet() it's better way. If you try to do itaration by Map.keySet() and than take value by key you can take O(n^2).
For your task realisation looks like:
<p:dataTable id="providerDatatable" var="infoMap" value="#{editUserBean.editUser.metaData.entrySet()}">
<p:column><h:outputText value="#{infoMap.key}"/></p:column>
<p:column><h:inputText value="#{infoMap.value}"/></p:column>
</p:dataTable>
To edit table row you can you use p:cellEditor more info about this component you can find at the Primefaces show case
Related
This question already has answers here:
How to set a Map value in h:inputText
(1 answer)
Write to a map property in an h:inputText in h:dataTable
(1 answer)
Closed 4 months ago.
I have a page where the user must input grading for a number of categories. The categories are retrieved dynamically from a database (there are different user types, and for each type you get different categories). As there are subcategories, I have implemented it using <p:treeTable>.
I have the grades stored in a map, with the category id as the key and the grade as the value:
HashMap<Integer, Double> detailedGrades
The problem is how to get and set the grade for each category using <p:inputText>, because the category id has to be a parameter in that. I have managed to do the getter like this:
<p:inputText id="cat" value="#registerCandidateGradeBean.getGradeForCat(gradingCat.pkCertGradeCategoryId)}"/>
and in the bean:
public Double getGradeForCat(int catID){
return detailedGrades.containsKey(catID) ? detailedGrades.get(catID) : null;
}
This displays the value in the input field OK, but I don't know how to set the value when the user changes it. I tried with <p:ajax listener> as mentioned here, where I set
<p:ajax listener="#{registerCandidateGradeBean.setGradeForCat1(gradingCat.pkCertGradeCategoryId)}"/>
and in the bean:
public void setGradeForCat1(int catID){
System.out.println(catID);
}
but whenever I change the input value I get a "javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation" exception. I tried to use a valueChangeListener on the inputText
<p:inputText id="cat" value="#registerCandidateGradeBean.getGradeForCat(gradingCat.pkCertGradeCategoryId)}"
valueChangeListener="#{registerCandidateGradeBean.setGradeForCat}"/>
and in the bean:
public void setGradeForCat(ValueChangeEvent e){
System.out.println("called");
//System.out.println(catID);
System.out.println(e.getNewValue());
}
but it never gets called. (I have tried both setGradeForCat(ValueChangeEvent e) and setGradeForCat(ValueChangeEvent e, int catID)).
Any ideas?
Forgot to mention: we are using primefaces 5.3.
The problem is, that you use value="#registerCandidateGradeBean.getGradeForCat(gradingCat.pkCertGradeCategoryId)}" in the input component.
This makes jsf looking for a getter and setter which is called getgetGradeForCat and setgetGradeForCat.
for manage a cart i have create an HashMap and i convert this in a list for display into a PrimeFaces Datatable with this method:
public List<Map.Entry<Livre, Integer>> getPanier() {
Set<Map.Entry<Livre, Integer>> panierSet = panier.entrySet();
return new ArrayList<Map.Entry<Livre, Integer>>(panierSet);
}
Once the list shown i wish to update the quantity directly inside the datatable with inputText.
But i have no idea if this is possible ? or if i need to convert HashMap in ArrayList for do this traitement.
You can use something like this in your table
<h:inputText value="#{myMap[someVarUsedInDatatable.keyOfThatRow]}"/>
That will allow you to read and modify the relevant value in the relevant key...
I'm trying to put an autocomplete that fetches suggestions as a list of Entry<String, Integer>
<p:autoComplete completeMethod="#{suggester.suggestTopics}"
var="x1" itemLabel="#{x1.key}" itemValue="#{x1.value.toString()}"
value="#{topicController.selected}" />
Manged bean code is as follows:
private int selected;
public int getSelected() {
return selected;
}
public void setSelected(int selected) {
this.selected= selected;
}
But this fails saying the Integer class doesn't have method/property named key. If I remove the value attribute from autocomplete then it starts working properly. But when I put value attribute it starts expecting that the object inside var should be of the same type as that inside value attribute. I believe/expect it should be that the object inside itemValue should be of the same type as that inside value attribute.
I want to use POJOs for suggestions but pass just the entity Id to the value
Using :
Primefaces 3.1
JSF 2.1.6
I believe/expect it should be that the object inside itemValue should
be of the same type as that inside value attribute.
Yes this makes sense, and it is the same in the primefaces showcase:
<p:autoComplete value="#{autoCompleteBean.selectedPlayer1}"
id="basicPojo"
completeMethod="#{autoCompleteBean.completePlayer}"
var="p" itemLabel="#{p.name}" itemValue="#{p}"
converter="player" forceSelection="true"/>
As you see is var="p" and itemValue="#{p} where p is an instance of Player. And selectedPlayer1 is also an instance of Player.
I don't know if it works with a Map since the Primefaces example is called "Pojo support" and the suggestions should be a List of elements of the same type as in the value attribute.
I think you want to use the Simple auto complete , but instead you looked at the wrong example on the showcase of the Pojo Support
x1 refers to the int selected - while it expect to be referred to a POJO (with key and value properties.) , that's why you get the message
Integer class doesn't have method/property named key
Or simple use the Simple auto complete
As commented to Matt you dont need to rebuild Player(Pojo) from Db. You can set simply id property of Player(Pojo) and in action method may be utilize this id to fetch it from DB.
In your case in convertor you might do
Entry<String, Integer> e = new Entry<String, Integer>();
e.setId(value) // where value is passed in to convertor in method getAsObject.....
This value will be set to private Entry<String, Integer> selected
I have used Pojo autocomplete but not tried with generic classes.
Hope this helps.
I know the question is outdated but I've had the same problem.
The point is that you have to assign var to p (var="p"). I think it's terribly unobvious (documentation doesnot mention it has to be that way) 'cause I thought I can assign any var name I want.
here is an example :
<h:outputLabel for="category1" value="Cateogry"/>
<h:selectOneMenu id ="category1" value="#{articleManageBean.categoryId1}"
converter="categoryConverter">
<f:selectItems value="#{articleManageBean.categories}" var="category"
itemValue="#{category.id}" itemLabel="#{category.name}" />
</h:selectOneMenu>
and here is the managed bean that I have
#ManagedBean
#SessionScoped
public class ArticleManageBean {
private Long categoryId1;
private List<Category> categories;
//...
}
The categories list gets populated from db, and selectOneMenu gets populated with this list using a converter.
My First question:
If I want to create another selectOneMenu in my jsf page I would have to copy paste the entire thing and just change the value of selectOneMenu to say categoryId2 thus putting another attribute to managed bean called categoryId2. That is not practical. I want to map these values of selectMenu to list items, for instance to an attribute
List<Long> categoryIds;
if I use
<h:selectOneMenu id ="category1" value="#{articleManageBean.categoryIds.[0]}" >
I get an error
javax.el.PropertyNotFoundException: /createArticle.xhtml #47,68 value="#{articleManageBean.categoriesId[0]}": Target Unreachable, 'null' returned null
If I nitialize the Araylist then I get this exception
javax.el.PropertyNotFoundException: /createArticle.xhtml #47,68 value="#{articleManageBean.categoriesId[0]}": null
My second question:
Is there a way to dinamicly write selectOneMenu tags, by that I mean not to copy paste the entire tag, just somehow create a function that take the categoryId parameter and writes automaticaly the tag (somekind of custom tag maybe ?)
Hope you understood my questions
thanks in advance
Use the brace notation instead to specify the index.
<h:selectOneMenu id="category1" value="#{articleManageBean.categoryIds[0]}">
You only need to make sure that you have already prepared the values behind #{articleManageBean.categoryIds}. JSF won't do that for you. E.g.
private List<Long> categoryIds = new ArrayList<Long>();
public ArticleManageBean() {
categoryIds.add(null);
categoryIds.add(null);
categoryIds.add(null);
// So, now there are 3 items preserved.
}
an alternative is to use Long[] instead, this doesn't need to be prefilled.
private Long[] categoryIds = new Long[3]; // So, now there are 3 items preserved.
I am using the Primefaces wizard component. On one tab I am dynamically creating input boxes based on previous tabs input(user type). The inputbox text labels are derived from a list. In my backing bean, I have a map that contains input labels as keys and inputbox inputs as values.
Clicking on next, I would like the map(values) to be updated with the user input (corresponding to the key)
<c:forEach items="#{gdsiGeodataBean.actionCommand.fields}" var="reqs">
<h:outputLabel for="#{reqs.name}" value="#{reqs.name}:* " />
<pou:inputText value="#{gdsiGeodataBean.actionCommand.values['reqs.name']}" required="true" requiredMessage="Input is required."/>
</c:forEach>
My backing bean :
private List<RequiredParam> fields; // +getter (no setter required)
private Map<String, String> values; // +getter (no setter required)
public CommandAction(String actionName, String actionParams, String context) {
this.actionName = actionName;
this.actionParams = actionParams;
this.contextName = context;
//Set up parameters
getRequiredParams();
getOptionalParams();
fields = getFields();
values = new HashMap<String, String>();
}
Essentially what I would like is for the map values to be updated with user inputs from the textinput boxes.
Your approach to bind the input value to a map is not entirely correct.
<pou:inputText value="#{gdsiGeodataBean.actionCommand.values['reqs.name']}" required="true" requiredMessage="Input is required."/>
You're specifying a fixed map key instead of a dynamic map key based on the currently iterated #{reqs}. This way all submitted values will end up in one and same fixed map key "reqs.name", whereby each one overrides each other so that you only get the value of the last field in the map.
You need to remove those singlequotes to make it a really dynamic key.
<pou:inputText value="#{gdsiGeodataBean.actionCommand.values[reqs.name]}" required="true" requiredMessage="Input is required."/>
Unrelated to the concrete question, even though this approach will work when used as-is in your question, the <c:forEach> will fail in certain circumstances. E.g. when used inside a composite component or an iterating JSF component. Rather use <ui:repeat> instead. See also JSTL in JSF2 Facelets... makes sense?