Primefaces tree and how to navigate based on TreeNode leaf entity ID - jsf

I have 3 entities - markets, topics and items. Markets is the parent of topics which is the parent of items. I'm hoping to find a simple way to invoke an action by selecting a value from the the final child node (items) and being taken to the page where the selected item can be viewed. The JSF:
<p:tree value="#{treeTestBean.treeTest}" var="tree"
dynamic="true"
selectionMode="single"
selection="#{treeTestBean.selectednode}">
<p:ajax event="select" listener="#{treeTestBean.onNodeSelect}"/>
<p:treeNode>
<h:outputText value="#{tree}"/>
</p:treeNode>
</p:tree>
The managed bean:
#Named(value = "treeTestBean")
#SessionScoped
public class TreeTestBean implements Serializable {
private TreeNode treetest;
private TreeNode selectednode;
private TreeNode node0;
private TreeNode node1;
private TreeNode node2;
private List<Enmarkets> markList;
private List<Entopic> topList;
private ListDataModel<Enitem> itList;
private Enitem selItem;
public TreeNode getTreeTest() {
treetest = new DefaultTreeNode("Root", null);
markList = rootFacade.findAll();
for (Enmarkets m : markList) {
node0 = new DefaultTreeNode(m.getMarketname(), treetest);
int marketid = m.getMarketid();
topList = topfac.marketTopNorm(marketid);
for (Entopic t : topList) {
node1 = new DefaultTreeNode(t.getTopicname(), node0);
int topicid = t.getTopicid();
itList = itfac.itemFroTopic(topicid);
for (Enitem i : itList) {
node2 = new DefaultTreeNode(i.getItemname(), node1);
}
}
}
return treetest;
}
The onNodeSelect method used in the ajax is also in the managed bean. If the selected node is a leaf it will search the item name and return that in the navigated page:
public void onNodeSelect(NodeSelectEvent event) {
this.setSelectednode(event.getTreeNode());
String somekey = selectednode.getRowKey();
if(selectednode.isLeaf()){
String itemName = selectednode.getData().toString();
// Standard JPA call to search for item name here (omitted because this is not how i want to do it)
FacesContext
.getCurrentInstance()
.getApplication()
.getNavigationHandler()
.handleNavigation(FacesContext.getCurrentInstance(), null, "/Main/Starter.xhtml?faces-redirect=true");
}
else {
doNothing();
}
}
onNodeSelect is supposed to search the item name and navigates to the page with details of the selected item. The above method does this by searching for the Item name String and matching this to the name in a list of the item entity values created from the persistence layer. This will allow matching the selectednode String to the correct item name, so that the navigated jsf page is populated with the entity details (for example using a standard h:outputText tag). For several reasons, i prefer to search based on the entity ID instead of a String.

Comments from Kukeltje greatly helped me in the right direction. First I include a Map(String, int) when creating the leaf node:
for (Enitem i : itList) {
node2 = new DefaultTreeNode(i.getItemname(), node1);
String rowK = node2.getRowKey();
int itid = i.getItemid();
rowMap.put(rowK, itid);
Then, in the onNodeSelect method I use this map to match the rowKey of the selectednode to the corresponding entity Id:
public void onNodeSelect(NodeSelectEvent event) {
if(selectednode.isLeaf()){
String rKey = selectednode.getRowKey();
if(rowMap.containsKey(rKey)) {
String xKey = rowMap.get(rKey).toString();
Integer rKeyint = Integer.parseInt(xKey);
selItem = itfac.find(rKeyint);
FacesContext
.getCurrentInstance()
.getApplication()
.getNavigationHandler()
.handleNavigation(FacesContext.getCurrentInstance(), null, "/Main/Client/ItemDetails.xhtml?faces-redirect=true");
}
}
else {
doNothing();
}
This navigates to the page showing the detail of the selected node leaf. I suspect there might be an easier or more efficient way of doing this and would welcome any views. Like, I don't know if it's really necessary to make the string to integer conversions and I didn't think through a simpler way.
For now, this seems to solve my concrete problem. thanks

Related

Need to pass the current tab name to the backing managed bean from dynamically generated tab

I am using primefaces. And my requirement is to have number of tabs which will be generated based on a list specified in the backing bean. Now the second criteria is that if the tab changes the content under that tab should also changes. So I kept the onChange event and tried to get the value through event.getTab().getTitle(), but it is returning null to the backing bean.
<p:tabView id="tabView" binding="#{dndProductsView.tabView}">
<p:ajax event="tabChange" listener="#{dndProductsView.onTabChange}"/>
</p:tabView>
Managed Bean required codes are as :-
#PostConstruct
public void init() {
user = SessionBean.getUserName();
categorylist = categoryLogics.findAllOrderedByCategoryName();
productList = productLogics.findAllOrderedByProductName();
droppedProducts = new ArrayList<Product>();
}
private TabView tabView;
#Inject
private FacesContext facesContext;
public void setTabView(TabView tabView) {
this.tabView = tabView;
}
public TabView getTabView() {
tabView = new TabView();
for (Category c : categorylist) {
Tab t = new Tab();
t.setTitle(c.getCategoryName());
tabView.getChildren().add(t);
}
return tabView;
}
public void onTabChange(TabChangeEvent event) {
String titleName = event.getTab().getTitle();
System.out.println("" + titleName);
}
The tab is getting generated properly and when the tab changes, the onTabChange() method is called but event.getTab().getTitle() returns null.
Integer index=(Integer)tabview.getActiveIndex();
It is not a name but it is index of activ tab witch in this case is the one you are interested in.
Index starts from 0 being the first tab :)

How to get data from the controller model to the view

hi guys sorry to post again but this is really confusing me
i have a query that i can get to run, the user enters a string and then the application will search for this in the database connected to the application, this bit i have working, however now i have successfully run the queury i am unsure of how to retrieve the data from it and be able to use it in the view in a h:datatable
currently to do the search, this is what is in the view, the faclet page the user enters
<h:inputText id="search" value="#{userdetailsController.search}" />
<p:commandButton value="Search" action="#{userdetailsController.submit}" ajax="true" />
this then goes to
#Named("userdetailsController")
#SessionScoped
public class UserdetailsController implements Serializable {
#EJB
private String search;
private List<Userdetails> item; // No need for DataModel here.
public String submit() {
item = ejbFacade.searchByString(search);
return ""; //change this !, testing only
}
public String getSearch() {
return search;
}
public void setSearch(String search) {
this.search = search;
}
then
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
private List userList;
/* trying out a search function */
public List<T> searchByString(String string) {
System.out.println("in SearchByString");
return getEntityManager().createNamedQuery("Userdetails.findByUsername").setParameter("username", "%" + string + "%").getResultList();
}
which does the search in
#Entity
#Table(name = "USERDETAILS")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Userdetails.findAll", query = "SELECT u FROM Userdetails u"),
#NamedQuery(name = "Userdetails.findById", query = "SELECT u FROM Userdetails u WHERE u.id = :id"),
#NamedQuery(name = "Userdetails.findByUsername", query = "SELECT u FROM Userdetails u WHERE u.username = :username")})
How can i once this process has been completed retrieve the data to print out in the console for example, what do i need to call to do this ?
i am unsure of how to retrieve the data from it
Your code already does that in the submit() method.
and be able to use it in the view in a h:datatable
Just add the following to your view, maybe below the command button in the same form, in order to present it:
<h:dataTable value="#{userdetailsController.item}" var="userdetails">
<h:column>#{userdetails.username}</h:column>
</h:dataTable>
And make sure that this is covered in the ajax update of the command button:
<p:commandButton ... update="#form" />
Unrelated to the concrete problem, I'd only rename the confusing property name item to items as it represents a collection of items, not a single item. Also, your submit() method doesn't need to return an empty string. It can also just be declared void. Also, ajax="true" is the default already for <p:commandButton>, you can just omit it.

JSF calling methods in JPA populated list

I have a database table with some oneToMany relations.
this is fragment of the entity:
#OneToMany(mappedBy="auction")
private List<Biding> bidings;
now i want to print higher bid on my jsf website:
<ui:repeat var="singleAuction" value="#{auctionListBean.auctionList}" varStatus="status">
<h:outputLabel value="#{singleAuction.getHigherBid()}"/>
</ui:repeat>
this my aucListBean
#ManagedBean
public class AuctionListBean
{
#PersistenceContext()
EntityManager entityManager;
public List<AuctionBean> getAuctionList() {
Query query = entityManager.createQuery("SELECT e FROM Auction e");
#SuppressWarnings("unchecked")
List<AuctionBean> resultList = (List<AuctionBean>) query.getResultList();
return resultList;
}
}
I also have AuctionBean class which I used before to add new auction. Now I want to create a bean which has one property: list of auctionBean. I populate it using my entity and cast it to AuctionBean. In AuctionBean class I implemented mentioned method:
public double getHigherBid()
{
double higherBid = 0;
for(Biding a : bidings)
{
if(a.getCurrentPrice() > higherBid)
higherBid = a.getCurrentPrice();
}
return higherBid;
}
The problem is "Method not found". It seems like it still dont even use AuctionBean class for some reason. It may be a problem why it cannot see the method. I am doing it right and where is the problem exactly? Could you help?
I have two suggestions:
1. Use singleAuction.higherBid, not singleAuction.getHigherBid()
2. Specify the target class of your query. Here's an example:
return entityManager.createQuery("SELECT e FROM Auction e", AuctionBean.class)
.getResultList();

Getter called multiple times - selected item not retained in JSP

I am working with JSF 1.2 and could use a little advice. I have an FMB (PlanFMB.java) that contains an array list of select items and a single selectedItem.
When the page loads, the getProjects() method is correctly called and displays the Projects as expected. Strange thing is though, the getSelectedItem() method is called three times (once of each project). Not sure if this is typical behavior:
SystemOut O getSelectedItem = null
SystemOut O getSelectedItem = null
SystemOut O getSelectedItem = null
Also, I have a command link in my JSP, that when clicked does the same thing, calls the getSelectedItem() method three times:
<h:commandLink action="#{planDocBean.classAction}" id="classActionENLink">
PlanFMB.java
String selectedItem = null;
private List<SelectItem> selectItems = null;
public String getSelectedItem() {
System.out.println("getSelectedItem = " + selectedItem);
return selectedItem;
}
public void setSelectedItem(String selectedItem) {
this.selectedItem = selectedItem;
System.out.println("setSelectedItem = " + selectedItem);
}
public List<SelectItem> getProjects() {
if (selectItems == null) {
selectItems = new ArrayList<SelectItem>();
selectItems.add(new SelectItem("Project1", "Project1"));
selectItems.add(new SelectItem("Project2", "Project2"));
selectItems.add(new SelectItem("Project3", "Project3"));
}
return selectItems;
}
<h:selectOneMenu id="items" value="#{planDocBean.selectedItem}">
<f:selectItems value="#{planDocBean.projects}" />
</h:selectOneMenu>
One last thing, the actual selected item is not retained in the select menu when the page reloads.
Any feedback much appreciated. Thanks!

How to bind data with checkbox list in JSF?

I've the following code in my edit user screen
<h:selectManyCheckbox id="selectedGroups" value="#{usersController.selectedGroups}">
<f:selectItems value="#{usersController.groupsList}" var="item" itemLabel="#{item.groupname}" itemValue="#{item.groupid}" />
</h:selectManyCheckbox>
I've user groups list with all the groups in it, and I've selectedGroups list with the groups that are enabled for the user. But, on the edit screen, they are not showing selected by default. What am I missing? Is this not the right way to bind selected many checkboxes?
An item value of the groupsList will be preselected only when equals() method has returned true for at least one item in the selectedGroups.
Assuming that groupid is a Long, then the selectedGroups should return a List<Long> containing the values to be preselected.
Following code will work perfectly for request scope bean...
xhml code....
<h:selectManyCheckbox binding="#{Page1.chk_1}">
<f:selectItem binding="#{Page1.chk_1_options}"/>
</h:selectManyCheckbox>
Java code....
HtmlSelectManyCheckbox chk_1 = new HtmlSelectManyCheckbox();
UISelectItems chk_1_options = new UISelectItems();
public HtmlSelectManyCheckbox getChk_1() {
return chk_1;
}
public void setChk_1(HtmlSelectManyCheckbox chk_1) {
this.chk_1 = chk_1;
}
public UISelectItems getChk_1_options() {
if (chk_1_options.getValue() == null) {
List<SelectItem> lst_chk_options = new ArrayList<SelectItem>();
lst_chk_options.add(new SelectItem(1, "Label1"));
lst_chk_options.add(new SelectItem(2, "Label2"));
chk_1_options.setValue(lst_chk_options);
}
return chk_1_options;
}
public void setChk_1_options(UISelectItems chk_1_options) {
this.chk_1_options = chk_1_options;
}
If you want for session scope then reply, because binding elements in session scope giving problems in some cases...

Resources