How to set theme by Java code in Primefaces 3? - jsf-2

I have for example theme test. How to set this theme using Java code in Primefaces ? I don't want to use context param primefaces.THEME and i don't want to use <p:themeSwitcher>.

One more way to do this: include stylesheet to your pages template:
<h:body>
<h:outputStylesheet library="primefaces-#{themesBean.theme}" name="theme.css" />
</h:body>
Where #{themesBean.theme} variable reffers to name of your theme.
P.S. tested in PF5
Same answer on similar question https://stackoverflow.com/a/24092773/2993327

This is what you need to do (untested, but should give you an indication how it should work)
Disable standard theme support (in web.xml):
Code:
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>none</param-value>
</context-param>
Make a managed bean (CDI or std JSF) that holds the value for the theme.
Code:
#Named #SessionScoped
public class LayoutBean
{
...
private String theme = "test";
...
public String getTheme()
{
return theme;
}
...
}
Add following tag in the head of all your pages (template)
Code:
<link rel="stylesheet" href="#{request.contextPath}/themes/{layoutBean.theme}/skin.css" />
You can find this solution on the following URL how to set a PrimeFaces theme?

Related

Get file url in JSF 2.2

I am trying to make an openfiledialog in the backing bean, so that I can get the url of the local file. However it seems that the standard JSF library does not support open/save file dialog. Is there another way of getting an url of a file with something similar to openfiledialog?
Here is what has to happen:
Click on a button --> send action to the backing bean --> show openfiledialog --> get url of the file --> add url of the file to a list of strings.
I am not sure how to accomplish the bold steps above. Is there someone who can give me any leads or help to accomplish this?
(I am using JSF & Primefaces, I would prefer not to use another external library if possible.)
Since you're using JSF 2.2 as well as Primefaces, why not use the primefaces component itself?
Below is the Primefaces 5.0 showcase example for a basic file upload:
<h:form enctype="multipart/form-data">
<p:growl id="messages" showDetail="true" />
<p:fileUpload value="#{fileUploadView.file}" mode="simple" skinSimple="true"/>
<p:commandButton value="Submit" ajax="false" actionListener="#{fileUploadView.upload}" disabled="true" />
</h:form>
Managed Bean
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.UploadedFile;
#ManagedBean
public class FileUploadView {
private UploadedFile file;
public UploadedFile getFile() {
return file;
}
public void setFile(UploadedFile file) {
this.file = file;
}
public void upload() {
if(file != null) {
FacesMessage message = new FacesMessage("Succesful", file.getFileName() + " is uploaded.");
FacesContext.getCurrentInstance().addMessage(null, message);
}
}
}
The enctype attribute for the form is required. Also, for using Primefaces file upload, you need to setup certain context parameters and filters. You may refer the appropriate documentation for the same.
You can get url for file uploaded to path or database, not sure if you make a search in google but I found these URLs maybe will help you:
http://balusc.blogspot.com/2007/07/fileservlet.html
Download a file with JSF?
You just need to open a dialog have link of file, or maybe file url can be stored in variable to add to list too or what ever you want.
Hope this will help you.

Why is JSF 2 managed bean not available in result page?

