.Cannot export chart as image in Primefaces? - jsf-2

I cannot export prime-faces chart as Image.
categoryModel is same as Prime-show Case.
Is it need dependency lib to export?
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
......
template="/common/commonLayout.xhtml">
<ui:define name="content">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript">
//<![CDATA[
function exportChart() {
//export image
$('#output').empty().append(chart.exportAsImage());
//show the dialog
dlg.show();
}
//]]>
</script>
<h:form enctype="multipart/form-data">
<p:barChart id="basic" value="#{ChartActionBean.categoryModel}" legendPosition="ne"
title="Bar Chart" widgetVar="chart" animate="true" yaxisLabel="Number of Count"/>
<p:commandButton type="button" value="Export" icon="ui-icon-extlink" onclick="exportChart()"/>
<p:dialog widgetVar="dlg" showEffect="fade" modal="true" header="Chart as an Image">
<p:outputPanel id="output" layout="block" style="width:500px;height:300px"/>
</p:dialog>
</h:form>
</ui:define>
</ui:composition>

In Showcase and Export button and OutputPanel are not wrapped in so $('#output') is able to pick the expected element to append the image.
But in your case you have wrapped these components in so JSF will generate an id for form like j_idt10 and the component's id "output" will become "j_idt10:output".
To fix this:
<h:form id="form1">
//chart
// export button
//dialog containing outputPanel
</h:form>
And in javascript:
function exportChart() {
$('#form1\\:output').empty().append(chart.exportAsImage());
dlg.show();
}
or simply put outside the and $('#output').empty().append(chart.exportAsImage()); will work as expected.

I also think that to specify a model you use a model attribute and not value. So in your case it would be:
<p:barChart id="basic" model="#{ChartActionBean.categoryModel}" legendPosition="ne" title="Bar Chart" widgetVar="chart" animate="true" yaxisLabel="Number of Count"/>

Related

Primefaces upade ui:include not working

I'm using Primefaces 5.1.When I press button dynamically include page but it not working.I try below code:
page.xhtml
<f:subview id="userView">
<h:form id="userId">
<p:commandButton id="userButton" value="Import"
action="user.pageAction" update=":userView:dynamicPanel"/>
</h:form>
<p:panel id="dynamicPanel">
<ui:include src="${BranchDetails.PagePath}" />
</p:panel>
</f:subview>
pageClass.java
public void pageAction()
{
pagePath="/pages/userMangement/userDetail.xhtml"
}
I try update facescontext and request context also but it not include page
FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add(":dynamicPanel"); and
RequestContext.getCurrentInstance().update(":dynamicPanel")
I try replace (:dyanamicPanel to dynamicPanel) update but that also not working.
You use action the wrong
<f:subview id="userView">
<h:form id="userId">
<p:commandButton id="userButton" value="Import"
action="user.pageAction" update=":userView:dynamicPanel"/>
</h:form>
<p:panel id="dynamicPanel">
<ui:include src="${BranchDetails.PagePath}" />
</p:panel>
</f:subview>
correct
<f:subview id="userView">
<h:form id="userId">
<p:commandButton id="userButton" value="Import"
action="#{user.pageAction}" update=":dynamicPanel"/>
</h:form>
<p:panel id="dynamicPanel">
<ui:include src="${BranchDetails.PagePath}" />
</p:panel>
</f:subview>

How to pass method expression to the Facelets tagfile

