When to use f:view and f:subview - jsf-2

I am not sure what are the benefits of using <f:view> and <f:subview>.
I noticed that one could write JSF pages without using them.
What are the benefits of using those tags?

<f:view>
The <f:view> is only useful if you want to explicitly specify/override any of the available attributes such as locale, encoding, contentType, etc or want to attach some phase listeners. E.g.
<f:view locale="#{user.locale}" encoding="UTF-8" contentType="text/html">
If you don't specify it, then the sane JSF defaults will just be used instead, which is respectively UIViewRoot#getLocale(), UTF-8 and the closest match of Accept request header. Noted should be that the closest match of Accept request header isn't always entirely right. Sometimes it results in application/xhtml+xml because of the presence of .xhtml extension in the URL in case of Facelets and the webbrowser not being configured to interpret it as text/html by default (like MSIE). You'd really like to avoid this wrong content type by explicitly setting it to text/html.
Note that it doesn't matter where you put it in the template. You can even put it in template client as immediate child of <ui:define>. However, canonical place is as immediate child of <html> and thus wrapping both <h:head> and <h:body>. This is also the way how it's done in legacy JSP where it's actually required. In Facelets it's optional and accounted as meta data.
See also:
Our XHTML wiki page
Is it possible to use JSF+Facelets with HTML 4/5?
JSF 2.0 not rendering any page
<f:subview>
The <f:subview> will create another naming container context. This is particularly useful when you want to reuse an include file which in turn contain fixed component IDs more than once in the same view root, otherwise you will get duplicate component ID errors. However, since JSF 2.0 such an include file can better be a composite component which is by itself already a naming container.
If you don't specify it, then it won't harm if you don't reuse a component with the same ID physically multiple times in the view.
See also:
Why <h:panelGroup> id is not found when I access through <f:subview> tag?
Binding attribute causes duplicate component ID found in the view
Difference between <f:subview> and <ui:composition> tags

Related

Trying to find c:out tag from the JSTL library within JSF application

I am building out a dynamic table using JSTL and was hoping to make use of the c:out tag to help build out some expressions, but am not able to find that tag available among the other JSTL core tags.
I have the following namespace being used:
xmlns:c="http://java.sun.com/jsp/jstl/core"
and made sure my web.xml file was set to use the 2.5 spec found here
https://stackoverflow.com/tags/jstl/info
but still only find catch, choose, forEach, if, otherwise, set, and when.
Additionally, I tried importing the JSTL 1.2.1.jar libraries as well with no success.
So, should the c:out tag be available for me to use in JSF2 ? If so, what steps am I missing?
Regards,
Mike
The <c:out> indeed not available in JSF2 Facelets. You don't need it in JSF2 Facelets anyway. Just use the JSF equivalent <h:outputText>,
<h:outputText value="#{bean.text}" />
or even better, just put EL in template text,
#{bean.text}
It will already be implicitly XML-escaped if that's your sole concern (and was during old JSP2 ages actually the sole reason why <c:out> is been used; in JSP1 the tag was simply mandatory in order to display a bean property as EL in template text wasn't supported in JSP1). The <c:out> offers no additional advantages over those standard JSF2 Facelets ways, that's why it's been removed from the JSTL subset for Facelets.
See also:
Is it suggested to use h:outputText for everything?

Dynamically add attribute to struts2 UI tag

Is there a way to dynamically add an attribute to a struts 2, tag UI tag such as a textfield?
The reason is that I want to add a readOnly form field attribute to an <s:textfield/>, depending on an action's method result. I cannot use readOnly="%{isReadOnly()}" since once the attribute is defined, the form element is read-only, no matter what value it has. And wrapping each form field into an <s:if/> tag is pretty cumbersome and results in a lot of code duplication.
I would also like to avoid JavaScript for interoperability reasons and for not relying on the browser's scripting settings.
If the issue is to use the built in struts2 functionality then one easy option is to render your view with freemarker, which readily supports the dynamic addition of attributes.
If you are using conventions, it is VERY trivial you just need to create a file with a ".ftl" extension, if you are using xml it is also very easy just use the freemarker result type (see here for greater description):
<action name="test" class="package.Test">
<result name="success" type="freemarker">/WEB-INF/content/testView.ftl</result>
</action>
Here is example view using a map to dynamically add attributes (example also taken from liked page):
<#s.textfield name="test" dynamicAttributes={"placeholder":"input","foo":"bar"}/>
The dynamicAttributes would be extremely useful in all JSP UI tags but alas it is not currently implemented.
NOTE: There is one error/omission in the above link. It tells you to add the following line which causes an error in my environment (simply the line is not needed).
<#assign s=JspTaglibs["/WEB-INF/struts.tld"] />
That is, this line in a file all by it self is sufficient for rendering a text element, no explicit tag library declaration needed!
<#s.textfield name="test" dynamicAttributes={"placeholder":"input","foo":"bar"}/>
There are a number of advantages to using freemarker over plain JSPs, so taking a moment to explore the syntax and using it for this one case may prove useful later.

JSF page in subfolder can't see template

