I've got template which has: header, footer, menu (left side), cart (right side) and content at center. I select category from menu and send it via parameter to view page which overrides content from template. Then i use commandButton to add any product to cart. It works but next I select different category from menu view page updates with other products but my cart (included in template) does not. It remains as it was before when I was on the view page with this category. How can I overcome this problem? Thanks for any solution.
template:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:metadata>
<f:viewParam name="category"/>
</f:metadata>
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<h:outputStylesheet name="./css/default.css"/>
<h:outputStylesheet name="./css/cssLayout.css"/>
<title>Drummers Store</title>
</h:head>
<h:body>
<div id="container">
<div id="top">
<div id="top-content">
<div style="text-align: left; margin-left: 50px; margin-top: 20px;">
<p:graphicImage value="./resources/images/logo.png" height="80px" width="80px" />
</div>
<h:form>
<p:menuButton style="font-size: 10px;" value="account_name">
<p:menuitem value="Account Settings" />
<p:separator />
<p:menuitem value="Logut" />
</p:menuButton>
</h:form>
</div>
</div>
<div id="left">
<div id="left-content">
<h:form id="form" style="width: 290px;" >
<p:panelMenu id="categories" style="text-align: center;">
<c:forEach items="#{dSServerBean.categories}" var="c">
<p:submenu label="#{c.category_name}">
<c:forEach items="#{c.sub_categories}" var="s">
<c:if test="#{not s.sub_categories.isEmpty()}">
<p:submenu label="#{s.subCategory_name}">
<c:forEach items="#{s.sub_categories}" var="si">
<p:menuitem value="#{si.subCategory_name}" outcome="productView">
<f:param name="category"
value="#{si.subCategory_name.toLowerCase()}" />
</p:menuitem>
</c:forEach>
</p:submenu>
</c:if>
<c:if test="#{s.sub_categories.isEmpty()}">
<p:menuitem value="#{s.subCategory_name}" outcome="productView">
<f:param name="category"
value="#{s.subCategory_name.toLowerCase()}" />
</p:menuitem>
</c:if>
</c:forEach>
</p:submenu>
</c:forEach>
</p:panelMenu>
</h:form>
</div>
</div>
<div id="right">
<div id="right-content">
<h:form style="width: 85%; margin: 0 auto; margin-top: 50px;">
<p:panel>
<f:facet name="header">Cart</f:facet>
<f:facet name="footer">To pay: 0 $</f:facet>
<p:scrollPanel id="scroll2"
style="height: 200px;
max-height: 200px;
overflow-wrap: break-word;">
<p:dataGrid value="#{dSBean.cart}" var="p"
columns="1" emptyMessage="No products added..."
style="border: 0;">
<h:panelGrid>
<h:outputText style="font-size: 10px;" value="#{p.name}" />
</h:panelGrid>
</p:dataGrid>
</p:scrollPanel>
</p:panel>
</h:form>
</div>
</div>
<div id="center">
<div id="center-content">
<ui:insert name="content" />
</div>
</div>
<div id="bottom">
<div id="bottom-content">
<p style="padding: 1px;">Copyright © <b>Drummers Store</b> 2013</p>
</div>
</div>
</div>
</h:body>
</html>
view:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui">
<f:metadata>
<f:viewParam name="category"/>
</f:metadata>
<body>
<ui:composition template="./templates/mainLayout.xhtml">
<ui:define name="right">
right
</ui:define>
<ui:define name="content">
<h:form>
<p:scrollPanel id="scroll1" style="height: 700px; max-height: 700px; width: 100%;">
<p:dataGrid value="#{dSServerBean.getProducts(param.category)}"
var="product" columns="1">
<p:panel header="#{product.name}">
<h:panelGrid style="width:100%;">
<h:outputText value="#{product.description}" />
<h:commandButton value="DODAJ" action="#{dSBean.addToCart(product)}" >
<f:param name="category" value="#{param.category}" />
</h:commandButton>
</h:panelGrid>
</p:panel>
</p:dataGrid>
</p:scrollPanel>
</h:form>
</ui:define>
</ui:composition>
</body>
</html>
DSServerBean:
#ManagedBean
#ApplicationScoped
public class DSServerBean {
public Set<Category> categories = new CategoriesTemplate().categoriesTemplate;
public static Set<Product> products = new ProductsTemplate().productsTemplate;
public Map<String, Set<Product>> category_products;
public DSServerBean() {
category_products = new TreeMap<>();
for(Category category : categories){
category_products.put(category.getCategory_name().toLowerCase(), new TreeSet<Product>());
for(SubCategory subCategory : category.getSub_categories()){
category_products.put(subCategory.getSubCategory_name().toLowerCase(), new TreeSet<Product>());
for(SubCategory subSubCategory : subCategory.getSub_categories()){
category_products.put(subSubCategory.getSubCategory_name().toLowerCase(), new TreeSet<Product>());
}
}
}
for(Product product : products){
for(String category : product.getCategories().split(",")){
category_products.get(category).add(product);
}
}
}
public Set<Category> getCategories() {
return categories;
}
public Map<String, Set<Product>> getCategory_products() {
return category_products;
}
public List<Product> getProducts(String category){
List<Product> view = new ArrayList<>();
for(Product p : category_products.get(category))
view.add(p);
return view;
}
}
DSBean:
#ManagedBean
#SessionScoped
public class DSBean {
private User logged_user;
private List<Product> cart;
public DSBean(){
logged_user = new User("Marian");
cart = new ArrayList<>();
}
public User getLogged_user() {
return logged_user;
}
public List<Product> getCart() {
return cart;
}
//METHODS
public String addToCart(String product){
System.out.println(product);
for(Product p : DSServerBean.products)
if(p.toString().equals(product))
cart.add(p);
return "productView";
}
}
Ok. I'll found alternative solution, just as I mentioned before. I change view via action attribute (instead outcome attribute) of menuitem which has linked parameter which I obtain in managed bean (not in view like before). Thanks for interest.
Related
I am trying to create Primefaces <p: treeView> with <p: textEditor> inside each <p: treeNode>. The problem is that <p: textEditor> only renders correctly in the root of <p: treeView>. On the other hand, <p: inputText> renders correctly on every <p: treeNode>.
my xhtml:
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form id="main_form" style="width: 100%;">
<p:outputPanel style="width: 100%; height: 100%;overflow: auto;display: block">
<p:tree id="commentsTree" value="#{commentsTreeManagedBean.root}" var="comment" style="width: 100%;">
<p:treeNode>
<p:inputText value="#{comment.content}"/>
<p:textEditor widgetVar="editor2" value="#{comment.content}" height="300" style="margin-bottom:10px" placeholder="Enter your content">
<f:facet name="toolbar">
<span class="ql-formats">
<button class="ql-bold"></button>
<button class="ql-italic"></button>
<button class="ql-underline"></button>
<button class="ql-strike"></button>
</span>
<span class="ql-formats">
<select class="ql-font"></select>
<select class="ql-size"></select>
</span>
</f:facet>
</p:textEditor>
</p:treeNode>
</p:tree>
</p:outputPanel>
</h:form>
</h:body>
</ui:composition>
thanks in advance.
I'm trying to update a outputPanel component when a tabView is changed but I could not find the way. Otherway I found was to update the complete form but I would rather to update only the component.
I tried update with :frmTest:grpButtons and frmTest:grpButtons, and the only thing it worked was frmTest.
Any idea about what is wrong.
test.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
template="/WEB-INF/template.xhtml">
<ui:define name="pageTitle">Test</ui:define>
<ui:define name="content">
<h:form id="frmTest" prependId="true">
<div class="Container100">
<div class="ContainerIndent">
<div class="Card ShadowEffect TexAlLeft">
<p:tabView id="tabView">
<p:ajax event="tabChange" listener="#{testBean.onTabChange}"
update=":frmTest:grpButtons"/>
<p:tab title="First" id="tab1">
<div class="Card ShadowEffect TexAlCenter">
<br/>
<h2>Empty Page 1</h2>
<br/>
<span class="gray">Use this page to start from scratch and place your custom content.</span>
<br/><br/>
</div>
</p:tab>
<p:tab title="Second" id="tab2">
<div class="Card ShadowEffect TexAlCenter">
<br/>
<h2>Empty Page 1</h2>
<br/>
<span class="gray">Use this page to start from scratch and place your custom content.</span>
<br/><br/>
</div>
</p:tab>
</p:tabView>
<p:separator/>
<p:outputPanel id="grpButtons" rendered="#{testBean.showButtons}">
<p:commandButton id="btnSaveSol" value="#{msgs.save}"
styleClass="Fright GreenButton"
action="#{testBean.save}"
ajax="true"
update=":frmTest"/>
</p:outputPanel>
</div>
</div>
</div>
</h:form>
</ui:define>
</ui:composition>
TestBean.java
#ViewScoped
#ManagedBean
public class TestBean implements Serializable {
private static final long serialVersionUID = 4078818945032342504L;
private Arxiu arxiu;
private boolean showButtons = true;
#PostConstruct
private void init() {
loadLocale();
}
//----------------------------------------------------------------
// Methods
//----------------------------------------------------------------
public void onTabChange(TabChangeEvent event) {
showButtons = !event.getTab().getId().equals("tab2");
}
public void save() {
System.out.println("save");
}
//Getters and setters
}
I found a way that works but I still don't know why it doesn't work as I was in the question. Could it be a primefaces error?
I wrapped the outputPanel with a panel and the attribute widgetVar="var" and then update="#widgetVar(var)".
Modifications of code
<p:ajax event="tabChange" listener="#{testBean.onTabChange}"
update="pnlButtons"/>
...
<p:panel id="pnlButtons">
<p:outputPanel id="grpButtons" rendered="#{testBean.showButtons}">
<p:commandButton id="btnSave" value="#{msgs.save}"
styleClass="Fright GreenButton"
action="#{testBean.save}" ajax="true"
rendered="#{testBean.showButtons}"/>
</p:outputPanel>
</p:panel>
I have a f:setPropertyActionListener within a data table and clicking on a command button the setpropertyaction listener is not being called. Any one see where I am going wrong?
thanks
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:form id="userDetailsForm" style="padding:5px">
<p:growl id="messages" showDetail="true" autoUpdate="true" life="2000"/>
<p:spacer height="15"></p:spacer>
<div class="row">
<div class="col-lg-4">
<div class="input-group">
<p:inputText type="text" styleClass="form-control" value="#{emailArticleBean.searchText}" />
<span class="input-group-btn" style="margin:3px;">
<p:commandButton actionListener="#{emailArticleBean.search}" value="Go!" update=":userDetailsForm:emailArticleTable" />
</span>
</div><!-- /input-group -->
</div><!-- /.col-lg-6 -->
</div><!-- /.row -->
<p:spacer height="15"></p:spacer>
<h:messages/>
<div class="row">
<div class="col-lg-1">
</div>
<div class="col-lg-11">
<p:dataTable var="email" value="#{emailArticleBean.emailArticles}" scrollRows="20"
scrollable="true" liveScroll="true" scrollHeight="750" id="emailArticleTable"
>
<p:column>
<p:accordionPanel multiple="true" activeIndex="-1" id="panel#{email.id}">
<p:tab title="#{email.headline}" titleStyleClass="email-header">
<div style="clear:both;margin-bottom:10px;">
<h6 style="font-weight:bold;">Summary</h6>
<h:outputText
value="#{email.summary}" />
</div>
<div style="clear:both;margin-bottom:10px;">
<h6 style="font-weight:bold;">Implication</h6>
<h:outputText
value="#{email.implication}" />
</div>
<div style="float:left;clear:both">
<p:commandButton value="View Existing Actions"
oncomplete="PF('dlg2').show();" update=":userDetailsForm:emailActionDialog">
<f:setPropertyActionListener value="#{email}" target="#{emailArticleBean.selectedEmail}" />
</p:commandButton>
</div>
<br/>
<br/>
<div style="margin-top:10px;">
<h:inputTextarea id="accordian1" value="#{email.tempAction}" cols="90" rows="3" />
</div>
<h6 style="font-weight:bold;">Due Date</h6>
<p:calendar value="#{email.tempDate}" id="popupCal" pattern="dd MMM, yyyy"/>
<p:commandButton actionListener="#{emailArticleBean.updateAction}" value="Add Action"
style="margin-left:5px;">
<f:setPropertyActionListener value="#{email}" target="#{emailArticleBean.selectedEmail}" />
</p:commandButton>
</p:tab>
</p:accordionPanel>
</p:column>
</p:dataTable>
</div>
</div>
<p:dialog id="emailActionDialog" header="Email Actions" widgetVar="dlg2" modal="true" height="100">
<h3>Email Actions</h3>
<p:dataList value="#{emailArticleBean.selectedEmail.actions}" var="action" itemType="disc">
#{action.action} --- #{action.username}
</p:dataList>
</p:dialog>
</h:form>
</html>
In my bean I have the following getter/setter
public EmailArticle getSelectedEmail() {
return selectedEmail;
}
public void setSelectedEmail(EmailArticle selectedEmail) {
this.selectedEmail = selectedEmail;
}
public void updateAction(ActionEvent ae) {
selectedEmail.getActions().add(new EmailActions(emailAction, "testUser", actionDueDate));
selectedEmail.merge();
}
The main problem here is the order of the invocation, first your actionListener is called then
f:setPropertyActionListener.
To solve this, change your actionListener to action, and update your action method to return a String.
Button
<p:commandButton action="#{emailArticleBean.updateAction}"
value="Add Action" style="margin-left:5px;">
<f:setPropertyActionListener value="#{email}"
target="# {emailArticleBean.selectedEmail}" />
</p:commandButton>
updateAction
public String updateAction() {
selectedEmail.getActions().add(new EmailActions(emailAction, "testUser", actionDueDate));
selectedEmail.merge();
return null;
}
OR
you can keep using your actionListener and pass the selectedEmail to it (without using f:setPropertyActionListener).
Button
<p:commandButton actionListener="#{emailArticleBean.updateAction(email)}"
value="Add Action" style="margin-left:5px;">
</p:commandButton>
updateAction
public void updateAction(EmailArticle selectedEmail) {
selectedEmail.getActions().add(new EmailActions(emailAction, "testUser", actionDueDate));
selectedEmail.merge();
}
To understand more the order of the invocation
See:
Differences between action and actionListener
I'm usign Mojarra 2.1.23 and Primefaces 3.5. I'm trying to make this code work, but for some reason I can't get the listener to be invoked.
<h:form id="menu" >
<p:growl id="messages" autoUpdate="true" showDetail="true" />
<p:panelMenu>
<p:submenu label="Ajax Menuitems">
<p:menuitem value="#{MenuController.test}"
actionListener="#{MenuController.save}" ajax="true"
update="messages" />
<p:menuitem value="Update" actionListener="#{MenuController.save}"
update="messages" />
</p:submenu>
</p:panelMenu>
</h:form>
MenuController is a session scoped bean managed by Spring 3 and even its properties are properly displayed on the same xhtml (button shows the text "Save").
The MenuController class is as follows:
public class MenuController() implements Serializable{
public static Logger log;
public String test="Save";
public MenuController() {
log = LoggerFactory.getLogger(this.getClass());
log.debug("Hello MenuController.");
}
public void save(ActionEvent event) {
addMessage("Data saved");
log.debug(" saving");
}
public void addMessage(String summary) {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
summary, null);
FacesContext.getCurrentInstance().addMessage(null, message);
}
//getters and setters...
}
I'm also using facelets, the following is Layout.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title><ui:insert name="title" /></title>
</h:head>
<h:body>
<div id="layout">
<table>
<tr>
<td>
<div id="menu">
<ui:include src="menu.xhtml"/>
</div>
</td>
<td>
<div id="content">
<ui:insert name="content">
</ui:insert>
</div>
</td>
</tr>
<tr>
<td>
<div id="footer">
<p>© Footer</p>
</div>
</td>
</tr>
</table>
</div>
When I click the menu entry, the method is not being called.
The problem was solved by changing the id on the form from "menu" to "menuForm", to not be confused by the one on the layout with id "menu"
<h:form id="menuForm" >
<p:growl id="messages" autoUpdate="true" showDetail="true" />
<p:panelMenu>
<p:submenu label="Ajax Menuitems">
<p:menuitem value="#{MenuController.test}"
actionListener="#{MenuController.save}" ajax="true"
update="messages" />
<p:menuitem value="Update" actionListener="#{MenuController.save}"
update="messages" />
</p:submenu>
</p:panelMenu>
</h:form>
I am using JSF 2.0 with PrimeFaces 3.0 M3. When I set dynamic="false" on <p:tabView>, then it works fine. But when I set it to true, then only the currently active tab works. Other tabs does not run. In the 1st tab I have a command link in a data table, this is also not working.
Below is my tabletabview.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
</h:head>
<h:body>
<f:view>
<h:form>
<p:growl id="growl" showDetail="true" />
<p:tabView cache="false" dynamic="true" activeIndex=0 >
<p:ajax event="tabChange" listener="ActivityController.onChange"/>
<p:tab title="Search Results 1">
<p:dataTable var="dataItem" value="#{ActivityController.dataList}">
<p:column>
<p:panel style="font-size:12px;width:600px">
<f:facet name="header">
<h:outputText value="#{dataItem.activityname}" />
</f:facet>
<div style="background-color: #DEB887;">
<h:outputText value="Location:" style="color:#FF0000;"></h:outputText>
<h:outputText value="#{dataItem.address}" />
<br></br>
</div>
<div style="background-color: #DEB887;">
<h:outputText value="Start Date:" style="color:#FF0000;"></h:outputText>
<h:outputText value="#{dataItem.startingdate}" />
<br></br>
</div>
<div style="background-color: #DEB887;">
<h:outputText value="Start Date:" style="color:#FF0000;"></h:outputText>
<h:outputText value="#{dataItem.endingdate}" />
</div>
<div style="background-color: #DEB887;">
<h:outputText value="Description:" style="color:#FF0000;"></h:outputText>
<h:outputText value="#{dataItem.description}" />
<br></br>
</div>
<p:commandLink action="#{ActivityController.editDataItem}">
<div style="display: none">
<h:outputText value="#{dataItem.activityname}" />
</div>
<h:outputText value="more....."></h:outputText>
<f:setPropertyActionListener target="#{ActivityController.dataItem}" value="#{dataItem}" />
</p:commandLink>
</p:panel>
</p:column>
</p:dataTable>
</p:tab>
<p:tab title="Search Results 2">
<p:panel style="width:600px;height:600px">
<p:schedule id="sche" value="#{searchController.eventModel}"
editable="true" draggable="false" resizable="false"
widgetVar="myschedule">
<p:ajax event="eventSelect"
listener="#{searchController.onEventSelect}" update="red"
process="#this" />
</p:schedule>
</p:panel>
</p:tab>
<p:tab id="gmap" title="Search Results 3">
<ui:include src="/locationpointers.xhtml"></ui:include>
</p:tab>
</p:tabView>
</h:form>
</f:view>
</h:body>
</html>
This is the relevant part of my ActivityController.java
public List<ActivityRegBean> getDataList() {
return dataList;
}
public void setDataList(List<ActivityRegBean> dataList){
this.dataList=dataList;
}
private ActivityRegBean dataItem;
private HtmlInputHidden dataItemId = new HtmlInputHidden() ;
public String editDataItem() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
System.out.println(dataItem.activityname);
dataItemId.setValue(dataItem.activityid);
System.out.println(dataItem.activityid);
retfromtable(dataItem.activityname);
return "edit"; // Navigation case.
}
public void onChange(TabChangeEvent event) {
System.out.println("tab id = " + event.getTab().getId());
}
The ActivityRegBean has a getter and setter.
How can I use dynamic="true" on the <p:tabView> without problems?
Can you try this instead of p:ajax
<p:tabView cache="false" dynamic="true" tabChangeListener="#{ActivityController.onChange}" onTabChangeUpdate="growl">
I have noticed that you are using xmlns:p="http://primefaces.prime.com.tr/ui" . It is for primefaces 2.2 and if you are indeed using primefaces 3, then it will complain about no taglibrary exists for that namespace. for PF3 you should be using xmlns:p="http://primefaces.org/ui" . may be you should clean your work directory.