I created a tagfile for a confirm dialog with a command button:
<?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:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:aym="http://aym.com/facelets"
xmlns:rich="http://richfaces.org/rich"
>
<h:body>
<ui:composition>
<p:growl id="messages" />
<h:panelGrid columns="1" cellpadding="5">
<p:commandButton value="#{label}" onclick="#{pupupId}.show()" type="button" ajax="false"/>
</h:panelGrid>
<p:confirmDialog message="#{message}"
showEffect="bounce" hideEffect="explode"
header="İşlem Onay" severity="alert" widgetVar="#{pupupId}">
<p:commandButton value="Evet" update="messages" oncomplete="#{pupupId}.hide()" ajax="false"
action="#{actionMethod}" />
<p:commandButton value="Hayır" onclick="#{pupupId}.hide()" type="button" />
</p:confirmDialog>
</ui:composition>
</h:body>
</html>
Here's how I'm using it:
<aym:onayButon id="onay2" label="#{lbl.kaydet}"
actionMethod="#{userMB.addUser}" pupupId="onaylaPopup"
message="#{msg.onay_sonuc}" />
I am passing the action method that I am going to call when I click the button. However, when I do that, then I am getting a PropertyNotFoundException:
WARNING: #{actionMethod}: javax.el.PropertyNotFoundException: /WEB-INF/tags/com/components/onayButton.xhtml #29,33 action="#{actionMethod}": /pages/index.xhtml #33,48 actionMethod="#{userMB.addUser}": Property 'addUser' not found on type com.otv.managed.bean.UserManagedBean
javax.faces.FacesException: #{actionMethod}: javax.el.PropertyNotFoundException: /WEB-INF/tags/com/components/onayButton.xhtml #29,33 action="#{actionMethod}": /pages/index.xhtml #33,48 actionMethod="#{userMB.addUser}": Property 'addUser' not found on type com.otv.managed.bean.UserManagedBean
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
It works fine when I hardcode the action method in the tagfile like so:
<p:commandButton ... action="#{userMB.addUser}" />
How is this caused and how can I solve it?
Try as a workaround to give action bean and action method as two separate parameters:
Template
<p:commandButton value="Evet"
update="messages" oncomplete="#{pupupId}.hide()" ajax="false"
action="#{actionBean[actionMethod]}" />
call
<aym:onayButon id="onay2" label="#{lbl.kaydet}"
actionBean="#{userMB}" actionMethod="addUser" pupupId="onaylaPopup"
message="#{msg.onay_sonuc}" />
On the call, the bean needs to be in curly brackets, the method name is only given as string. See also Solution on a similar topic .
Maybe it helps...

Unable to use p:overlaypanel inside composite component

Am trying to create a composite component that will display the values as overlaypanel. But it returns the below error;
Cannot find component 'j_idt58:reviewDataTable:0:overrideCol' in view
overrideVersionDetails.xhtml:(composite component)
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<cc:interface>
<cc:attribute name="forId" type="java.lang.String" required="true" />
<cc:attribute name="forValue" type="java.lang.Object" />
</cc:interface>
<cc:implementation>
<p:overlayPanel for="#{cc.attrs.forId}" my="left bottom">
#{cc.attrs.forValue}
</p:overlayPanel>
</cc:implementation>
</ui:composition>
Its used in another page:
<h:form>
....
...
<p:dataTable .....>
....
<p:column sortBy="#{dto.isSameCycleOverride}" width="100">
<f:facet name="header">
Override
</f:facet>
<h:commandLink id="overrideCol" binding="#{overrideCol}"
value="#{(dto.isSameCycleOverride) ? 'Yes' : 'No'}" />
<comp:overrideVersionDetails forId="#{overrideCol.clientId}"
forValue="#{dto.message}" />
</p:column>
....
</p:dataTable>
</h:form>
Any help is really appreciated.
I don't work with Primefaces, but with RichFaces I would use :
<comp:overrideVersionDetails forId="#{rich:clientId('overrideCol')}"
forValue="#{dto.message}" />
to do what you want.
With a little Help from SO :
Rich Faces rich:clientId in Primefaces?
it seems you can do this :
...
<h:commandLink id="overrideCol" value="#{(dto.isSameCycleOverride) ? 'Yes' : 'No'}" />
<comp:overrideVersionDetails forId="#{p:component('overrideCol')}"
forValue="#{dto.message}" />
...
Now to see if this works better than the use of binding in a dataTable...