I have a very simple app. One bean annotated with #Named #SessionScoped and 2 web pages. home.xhtml and list.xhtml. When I set searchForm.hostanme on the first page, and access it again on the 2nd page. I can see from sysout statements that hostname is getting set, but there is a space where that value should be on the list.xhtml page. It's disappearing between home and list. Why?
home.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head></h:head>
<h:form>
<h:outputText value="Hi Mama" />
<h:inputText value="#{searchForm.hostname}" />
<h:commandButton action="list?faces-redirect=true" value="Devices" />
<h:commandButton action="#{searchForm.reset}" value="Reset" immediate="true" type="reset" />
</h:form>
</html>
list.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:outputText value="Device is #{searchForm.hostname}" />
</html>
SearchForm.java
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
#Named
#RequestScoped
public class SearchForm {
String hostname;
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
System.out.println("hostname is "+ hostname);
this.hostname = hostname;
}
public String reset(){
System.out.println("RESETTING");
System.out.println("hostname is "+ hostname);
return "/index.xhtml";
}
}
I'm thinking it might be a scoping issue, but I've tried several scopes and still searchForm.hostname is not avaible by the time I navigate to the list.xhtml page.
I've been reading and reading and reading up on JSF2, but I still can't resolve I hope is a simple problem.
I have a beans.xml file is in WEB-INF.
I come from a seam 2 background so decided I was comfortable with ConversationScoped in this context. It worked like a charm.
Some more thoughts that might help a confused person like me.
As I commented above, I grappled with a similar issue before in this question. As the comments above suggest, this is a scope issue. I realized that it is not only a scoping issue, it is an issue of confusion between CDI and JSF2 managed beans.
Both have a unique set of scopes, but there is some overlap, and in order to not be scratching your head over what should really not be a difficult problem, it is important to
Decide whether to use CDI beans or JSF2 managed beans
Thoroughly learn the scopes assocated with either type of bean
Know which one you are selecting when eclipse offers you 2 choices!
That last one has messed me up more times than I should admit.
Whether to use CDI or JSF2 just google "cdi vs. jsf2". I chose CDI since most things I read said to use CDI. I'm not sure it really makes a difference for my simple app.
Learn your scopes!! There are many articles about scopes, unfortunately I don't understand them as well as I should.
This is a classic for JSF2 users: Communication in JSF2 and I found this helpful as well. (notice same author - BalusC is a good resource for anything JSF2)
As for CDI just stick with the tutorial on Oracle's website.
And as for which library to import -- both JSF and CDI have a SessionScoped, and I think also RequestScoped:
CDI scopes are in javax.enterprise.context.SessionScoped
JSF scopes are in javax.faces.bean.SessionScoped
I consistently just take the first thing eclipse offers me. It can really screw you up so pay attention!

UI Repeat varStatus not working in CompositeComponent

