Conditionally including a template file in ui:composition tag - jsf

I am using facelets for templating in my jsf application. I would like to including a template file conditionally in ui:composition tag. If user is logged in the template must be "authorized.xhtml" and if the user is not logged in then the template must be "unauthorized.xhtml". Is there a way to do it? Thanks.
<ui:composition template="/templates/unauthorized.xhtml">
<ui:composition template="/templates/authorized.xhtml">
I am using JSF 1.2.

I would try ternary operation on isAuthorized() attribute, if you have one in your log-in bean:
<ui:composition template="#{loginbean.authorized ? '/templates/authorized.xhtml' : '/templates/unauthorized.xhtml'}">
Or use two <h:panelGroup> tags with appropriate rendered values:
<h:panelGroup rendered="#{loginbean.authorized}">
<ui:decorate template="/templates/authorized.xhtml">
</h:panelGroup>
<h:panelGroup rendered="#{not loginbean.authorized}">
<ui:decorate template="/templates/unauthorized.xhtml">
</h:panelGroup>

Related

JSF: duplicate component id exception when including the same facelets tag twice

I have a facelets tag like this:
<ui:composition>
<h:outputText value="#{label}"/>
<h:inputText id="input" value="#{value}"/>
<h:message for="input"/>
</ui:composition>
Now if I inlcude this facelets tag twice on the same page, I get an exception complaining about duplicate compoment ids. One solution proposed here https://stackoverflow.com/a/21572756/1785730 was to supply a prefix for the id. However, I find it cumbersome having to come up with an id prefix every time I use this facelets tag. By the way, I don't need the id of the h:inputText outside of the tag.
So I'm thinking of two ways how I can fix this:
Is there a way to link the h:message to the h:inputText without having to specify ids?
If not, I could wrap the tag with a NamingContainer. Which element would be appropriate for that? I can't use h:form here, because that tag already goes into a form.
Your page should be like this
<f:view contracts="default" transient="false">
<ui:composition template="/template.xhtml">
<ui:define name="content">
<h:form>
inputs
</h:form>
</ui:define>
</ui:composition>
</f:view>
inside ui composition you should have ui define and in it form and inputs.

JSF Missing get parameters in url [duplicate]