I've got a template in WEB-INF/templates/standardTemplate.xhtml
In my "Web Pages" root, I've got an index.xhtml which uses the template via
<ui:composition template="/WEB-INF/templates/standardTemplate.xhtml">
The above works fine.
However I also have another page which uses the same template, but it's in a subfolder "Web Pages"/messageboard/list.xhtml
It uses exactly the same syntax/paths:
<ui:composition template="/WEB-INF/templates/standardTemplate.xhtml">
But it can't find the template and renders just the content of list.xhtml (none of the template's content).
Faces servlet is mapped to "/faces/*"
What am I doing wrong? Tried every variant I can think of but I can't get the right syntax.
Thanks
As per the comments, you're seeing <ui:composition> unparsed in the HTML output.
That can only mean that the request URL as you've in the browser address bar does not match the URL pattern of the FacesServlet. Make sure that it matches the URL pattern of the FacesServlet. You've mapped it on /faces/*, so the URL should contain the /faces path prefix right after the context path.
Better would be to map the FacesServlet directly on *.xhtml so that you never need to fiddle with virtual URLs.

A better way to get the real ID of an component in a naming container

I got the following scenario:
I got several tabs (TabView is a naming container )
and in one of the I got a p:inputText which shows a dialog(which is located in other xhtml file) , now I want the dialog to update the p:inputText , the thing is that the id of the p:inputText is unknow (JSF adds some prefix to it)
<h:form id="hoursReportFrm">
<p:inputText id="comment4Dialog" value="#{hoursReportBean.aComment}"
onfocus="dlg1.show();"/>
I can't use this update="hoursReportFrm:comment4Dialog" in the dialog
ATM i looked at the example of this site JSF: working with component IDs (id vs clientId) (its from 2009)
and added binding to to inputtext , like thisbinding="#{lookup.components.comment4Dialog}" and in the p:commandButton of the dialog I changed to update="#{lookup.clientIds.comment4Dialog}"
and It works just fine, but I'm looking for a better way , without the need to bind every component that I would like to access later...
Thanks ahead,
To be quite honest, I think the binding is probably the easiest route, however when I've been in that situation I've found composite components often offer a better solution than bindings. Depending on the situation (and again, its totally case by case) you can use a composite component to get around this problem. This allows you to reuse parts of a page creatively so that your specific updates don't take a lot of work and you can reuse the code.
An example of this might be:
//comp:myDialog
...
<composite:interface>
<composite:attribute name="update" />
<!-- Other attributes -->
</composite:interface>
<composite:implementation>
...
<!-- Implementation -->
<p:commandButton update="#{cc.attrs.update}"/>
...
</composite:implementation>
And here might be the component in use:
//for the sake of argument 'comp' as your library
<h:form id="someForm">
<p:inputText value="#{bean.changeMe}" id="changeMe"/>
</h:form>
<h:form id="dialog">
<!-- dialog here -->
<comp:myDialog update="someForm:changeMe" />
</h:form>
By separating this view into a piece of reusable code you might be able to get around the burden of specifying the full path because it is now much easier to reuse. However, I think it is a toss up of a binding or the composite component depending on the specific case. For reuse, make a new object (component) and reuse it. If you're dealing with a highly dynamic environment: bind it.
I'm not an expert by any means, but generally speaking the above has gotten me out of a lot of tough situations.
EDIT: on a re-read you should also make sure that the tab-view isn't lazily loaded and take a look at the rendering to make sure the path is correct (inspect the ID). I've had problems (in older versions of Primefaces) where sometimes the id was nested inside a p:outputPanel or in rare cases the subview id. It might be a very simple fix by specifying the full path ':subview:form:component' though that shouldn't be the case.

f:verbatim tag stops working when inside a dataTable

I posted this to the PrimeFaces user forum but I think they are too busy to look into it, so I thought I would try here.
I have server-side string that has markup in it, so when I want it rendered I do this:
<p:panel>
<f:verbatim>
#{daBean.markedUpString}
</f:verbatim>
</p:panel>
This works fine, but not if the same tag is used inside a p:dataTable -- either with or without the p:panel enclosure. What gets rendered is a div class="ui-dt-c" element with nothing in it. To test, if I take out the f:verbatim tag the marked-up text gets escaped and rendered.
I don't know if this should be considered a bug or not, but does anyone know of a work-around for this? This is with PrimeFaces 3.0.M3.
The <f:verbatim> tag is intented to hold plain text/HTML, not JSF components nor EL expressions. The tag is a leftover from JSF 1.0/1.1 ages when it was not possible to inline plain text/HTML between JSF components. The tag is deprecated in JSF2. You do not need it anymore.
Your concrete functional requirement is thus displaying some HTML string from a managed bean unescaped. For that you should use <h:outputText> with escape="false".
<h:outputText value="#{daBean.markedUpString}" escape="false" />
See also:
Getters inside f:verbatim called before form submission
JSF/Facelets: why is it not a good idea to mix JSF/Facelets with HTML tags?
What are the main disadvantages of Java Server Faces 2.0?

Resources