JSF selectOneMenu with Object iteration - jsf

I do know that similar problem was announced here few times but I spent a lot of time and still have no idea why that code doesn't work :/
This is my JSF page:
<h:form>
<h:selectOneMenu value="#{productBean.productName}">
<f:selectItems value="#{productBean.products}" var="c" itemValue="#{c.name}"/>
</h:selectOneMenu>
</h:form>
This is my productBean:
public class ProductBean extends Connector
{
private List<Product> products;
private Product product;
private String productName;
//setters and getters
public List<Product> getProducts() throws SQLException
{
resultSet = statement.executeQuery("SELECT * FROM dbo.products");
products = new ArrayList<Product>();
while(resultSet.next())
{
product = new Product();
product.setId_product(resultSet.getInt("id_product"));
product.setName(resultSet.getString("name"));
product.setCategory(resultSet.getInt("category_id"));
product.setIs_available(resultSet.getInt("is_available"));
products.add(product);
}
return products;
}
}
And finally product class:
public class Product
{
private int id_product;
private String name;
private int price;
private int category;
private int is_available;
/setters and getters
}
My goal is to have a menu list with products names. All i got in the expanded list are references.
I also tried to declare everything in the bean class and make ArrayList instead of ArrayList but i think it's not nice. It did't work anyway.
Tell me if I understand it corectly. productBean.productName is some kind of holder. productBean.products is a whole Products list and the c.name means that I want only name from the actual product.

You must also include the itemLabel :
<f:selectItems value="#{productBean.products}" var="c" itemValue="#{c.name}" itemLabel="#{c.name}" />

Related

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

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

Search function not doing anything