This question already has answers here:
Retaining GET request query string parameters on JSF form submit
(2 answers)
Closed 8 years ago.
After days of googling I must give up and ask for help. I have xhtml page with jsf tags. Whole page is controlled by PageController.java. Important thing is that controller takes item Id and page number from url parameters. Beside that I have small form which contains current logged user information or username and password input if no one is logged in. I would like have possibility to log in or log out user using that form. But when I call either user logIn() or logOut() function from user controller parameters from url just missing. I've already tried using h:commandbutton and h:commandlink as well. I managed to send parameters via f:param tag but they still missing from url (that's problem because I need bookmarking here). tags like h:link, h:button or h:outputLink cannot be used because they don't allow me to call controller function on click.
Thanks for any help.
Edit:
I forgot to mention, I've tried to solve this via f:ajax. Problem is after log in I cannot log out without refreshing page. This same with other direction.
Edit II:
I will show sample code illustrating the problem. In my project I have template.html which is simple page template containing header, footer, aside menu, and main content. It probably have not influence at the problem I've met. My code looks like that:
<?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://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">
<f:metadata>
<f:event type="preRenderComponent" listener="#{PageController.init()}"/>
</f:metadata>
<ui:composition template="/template.xhtml">
<ui:define name="aside-menu">
<h:form id = "sidemenuform">
<h:panelGrid rendered="#{usersController.isLoggedIn()}" columns="1">
<h:commandLink value="LogOut" >
<f:param name="orderId" value="${PageController.groupId}"/>
<f:param name="page" value="${PageController.PageNumber}"/>
</h:commandLink>
</h:panelGrid>
<h:panelGrid rendered="#{!usersController.isLoggedIn()}" columns="1">
<h:outputLabel for="usernameInput" value="#{bundle.LogginUsernameLabel}: "/>
<h:inputText id="usernameInput" value="#{usersController.username}"/>
<h:outputLabel for="passwordInput" value="#{bundle.LogginPasswordLabel}:">
</h:outputLabel>
<h:inputSecret id="passwordInput" value="#{usersController.password}"/>
<h:commandButton action="#{usersController.login()}">
<f:param name="orderId" value="${PageController.GroupNumber}"/>
<f:param name="page" value="${PageController.PageNumber}"/>
</h:commandButton>
</h:panelGrid>
</h:form>
</ui:define>
<ui:define name="body">
<div id="navBar">
<ul>
<li class="previousPage">
<h:commandLink action="#{PageController.previous}" rendered="#{PageController.pagination.hasPreviousPage}">
</h:commandLink>
</li>
<li class="nextPage">
<h:commandLink action="#{PageController.next}" rendered="#{PageController.pagination.hasNextPage}">
</h:commandLink>
</li>
</ul>
</div>
<ui:repeat value="#{PageController.items}" var="item" varStatus="status">
<!-- List of items in group divided into pages -->
</ui:repeat>
</ui:define>
</ui:composition>
PageController.previous and PageController.next functions working well because they returning url with GET parameters as string which looks like:
Page?groupId=1&PageNumber=2&faces-redirect=true
But userController knows nothing about them, neither about page which we currently show. So functions Login and Logout can not return url. Both functions return void. The problem is that when I fire these functions after page reload my address url changed from
/Project/faces/groups/Page.xhtml?groupId=534?pageNumber=1
To
/Project/faces/groups/Page.xhtml
And then init function fail. How to prevent this behavior??
h:link and h:button create javascript links, there's no chance to use them for invoking server side methods. What you need is to POST the server with user credentials and later on invoke a REDIRECT if the login process is correct. Your best is to use a page controller for the current view and a user controller which has the session info for the logged user. You can easily inject one bean into the other one:
#ManagedBean
#SessionScoped
public class UserController{
public boolean doLogin(String email, String password){
//Do your internal request here
}
}
#ManagedBean
#ViewScoped
public class PageController{
//You'll need a setter for this
#ManagedProperty(value=#{userController})
private UserController userController;
public String doLogin(){
if (userController.doLogin(email, password)){
return "page?groupId=" + groupId + "PageNumber=" +
pageNumber +"faces-redirect=true";
}
else{
//Add some faces message describing the error
}
}
}
That way you make the process transparent for the view, which will only acess page controller methods.
Try using f:viewParams inside your f:metadata tags:
<f:metadata>
<f:viewParam name="orderId" value="${PageController.groupId}"/>
<f:viewParam name="page" value="${PageController.PageNumber}"/>
</f:metadata>
and append ?includeViewParams=true to the url returned by userController.login() and userController.logout(). This should append the view parameters to the url automatically.

JSF page lost style after partial update

I have some troubles with partial update of jsf 2.0 page.
I have dropdown menu with few choices. Depending on choice I show different page. When I load page first time it shows css and javascript works fine. When I change another option in dropdown menu this part of page which has been re rendered appearing without css and javascript on it doesn't work.
This is example of page itself which I using, template.xhtm and bean are pretty generic therefor I didn't include it.
<ui:composition template="/template.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:t="http://myfaces.apache.org/tomahawk"
xmlns:h="http://java.sun.com/jsf/html">
<ui:define name="body">
<h:form>
<h:selectOneMenu value="#{bean.answer}">
<f:selectItems value="#{bean.answers}" />
<f:ajax event="change" render="includeContainer #All" />
</h:selectOneMenu>
</h:form>
<h:panelGroup id="includeContainer">
<h:panelGroup library="primefaces" name="jquery/jquery.js"
rendered="#{bean.answer == 'yes'}">
<ui:include src="answer_yes.xhtml"></ui:include>
</h:panelGroup>
<h:panelGroup rendered="#{bean.asnwer == 'no'}">
<ui:include src="answer_no.xhtml"></ui:include>
</h:panelGroup>
</h:panelGroup>
</ui:define>
</ui:composition>
One important remark regarding template that I use this statement to include css, it's located on remote server and I can't download and place it locally, it's company's policy.
<link href="http://server.com/resources/w3.css" rel="stylesheet" title="w3" type="text/css" />
Thank you in advance for your help.
You can put rendered panel group inside an <h:form id="toberendred"> and re-render this form instead of h:panelGroup.
For proper (JSF way) loading your css file from remote server you can use Omnifaces CDNResourceHandler
In addition you got some serious issues in your code:
Why use #all (fix to lowercase) with additional (includeContainer) selector? , do view source and see that you can't render <ui:include in view source you will see content of both yes and no xhtmls + <h:panelGroup got no attributes library and name...

How do I dynamically include the backing bean value in jsf 1.2

