I'm using the component rich:fileUpload for uploading files to my server the problem is that those files go along with a form that the user fills, so I wanna use one external button for doing this.
The user select the files to upload, fill the form and then click a "Submit" button at the bottom of the page. This upload the file with the form. I've tried it like this:
I'm able to hide the button inside the panel of fileUpload so the user don't click on it.
<rich:fileUpload id="fileUploadId"
style="width: 100%; height: 130px;"
fileUploadListener="#{documentsBean.listener}"
maxFilesQuantity="1"
uploadButtonClass="display-none"
uploadButtonClassDisabled="display-none">
</rich:fileUpload>
And what I've tried with the button is
<a4j: commandButton id="uploadFormButton"
value="Attach"
onclick="#{rich:component('fileUploadId')}.submitForm();"
oncomplete="#{rich:component('fileUploadId')}.clear(); return false;"/>
But it doesn't work.
I don't know if there is a way to do exactly what you want, but here is another solution you can use :
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:st="http://spectotechnologies.com/jsf"
xmlns:t="http://myfaces.apache.org/tomahawk">
...
<h:form enctype="multipart/form-data">
... your fields ...
<t:inputFileUpload value="#{bean.document}" />
<h:commandButton value="Submit" actionListener="#{bean.onButtonSubmitClick}" />
</h:form>
</html>
and the bean :
#ManagedBean
#RequestScoped
public class Bean
{
private UploadedFile m_oDocument;
public void setDocument(UploadedFile p_oDocument)
{
m_oDocument = p_oDocument;
}
#UploadedFileNotEmpty
#UploadedFileSize(max="10000000")
#UploadedFileExtension(accept="doc,docx,pdf,txt,rtf,xls,xlsx,zip,rar,jpg,jpeg,jpe,bmp,gif,png,csv,ppt,pptx,odp,pic,odt,ods")
public UploadedFile getDocument()
{
return m_oDocument;
}
public void onButtonSubmitClick(ActionEvent p_oEvent)
{
...
}
}
Hope this helps!
Related
edit: Based on Jasper's comment, the selection feature requires p:dataTable to be in a form, so my question is moot.
I have a DataTable outside of a form. When I submit the form (non-ajax), the field referenced by the selection attribute is set to null in my view. This happens for PrimeFaces 10.0.1 and higher. In 10.0.0 and 8.x, the field is not touched.
The field in the example is DtView.selectedEntry.
xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>PrimeFaces Test</title>
</h:head>
<h:body>
<p:dataTable id="data-table" var="entry"
value="#{dtView.entries}"
rowKey="#{entry.id}"
selection="#{dtView.selectedEntry}"
selectionMode="single">
<p:column headerText="Entry">
<h:outputText value="#{entry}" />
</p:column>
</p:dataTable>
<h:form id="frmTest">
<div>
<p:outputLabel for="#next" value="Selected: "/>
<h:outputText id="selected-entry" value="#{dtView.selectedEntry}" />
</div>
<div>
<p:commandButton value="save input"
ajax="false"
imediate="true"
update="#form :data-table"
action="#{dtView.submit()}" />
</div>
</h:form>
</h:body>
</html>
View:
#Data
#Named
#ViewScoped
public class DtView implements Serializable {
private List<Product> entries;
private Product selectedEntry;
#PostConstruct
void setup() {
entries = List.of(
new Product(1, "entry 1"),
new Product(2, "entry 2"),
new Product(3, "entry 3")
);
selectedEntry = entries.get(0);
}
public String submit() {
System.out.println("Selected entry: " + selectedEntry);
return null;
}
}
Console (PrimeFaces 11.0.0 and then 10.0.0):
Selected entry: null
Selected entry: Product(id=1, name=entry 1)
To avoid the 'null' I can put p:dataTable inside a form, so it won't get processed during the apply request value phase or use ajax on the command button. I am not sure why the dataTable is outside a form in my real application to begin with.
I expected a value outside of a form not to be set in the view, but dataTable does not seem to follow this. Is the new PF behaviour more logical and my understanding is wrong?
The reason for this change seems to be located in SelectionFeature.
PF 8: just calls table.setSelection(null);:
https://github.com/primefaces/primefaces/blob/cd4fbdf1d9d4ae054da19b9a84001d0c34d142eb/src/main/java/org/primefaces/component/datatable/feature/SelectionFeature.java#L78
PF 10.0.0: decodeSingleSelection() does not call setSelection() because !rowKeys.isEmpty() evaluates to false (empty check disappears in 10.0.1):
https://github.com/primefaces/primefaces/blob/10.0.0/src/main/java/org/primefaces/component/datatable/feature/SelectionFeature.java#L84
11.0.0: decodeSingleSelection() eventually calls setSelection() to set the value in the view to null:
https://github.com/primefaces/primefaces/blob/11.0.0/primefaces/src/main/java/org/primefaces/component/datatable/feature/SelectionFeature.java#L87
I am having trouble displaying image from database on a primefaces graphicimage component. I am using primefaces 3.4.2, jsf 2.2, glassfish 3.1.2.2. Following is the simple code I am trying. I went through other posts related to p:graphicimage and incorporated the recommendations, still I gouldnt make this work. What is wrong here?
index.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form id="f1">
<p:panel style="height: 500px ; width: 800px" visible="true">
<p:graphicImage value="#{treeBean.image}" />
</p:panel>
</h:form>
</h:body>
</html>
TreeBean.java
#Named
#ApplicationScoped
public class TreeBean implements Serializable{
#EJB
private ImageEJB imageEjb;
public StreamedContent getImage() throws IOException{
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
return new DefaultStreamedContent();
}
else {
Decisiontree dr = imageEjb.getTree();
return new DefaultStreamedContent(new ByteArrayInputStream(dr.getImage()));
}
}
}
This is what I see in the browser console.
Add a MIME type in web.xml like below:-
<mime-mapping>
<extension>xhtml</extension>
<mime-type>image/svg+xml</mime-type>
</mime-mapping>
Change your return statement in your bean as below:-
return new DefaultStreamedContent(new ByteArrayInputStream(dr.getImage()),"image/svg+xml");
I have commandButton component on my JSF page:
<p:commandButton id="period"
value="#{myBean.isMonthly == false ? 'Yearly' : 'Monthly'}"
action="#{myBean.doSomeOtherStuff()}"
update="period myDataTable">
</p:commandButton>
I'm trying to update a dataTable upon a click on the button above.
When I click it, the dataTable is updated as desired whereas the commandButton behaves weirdly, resulting in a display like:
Can someone help me understand the causes of such a weird situation and also tell a solution if possible?
NOTES:
JSF implementation and version: Mojarra (javax.faces-2.1.11.jar)
View technology: Facelets (XHTML)
Copy'n'paste'n'runnable example! (SSCCE) listed below:
FilterBean.java:
package com.turkcell.mdealer.bean.impl;
import org.springframework.stereotype.Component;
#Component
public class FilterBean {
private boolean monthly = true;
public String applyPeriod(String caller) {
monthly = !monthly;
return caller;
}
public boolean isMonthly() {
return monthly;
}
public void setMonthly(boolean monthly) {
this.monthly = monthly;
}
}
sample.xhtml:
<f:view xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:turkcell="http://turkcell.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui" xmlns:o="http://omnifaces.org/ui"
xmlns:of="http://omnifaces.org/functions"
xmlns:pm="http://primefaces.org/mobile" contentType="text/html"
renderKitId="PRIMEFACES_MOBILE">
<pm:page title="Bayi Raporlari">
<pm:view id="FaturasizAktivasyon" swatch="c">
<p:outputPanel id="FaturasizPanel">
<h:form id="FaturasizForm">
<pm:content>
<p:commandButton id="period"
value="#{filterBean.monthly == false ? 'Yearly' : 'Monthly'}"
action="#{filterBean.applyPeriod('sample')}" update="period">
</p:commandButton>
</pm:content>
</h:form>
</p:outputPanel>
</pm:view>
</pm:page>
</f:view>
General view of libraries:
I don't know the reason of the weird behaviour
However, you can use two conditionally rendered button to achieve the same effect:
<p:panelGroup>
<p:commandButton value="Monthly"
action="#{myBean.doSomeOtherStuff()}"
update="myDataTable #parent" rendered="#{myBean.isMonthly}" />
<p:commandButton value="Yearly"
action="#{myBean.doSomeOtherStuff()}"
update="myDataTable #parent" rendered="#{not myBean.isMonthly}" />
</p:panelGroup>
I have a very simple xhtml file where a panelGroup containing a commandButton is added to the page on clicking toggle button but this dynamically added commandButton fails to execute its actionlistener on being clicked.
Complete code below:
<?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:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:panelGroup id="checkDyna">
<h:panelGroup rendered="#{listRetriever.booleanStatus}" >
<h:form>
<p:commandButton value="check" process="#all" actionListener="#{listRetriever.xx()}"/>
</h:form>
</h:panelGroup>
</h:panelGroup>
<h:form>
<p:commandButton value="Toggle" actionListener="#{listRetriever.toggleBooleanStatus()}" update=":checkDyna"/>
</h:form>
</h:body>
</html>
Bean
#ManagedBean(name = "listRetriever")
#RequestScoped
public class ListRetriever implements Serializable {
private boolean booleanStatus;
public void toggleBooleanStatus(){
if (!booleanStatus)
booleanStatus=true;
}
public void xx(){
System.out.println("Invoked***");
}
public boolean isBooleanStatus() {
return booleanStatus;
}
public void setBooleanStatus(boolean booleanStatus) {
this.booleanStatus = booleanStatus;
}
}
On removing rendered="#{listRetriever.booleanStatus}" actionlistener is successfully invoked.
On making the bean ViewScoped too the problem is eliminated but I dont want to make it wider than RequestScoped.
I had this p:commandButton within a conditionally rendered panel whose conditional expression for rendering was evaluating to false while I was trying to execute the actionlistener. This was the cause of actionlistener not getting executed.
I want to create JSF page with tabs. Something like this. But I wonder if I choose to do this with Jquery can I implement lazy loading - when I click a tab on the JSF page the content is generated when the tab is opened. Is it possible to implement lazy loading of tabs in pure JSF? And I suppose that I can easily implement AJAX in both cases.
Best wishes
The Primefaces Tabview component supports lazy loading.
Quote from the showcase:
Tab contents can be lazy loaded with ajax as well, when dynamic
attribute is set to "true" only the active tab's content will be
rendered and clicking on a lazy tab will fetch the tab contents with
ajax. This behavior is handy to save bandwith and reduce page size
when dealing with tabs having a lot of content.
Quick example from the showcase:
<h:form id="form">
<p:tabView id="tabView" dynamic="true" cache="true">
// tabs
</p:tabView>
</h:form>
The cache attribute is used to prevent ajax reloading of tab content if you toggle between tabs.
Note: If you want your tabs beans be Session Scope then read instructions in the buttom of the Answer...
Since you are don't want to use any third party Libarary here is a PureJSF + jQuery example
JSF + Jquery + Ajax Lazy Loading + View Scope Beans Example...
B.T.W here is how it looks like eventually :
You can look at the web server console for the print outs of #PostConstruct and the #PreDestroy when you click on each tab...
The content of the tab - the xhtml page and its bean will be loaded upon tab click (Lazy Loading) and will be destroyed upon click on other tab,
I suggest you to create a new project and slowly place all the files inside it and start playing and looking into it... its 100% working , but I placed some print outs just to see that it is really working...
The Example is very simple and straight forward....
First Of all go to jQueryUI and download it(1.8.18)
and place jquery-1.7.1_.min.js and jquery-ui-1.8.18.custom.min.js in WebContent\resources\js and jquery-ui-1.8.18.custom.css in WebContent\resources\css
Now to the other files...
myTabs.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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
<h:outputScript library="js" name="jquery-1.7.1_.min.js" target="head" />
<h:outputScript library="js" name="jquery-ui-1.8.18.custom.min.js" target="head" />
<h:outputStylesheet library="css" name="jquery-ui-1.8.18.custom.css" target="head" />
<h:outputScript library="js" name="mytabs.js" target="head" />
</h:head>
<h:body>
<f:view>
<h:form prependId="false">
<h:panelGroup id="tabs" layout="block">
<ul>
<c:forEach items="#{myTabs.tabs}" var="tab">
<li>#{tab.tabid}</li>
<h:commandButton id="button_#{tab.tabid}" value="TabClick" action="#{myTabs.switchPages(tab.tabid)}" style="display:none">
<f:ajax render="tabs"></f:ajax>
</h:commandButton>
</c:forEach>
</ul>
<c:forEach items="#{myTabs.tabs}" var="tab">
<h:panelGroup id="#{tab.tabid}" layout="block" rendered="#{tab.tabid eq myTabs.selectedTab}">
<ui:include src="#{tab.tabfilename}"></ui:include>
</h:panelGroup>
</c:forEach>
</h:panelGroup>
</h:form>
</f:view>
</h:body>
</html>
MyTabs.java
package pack;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class MyTabs{
#PostConstruct
public void init(){
tabs = new ArrayList<MyTabObject>();
tabs.add(new MyTabObject("tab1.xhtml", "tab1"));
tabs.add(new MyTabObject("tab2.xhtml", "tab2"));
tabs.add(new MyTabObject("tab3.xhtml", "tab3"));
}
String selectedTab="tab1";
public String getSelectedTab() {
return selectedTab;
}
public void setSelectedTab(String selectedTab) {
this.selectedTab = selectedTab;
}
public String switchPages(String selTab) {
selectedTab = selTab;
return "myTabs.xhtml";
}
List<MyTabObject> tabs;
public List<MyTabObject> getTabs() {
return tabs;
}
public void setTabs(List<MyTabObject> tabs) {
this.tabs = tabs;
}
}
MyTabObject
package pack;
public class MyTabObject{
String tabfilename;
String tabid;
public String getTabfilename() {
return tabfilename;
}
public void setTabfilename(String tabfilename) {
this.tabfilename = tabfilename;
}
public String getTabid() {
return tabid;
}
public void setTabid(String tabid) {
this.tabid = tabid;
}
public MyTabObject(String tabfilename, String tabid) {
super();
this.tabfilename = tabfilename;
this.tabid = tabid;
}
}
Tab1Page , (Tab2Page and Tab3Page are exactly the same , just change the number in all places)
package pack;
import java.io.Serializable;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class Tab1Page implements Serializable{
/**
*
*/
private static final long serialVersionUID = 254415216070877770L;
// Constants
public final static String hashKey = "tab1PageTab";
public String actionString = "";
#PostConstruct
public void post(){
Format formatter;
Date date = new Date();
// Time formate 01:12:53 AM
formatter = new SimpleDateFormat("hh:mm:ss a");
tabName = formatter.format(date);
System.out.println("Tab1Page\t"+tabName+"\t#PostConstruct...");
}
#PreDestroy
public void destroy(){
Format formatter;
Date date = new Date();
// Time formate 01:12:53 AM
formatter = new SimpleDateFormat("hh:mm:ss a");
tabName = formatter.format(date);
System.out.println("Tab1Page\t"+tabName+"\t#PreDestroy...");
}
String tabName;
public String getTabName() {
return this.getClass().getName().substring(this.getClass().getName().lastIndexOf("."))+"\t"+tabName;
}
public void setTabName(String tabName) {
this.tabName = tabName;
}
public String getActionString() {
return actionString;
}
public void setActionString(String actionString) {
this.actionString = actionString;
}
}
tab1.xhtml (tab2.xhtml and tab3.xhtml are exactly the same - just replace the numbers)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:panelGroup>
<h:form>
<h:outputText value="#{tab1Page.tabName}" />
</h:form>
</h:panelGroup>
</ui:composition>
and to the last file
mytabs.js (place it in WebContent\resources\js)
$(document).ready(function () {
$("#tabs").tabs();
});
$(window).load(function() {
jsf.ajax.addOnEvent(function (data) {
if (data.status === "success") {
$("#tabs").tabs();
}
});
});
In order to use Session Scope Beans:
The method switchPages in MyTabs.java should be void and not to return anything, like this
public void switchPages(String selTab) {
selectedTab = selTab;
}
It's not a problem at all implement an ajax tab with jQuery UI.
See the documentation of jQuery Tabs with ajax here and click on "view source" to find the code you need.
You can look at the book Core Java Server Faces third edition page 339 to see how you can implement simple tabs with h:panelGrid.
The output is something like this:
This is the code example from the book:
...
<h:form>
<h:panelGrid styleClass="tabbedPane" columnClasses="displayPanel">
<!-- Tabs -->
<f:facet name="header">
<h:panelGrid columns="4" styleClass="tabbedPaneHeader">
<h:commandLink tabindex="1"
title="#{msgs.jeffersonTooltip}"
styleClass="#{tp.jeffersonStyle}"
actionListener="#{tp.jeffersonAction}">
#{msgs.jeffersonTab}
</h:commandLink>
...
</h:panelGrid>
</f:facet>
<!-- Tabbed pane content -->
<ui:include src="washington.xhtml" />
<ui:include src="roosevelt.xhtml" />
<ui:include src="lincoln.xhtml" />
<ui:include src="jefferson.xhtml" />
</h:panelGrid>
</h:form>
...
This is the description:
The tabbed pane is implemented with h:panelGrid. Because we do not specify
the columns attribute, the panel has one column. The panel’s header—defined
with an f:facet tag—contains the tabs, which are implemented with another
h:panelGrid that contains h:commandLink tags for each tab. The only row in the panel
contains the content associated with the selected tab.
When a user selects a tab, the associated action listener for the command link is
invoked and modifies the data stored in the backing bean. Because we use a
different CSS style for the selected tab, the styleClass attribute of each h:commandLink
tag is pulled from the backing bean with a value reference expression.
As you can see from the top picture in Figure 8–11, we have used the title
attribute to associate a tooltip with each tab. Another accessibility feature is the
ability to move from one tab to another with the keyboard instead of the
mouse. We implemented that feature by specifying the tabindex attribute for
each h:commandLink.
The content associated with each tab is statically included with the JSP include
directive. For our application, that content is a picture and some text, but
you could modify the included JSF pages to contain any set of appropriate
components. Notice that even though all the JSF pages representing content are
included, only the content associated with the current tab is rendered. That is
achieved with the rendered attribute—for example, jefferson.xhtml looks like this:
Putting It All Together
<h:panelGrid columns="2" columnClasses="presidentDiscussionColumn"
rendered="#{tp.jeffersonCurrent}">
<h:graphicImage value="/images/jefferson.jpg"/>
<span class="tabbedPaneContent">"#{msgs.jeffersonDiscussion}"</span>
</h:panelGrid>
Figure 8–12 shows the directory structure for the tabbed pane application and
Listings 8–14 through 8–17 show the most important files.
Unfortunately I don't know how to add lazy loading and AJAX support to this code.