h:command button is showing blank page when managed bean scope is requst or view

I am trying to submit a form, when I am keeping managed bean scope as view or request the action method is not getting invoked and it is showing me blank page. Where as when I am keeping the managed bean's scope as "session" action method is getting invoked and can see the desired result.
I am using jsf 2.1, primefaces 3.5, EL 2.2, tomcat 7
Below is my xhtml code:
<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:p="http://primefaces.org/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core"
template="globalTemplate.xhtml">
<h:messages />
<ui:define name="title">UserForm</ui:define>
<ui:define name="content">
<h:form id="userForm">
<ui:repeat value="#{loginBean.userMap.keySet().toArray()}" var="entry">
<h:inputText id="usrId#{entry.key}" value="#{loginBean.userMap.get(entry)}" />
<ui:repeat value="#{loginBean.userMap.get(entry)}" var="item" varStatus="loop">
<h:outputText id="msgDesc" value="#{item.userDesc}" />
<br/>
</ui:repeat>
<p:inputTextarea rows="6" cols="33" id="replyId#{entry.key}" value="#{loginBean.userInput}"
onkeypress="if (event.keyCode == 13) {submitUsr(); return false; }"/>
<p:commandButton id="submitInput#{entry.key}" value="Click" action="#{loginBean.submitUser}" />
</ui:repeat>
</h:form>
</ui:define>
I am not getting what is not allowing me to call the action method when I am submitting the page keeping managed bean's scope as view/request.
Thanks for your help in advance.

JSF 2 facelets <f:metadata/> in template and page