sorry if this is a poor question but this one feature have been driving me mad for days so i thought id post it here to see if you guys can help me
basically all i want to do from a jsf page have the user search a user and for me to return all the details
<h:form id="searchForm">
<h:outputLabel value="Search: " style="font-weight:bold" />
<h:inputText id="search" value="#{userdetailsController.search}" />
<h:commandButton value="Search" action="index"/>
</h:form>
that is the jsf page, working fine
it calls my userdetailsController class
#Named("userdetailsController")
#SessionScoped
public class UserdetailsController implements Serializable {
private Userdetails current;
private DataModel items = null;
#EJB
private Richard.beans.UserdetailsFacade ejbFacade;
private PaginationHelper pagination;
private int selectedItemIndex;
private String search;
public String getSearch() {
System.out.println("inGetSearch");
return search;
}
public void setSearch(String search) {
this.search = search;
}
......
a contactsService class
#Stateless
public class ContactsService {
// Add business logic below. (Right-click in editor and choose
// "Insert Code > Add Business Method")
#EJB
private UserdetailsFacade cf;
public List<Userdetails> searchByString(String string) {
return cf.searchByString(string);
}
public List<Userdetails> getAllPersons() {
return cf.findAll();
}
}
an AbstractFacade class
/* trying out a search function */
public List<T> searchByString(String string) {
System.out.println("in SearchByString");
return getEntityManager().createNamedQuery("Userdetails.findByUsername").setParameter("string", "%" + string + "%").getResultList();
}
and the Userdetails class with the query i am trying to search
#NamedQuery(name = "Userdetails.findByUsername", query = "SELECT u FROM Userdetails u WHERE u.username = :username")})
currently only the getters and settings are working in Getsearch
how can i make this work as i have spent days on this feature and are still no closer, sorry this is my first time at this
thanks guys
EDIT
would adding
public List<Userdetails> getAllPersons() {
if (search == null) {
return cs.getAllPersons();
}
return cs.searchByString(search);
}
in the UserdetailsController be enough ?
You're not invoking any action here:
<h:commandButton value="Search" action="index"/>
So it's indeed logical that it isn't "doing anything".
You need to invoke a managed bean action which in turn executes the desired code to obtain the desired data from the DB and assign to a property:
<h:commandButton value="Search" action="#{userdetailsController.submit}" />
with inside UserdetailsController:
private String search;
private List<UserDetail> items; // No need for DataModel here.
#EJB
private UserdetailsFacade ejbFacade;
public String submit() {
items = ejbFacade.searchByString(search);
return "index";
}
Your whole ContactsService seems useless by the way.
As per your attempt in the getter method in the update of your question, please don't do that. You should never call the DB in a getter method for the reasons mentioned in Why JSF calls getters multiple times

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

h:selectManyListBox setter not setting all the values selected

<h:selectManyListbox id="sectorsListBox" size="2" multiple="multiple" value="#{Mybean.classificationSelectedItems}">
<f:selectItems id="sectors" value="#{Mybean.classificationSelectItems}"/>
</h:selectManyListbox>
Backing Bean has:
public class Mybean
{
private Map<String,String> classificationSelectItems = new LinkedHashMap<String,String>();
private List<String> classificationSelectedItems = new ArrayList<String>();
//getter and setter for both.
}
init()
{
classificationSelectItems.put("INS","Insurance")
classificationSelectItems.put("HLC","HealthCare")
}
The select many box gets initialized with these 2 values but the problem is only the last selected entry is getting stored in classificationSelectedItems. Why is that so ? And how do I get all the selected entries stored in the list of classificationSelectedItems ?
Adding FYI, the init method is class by Spring.
I have tested with an examle(reference:http://www.mkyong.com/jsf2/jsf-2-multiple-select-listbox-example/), good luck :)
Facelets:
<h:form id="form">
<h:selectManyListbox value="#{user.favFood1}" >
<f:selectItems value="#{user.favFood2Value}" />
</h:selectManyListbox>
<h:commandButton value="test"/>
</h:form>
Bean:
#ManagedBean(name = "user")
#ViewScoped
public class UserBean implements Serializable {
private static final long serialVersionUID = 1L;
public List<String> favFood1;
private Map<String, Object> food2Value;
public UserBean() {
favFood1 = new ArrayList<String>();
food2Value = new LinkedHashMap<String, Object>();
food2Value.put("Food2 - Fry Checken", "Fry Checken1"); //label, value
food2Value.put("Food2 - Tomyam Soup", "Tomyam Soup2");
food2Value.put("Food2 - Mixed Rice", "Mixed Rice3");
}
public List<String> getFavFood1() {
return favFood1;
}
public void setFavFood1(List<String> favFood1) {
this.favFood1 = favFood1;
}
public Map<String, Object> getFavFood2Value() {
return food2Value;
}
}
I noticed exactly this behaviour when I used a Collection in the setter method, like
public void setClassificationSelectedItems(Collection<String> in){
// store it somewhere
}
This setter is called during the restore phase but not during the update phase, so the previously set value will be set, but never the new one. If you use a List, it works as expected:
public void setClassificationSelectedItems(List<String> in){
// store it somewhere
}
Note that you will need to redeploy the application after such a change because the JSP needs to be recompiled but this isn’t done automatically.

showing 1-n relations in JSF

I want to place a table on my page. I have two tables in my database for example users and locations. Every location has more than one user. I want to list these locations and show the users who live in these locations.
Los Angeles
John Locke
Dr. Jack
Mr. Eco
Like the below image, could someone do this in JSF?
Thanks.
You can use RichFaces to do such thing:
<h:form>
<rich:dataList var="city" value="#{myBean.allCity}">
<h:outputText value="#{city.name}" ></h:outputText>
<rich:dataList var="user" value="#{city.users}">
<h:outputText value="#{user.name}" ></h:outputText>
</rich:dataList>
</rich:dataList>
</h:form>
Where allCity - list of the City, and every City has list of the user inside.
See http://livedemo.exadel.com/richfaces-demo/richfaces/dataLists.jsf?c=dataList&tab=usage for example.
Backing bean:
myBean:
public class MyBean(){
private ArrayList<City> allCity= new ArrayList<City>();
#PostConstruct
public void init(){
//fill Array list
}
public ArrayList<City> getAllCity() {
return allCity;
}
}
City:
public class City{
private ArrayList<User> users= new ArrayList<User>();
public City( ArrayList<User> users){
this.users = users;
// you can get data from database in myBean, and pass it hear with cinstructor;
}
public ArrayList<User> getUsers() {
return allCity;
}
}
User
public class User{
private String name;
//constructor and others fields;
public String getName(){
return name;
}
}
Only MyBean you register as backing-bean. I show you only base structure of class, how you fill it with data is you choice.

Resources