I use JSF 2.0 (Apache myFaces) on WebSphere Application Server 8.
I have a bean which contains a list of charts (data for jquery HighCharts).
For each chart I need some JSF components + one Highchart Wrapper written as CompositeCompoent (look here)
So I use the ui:repeat function of jsf 2 like this:
<?xml version="1.0" encoding="UTF-8" ?>
<ui:composition 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"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:hc="http://java.sun.com/jsf/composite/chartComponents"
template="/template/mytemplate.xhtml">
<ui:define name="content">
<ui:repeat value="#{chartCtrl.charts }" var="chart" id="chartrepeat" varStatus="chartStatus">
#{chartStatus.index }
<h:form id="chartform_#{chartStatus.index }">
<!-- some jsf select stuff-->
</h:form>
#{chartStatus.index }
<hc:Chart title="Statistics" id="hcchart_#{chartStatus.index }"
<!-- here's the problem-->
<ui:repeat value="#{chart.series }" var="serie">
<hc:ChartSeries series="#{serie.data }" />
</ui:repeat>
</hc:Chart>
#{chartStatus.index }
</p:panel>
</ui:repeat>
<h:outputScript library="js" name="highcharts.js" />
<h:outputScript library="js/modules" name="exporting.js" />
<h:outputScript library="js" name="jquery-1.9.1.min.js" target="head" />
</ui:define>
</ui:composition>
The #{chartStatus.index } works every where but not in hc:Chart id="".
The generated js and div by this CC contains the id 'hcchart_chartdiv'. The index of the current repeat left.
How can I pass the correct number to the id attribute?
EDIT: Composite Component
Here is a part of the hc:Chart where the ID should be used
<cc:implementation>
<div id="#{cc.id}_chartDiv" />
<!-- Highcharts -_>
<script type="text/javascript">
$(function() {
// Data must be defined WITHIN the function. This prevents
// different charts using the same data variables.
var options = {
credits : {
enabled : false
},
chart : {
renderTo : '#{cc.id}_chartDiv',
....
</script>
When I leave the attribute id in hc:Chart empty, then the generated ID is something like "j_id568185923_1_5f9521d0_chartDiv". But still without :row:.
EDIT 2: IndexOf Approach
I tested another approach to set the ID of my chart.
id="hc_#{chartCtrl.charts.indexOf(chart) }"
I tried to use the IndexOf method of my ArrayList. I implemented HashCode und Equals method in all Classes. When I test it, it works fine.
But when I use it with EL I get -1 returned.
Solution
Just as BalusC said I cant use the ID tag for EL. So I simple created a new attribute in my CC. That works fine (just so easy).
Thanks BalusC.
Does someone has another idea?
The id attribute is evaluated during view build time. The <ui:repeat varStatus> is set during view render time which is after view build time. Essentially, you've the same problem as explained in detail here: JSTL in JSF2 Facelets... makes sense?
Any EL expression in the id attribute must be available during view build time. If you replace <ui:repeat> by <c:forEach> which runs during view build time, then the id must be properly set. An alternative is to just get rid of EL in those id attributes based on <ui:repeat varStatus>. JSF will already automatically suffix the IDs of <ui:repeat> child components with the row index.
Note that the <c:forEach> may have unforeseen side effects when used in combination with view scoped beans and partial state saving enabled. See the aforelinked answer for details.

Using bootstrap related tags inside JSF2 h:inputText component

Is there anyway to use bootstrap related tags in JSF2 components? For example I'm interested in using the bootstrap typeahead feature which requires something like
<h:inputText id="typeahead" type="text" data-provide="typeahead"></h:inputText>
but since data-provide doesn't exist for h:inputText it gets stripped out and so the typeahead feature would obviously not work.
Depends on JSF version you're using.
In JSF 2.0/2.1, it's not possible to specify additional attributes. The JSF HTML renderers will only render predefined attributes. You'd need to create a custom renderer to achieve the desired job. To minimize boilerplate code, you're forced to extend the implementation-specific renderer. It's unclear which one you're using, so here's just a Mojarra targeted example:
import com.sun.faces.renderkit.html_basic.TextRenderer;
public class MyTextRenderer extends TextRenderer {
#Override
protected void getEndTextToRender(FacesContext context, UIComponent component, String currentValue) throws IOException {
Object dataProvide = component.getAttributes().get("data-provide");
if (dataProvide != null) {
context.getResponseWriter().writeAttribute("data-provide", dataProvide, null);
}
super.getEndTextToRender(context, component, currentValue);
}
}
Register it as follows in faces-config.xml to get it to run:
<render-kit>
<renderer>
<component-family>javax.faces.Input</component-family>
<renderer-type>javax.faces.Text</renderer-type>
<renderer-class>com.example.MyTextRenderer</renderer-class>
</renderer>
</render-kit>
In JSF 2.2, it's possible by the new passthrough namespace or the <f:passThroughAttribute> tag. See also What's new in JSF 2.2? - HTML5 Pass-through attributes.
Thus, so:
<html ... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
...
<h:inputText id="typeahead" a:data-provide="typeahead" />
(note that the type attribute defaults to text already)
Or:
<h:inputText id="typeahead">
<f:passThroughAttribute name="data-provide" value="typeahead" />
</h:inputText>
See also:
Custom HTML tag attributes are not rendered by JSF

Can't use composite component on same page with a ui:include that relies on ui:params

I have a base page that uses a ui:include to include another page. The ui:include uses a ui:param to pass a parameter to the included page. The param is read in the PostConstruct method of the included page's controller.
This design works fine until I add a composite component to the base page; once added, the included page controller reports that the ui:param's value is null. Once I remove the composite component from the page, the ui:param is able to be read (i.e. is not null) by the included page's controller. Please help!
Files to reproduce the problem:
myPage.xhtml
<html xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:mycomponents="http://java.sun.com/jsf/composite/mycomponents">
<ui:include src="includePage.xhtml">
<ui:param name="myParam" value="myValue"/>
</ui:include>
<p/>
<mycomponents:myComponent/>
</html>
myIncludedPage.xhtml
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets">
The value of the param is: #{includedPageController.myParam}
</ui:composition>
myComponent.xhtml (placed in "resources/mycomponents")
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface/>
<composite:implementation>
I am the composite component
</composite:implementation>
</html>
IncludedPageController.java
#ManagedBean
public class IncludePageController
{
String myParam;
#PostConstruct
private void init()
{
FaceletContext faceletContext = (FaceletContext)FacesContext.getCurrentInstance().
getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
myParam = (String)faceletContext.getAttribute("myParam");
}
public String getMyParam()
{
return myParam;
}
public void setMyParam(String myParam)
{
this.myParam = myParam;
}
}
See: How do I set Managed Bean field to the value of a ui:param?. There is no standard for doing this sort of thing in the JSF API. A composite or custom component should be used rather than an include/param tag combination.

Resources