Hi i have the following code
creatPage1.jsp
<h:inputText id="inputId1" value="#{createPage.item.name}"/>
i have updatePage1.jsp
<h:inputText id="inputId1" value="#{updatePage.item.name}"/>
I want to be able to do include (via ui:include or jsp:include) and be able to pass in the value dynamically (the base backing bean to be createPage or updatePage).
So the result should be
<ui:include src="Page1.jsp" basebean="#{createPage}"/>
Page1.jsp
<h:inputText id="inputId1" value="#{baseBean.item.name}"/>
Whats the best way to do this in jsf?
You can use ui:param :
<ui:include src="Page1.jsp">
<ui:param name="basebean" value="#{createPage}"/>
</ui:include>
You will probably need to create your own custom tag. Check this out: http://www.ibm.com/developerworks/java/library/j-facelets/

How to add placeholder attribute to JSF input component?

Shouldn't this line of code render a inputtext field with the placeholder text "fill me" when using html5?
<h:inputText placeholder="fill me" />
I do not see any placeholder text. I thought everything that was not JSF was passed to the browser for rendering?
I thought everything that was not JSF was passed to the browswer for rendering?
This assumption is thus wrong. Unspecified component attributes are ignored by the JSF renderers.
You have basically the following options to get it to work:
If you're already on JSF 2.2 or newer, set it as a passthrough attribute.
<... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
<h:inputText a:placeholder="fill me" />
Note that I use a XML namespace prefix of a ("attribute") instead of p as shown in the tutorial, as it would otherwise clash with default XML namespace prefix p of PrimeFaces.
Implement a custom renderer for <h:inputText> wherein you explicitly check and write the attribute.
Implement a custom component which uses the aforementioned custom renderer.
Implement a JS based solution wherein you grab the element from DOM and explicitly set the attribute.
Look for a component library which supports this out the box. PrimeFaces for example has a <p:watermark> for this purpose with nice JS based graceful degradation for browsers which does not support the placeholder attribute on inputs.
See also:
Custom HTML tag attributes are not rendered by JSF
You can achieve it either with placeholder attribute or with p:watermark if using Primefaces and JSF 2.0+ or, when JSF 2.2 available, you can use pt:placeholder attribute.
Primefaces
<p:inputText id="search_input_id" value="#{watermarkBean.keyword}"
required="true" label="Keyword" placeholder="fill me" />
Legacy browser support (Adds JS solution):
<p:inputText id="search_input_id" value="#{watermarkBean.keyword}"
required="true" label="Keyword" />
<p:watermark for="search_input_id" value="fill me" />
JSF 2.2 (without PF)
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough">
<h:head>
</h:head>
<h:body>
<h:inputText value="#{bean.value}" pt:placeholder="fill me"/>
</h:body>
</html>
Which basically generates an HTML 5
<input placeholder="fill me" />
Check out this answer.
With JSF 2.2 you can passthrough unspecified attributes like this:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://xmlns.jcp.org/jsf/passthrough"
>
<h:inputText p:placeholder="fill me"></h:inputText>
In case you are using RichFaces, starting in version 4.3, you can use the tag "rich:placeholder" for this purpose as shown here. Basically:
<h:inputText id="myInput">
<rich:placeholder value="My placeholder text"></rich:placeholder>
</h:inputText>
Try this
<h:inputText id="name" value="#{login.userId}" class="aux1" />
<h:inputSecret id="password" value="#{login.password}" redisplay="true" class="aux2" autocomplete="off" />
<script>
$('.aux1').attr('placeholder', 'Introducir Usuario');
$('.aux2').attr('placeholder', 'Introducir ContraseƱa');
</script>
With jQuery, this works right for me.
It's very easy and browser independent code as BaluSc told,
In primefaces, use p:watermark to get the required functionality.
Official Demo is HERE
Use primeface 4.0. Versions below this version do not support the placeholder attribute.
use name space xmlns:pt="http://java.sun.com/jsf/passthrough".
p:inputTextarea id="textAreaValue" pt:placeholder="your text"
don't insert a new line in inputTextArea.
The simplest way to render an input field with a placeholder text is to use the elementary input tag
Example:
<input type="text" placeholder="Fill me" value="#{EL}"/>
Note: you dont have to include any namespaces
<h:head>
</h:head>
<h:body>
<h:inputText value="#{bean.value}" placeholder="fill me"/>
</h:body>
This works right for me, try it!

Resources