I have the following template (masterLayout.xhtml):
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<f:view contentType="text/html">
<ui:insert name="metadata"/>
<h:head>
<title><ui:insert name="windowTitle"/> | MySite</title>
</h:head>
<h:body>
<div id="container">
<div id="header">
<ui:insert name="header">
<ui:include src="/WEB-INF/templates/header.xhtml"/>
</ui:insert>
</div>
<div id="content">
<ui:insert name="content"/>
</div>
<div id="footer">
<ui:insert name="footer">
<ui:include src="/WEB-INF/templates/footer.xhtml"/>
</ui:insert>
</div>
</div>
</h:body>
</f:view>
</html>
and page that uses it (search.xhtml):
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title></title>
</h:head>
<h:body>
<ui:composition template="/WEB-INF/templates/masterLayout.xhtml">
<ui:define name="metadata">
<f:metadata>
<f:viewParam name="address" value="#{searchBean.address}"/>
<f:event type="preRenderView" listener="#{userSessionBean.preRenderViewCookieLogin(e)}"/>
<f:event type="preRenderView" listener="#{searchBean.preRenderView(e)}"/>
</f:metadata>
</ui:define>
<ui:define name="windowTitle">#{searchBean.address}</ui:define>
<ui:define name="content">
<!-- Content goes here -->
</ui:define>
</ui:composition>
</h:body>
</html>
The problem is that I want to place the call to userSessionBean.preRenderViewCookieLogin(e) in the template because there are many other pages. This method checks that the user is logged in (according to session state) and, if not, checks that a cookie is available which can be used to log the user in and, if so (and if valid), logs the user in automatically. The system works in the code above, but when I try to push this into the template, my view parameters are no longer being set.
Here's the modified version of the above, with userSessionBean.preRenderViewCookieLogin(e) pushed up to the template.
masterLayout.xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<f:view contentType="text/html">
<f:metadata>
<f:event type="preRenderView" listener="#{userSessionBean.preRenderViewCookieLogin(e)}"/>
<ui:insert name="metadata"/>
</f:metadata>
<h:head>
<title><ui:insert name="windowTitle"/> | MySite</title>
</h:head>
<h:body>
<div id="container">
<div id="header">
<ui:insert name="header">
<ui:include src="/WEB-INF/templates/header.xhtml"/>
</ui:insert>
</div>
<div id="content">
<ui:insert name="content"/>
</div>
<div id="footer">
<ui:insert name="footer">
<ui:include src="/WEB-INF/templates/footer.xhtml"/>
</ui:insert>
</div>
</div>
</h:body>
</f:view>
</html>
search.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title></title>
</h:head>
<h:body>
<ui:composition template="/WEB-INF/templates/masterLayout.xhtml">
<ui:define name="metadata">
<f:viewParam name="address" value="#{searchBean.address}"/>
<f:event type="preRenderView" listener="#{searchBean.preRenderView(e)}"/>
</ui:define>
<ui:define name="windowTitle">#{searchBean.address}</ui:define>
<ui:define name="content">
<!-- Content goes here -->
</ui:define>
</ui:composition>
</h:body>
</html>
Notice that I've moved the <f:metadata/> tag to the template. That alone is the problem as removing userSessionBean.preRenderViewCookieLogin(e) makes no difference. I also tried a variation on the code that worked, which was to just move userSessionBean.preRenderViewCookieLogin(e) into the template which means it can't be inside the <f:metadata/> tag. In this case, that method executed after all the view parameters had been set and searchBean.preRenderView(e) called. I want userSessionBean.preRenderViewCookieLogin(e) to be called before any page's preRenderView(e) is called, not after. And just for fun I tried putting an <f:metadata/> around userSessionBean.preRenderViewCookieLogin(e), which called this method, but didn't set the view parameters.
So, I would like to know:
Why is this happening and is there a way to fix it?
Is there a better way to ensure the same method is called for each page before anything else?
Edit:
I just tried something else - a phase event:
<f:view contentType="text/html" beforePhase="#{userSessionBean.beforePhase(e)}">
This is in masterLayout.xhtml. It is not being called at all; not for any phase.
Edit:
Removed the e (damn you NetBeans!):
<f:view contentType="text/html" beforePhase="#{userSessionBean.beforePhase}">
This is only called before the render response phase, which of course means it's called after the preRenderView event is raised.
Why is this happening and is there a way to fix it?
From the <f:metadata> tag documentation (emphasis of 2nd paragraph is mine):
Declare the metadata facet for this view. This must be a child of the <f:view>. This tag must reside within the top level XHTML file for the given viewId, or in a template client, but not in a template. The implementation must insure that the direct child of the facet is a UIPanel, even if there is only one child of the facet. The implementation must set the id of the UIPanel to be the value of the UIViewRoot.METADATA_FACET_NAME symbolic constant.
So, it really has to go in the top view, not in the template.
Is there a better way to ensure the same method is called for each page before anything else?
In your particular case, store the logged-in user as a property of a session scoped managed bean instead of a cookie and use a filter on the appropriate URL pattern to check it. Session scoped managed beans are in the filter available as HttpSession attributes. Homegrown cookies are unnecessary as you're basically reinventing the HttpSession here. Unless when you want a "remember me" facility, but this should not be solved this way. Do it in a filter as well.
See also:
Prevent accessing restricted page without login in Jsf2
I got this working using a PhaseListener instead.
public class CookieLoginPhaseListener implements PhaseListener
{
#Override
public void beforePhase(PhaseEvent event)
{
}
#Override
public void afterPhase(PhaseEvent event)
{
UserSessionBean userSessionBean = Util.lookupCdiBean("userSessionBean");
userSessionBean.handleAuthCookie();
}
#Override
public PhaseId getPhaseId()
{
return PhaseId.RESTORE_VIEW;
}
}
and the little bit of bean lookup magic is here:
public static <T> T lookupCdiBean(String name)
{
return (T) FacesContext.getCurrentInstance().getApplication().evaluateExpressionGet(FacesContext.getCurrentInstance(), "#{" + name + "}", Object.class);
}
Thanks to #BalusC for this: JSF - get managed bean by name. Since I'm using CDI, I can't use the more declarative #ManagedProperty option. Not a big deal though.

Resources