Jsf <F:Facet> Contents Not Rendered

JSF f:facet contents not rendered

You are trying to register a facet on the h:form tag. The example in the link is registered on the h:head tag. Primefaces has a custom renderer for head.

There is no such facet defined for form, so it doesn't know how to handle it. See also <f:facet> not working with <h:form>

I believe you are confusing the css ordering issue. If you wish to override the PrimeFaces css, use the "last" facet in the head - which would place your css definition below the primefaces css.

<h:head>
<f:facet name="last">
<h:outputStylesheet library="default" name="css/style.css" />
</f:facet>
</h:head>

See http://www.mkyong.com/jsf2/primefaces/resource-ordering-in-primefaces/ for a good explanation.

f:facet tag not rendered

Use <f:facet name="header"> instead of <f:facet name="run_header">

http://www.mkyong.com/jsf2/jsf-2-datatable-example/

How do I conditionally render an f:facet?

I was able to solve this by swapping the facet out for an attribute. To summarize:

This works

<p:panel ...>
<f:attribute name="footer" value="#{message}"/>
<!-- ... -->
</p:panel>

But this doesn't work

<p:panel footer="#{message}">
<!-- ... -->
</p:panel>

Neither does this

<p:panel ...>
<f:facet name="footer">#{message}</f:facet>
<!-- ... -->
</p:panel>

Nor this

<p:panel ...>
<f:facet name="footer">
<h:outputText value="#{message}" rendered="#{!empty message}"/>
</f:facet>
<!-- ... -->
</p:panel>

by "works" I mean:

"renders no footer — not just an empty footer — when #{message} is empty or null; otherwise, correctly renders the footer with the specified text."


PrimeFaces forum thread on this issue

f:facet not working with h:form

The reference pages for h:form does not mention enctype facet. I don't think it is valid facet for h:form. However, there is attribute enctype.

If you want to define content type of the form in specific pages then use template parameters like shown below.

Template would look then:

<h:form id="main-form" enctype="#{myenctype}">

<ui:insert name="buttons"/><p/>
<ui:insert name="content"/><p/>
<ui:insert name="buttons"/>
<ui:insert name="additionalHelper"/>

</h:form>

and specific page has to define <ui:param name="myenctype" value="multipart/form-data"/>:

<ui:composition template="template.xhtml">
<ui:param name="myenctype" value="multipart/form-data"/>
<!-- other stuff like <ui:define ...> -->
</ui:composition>

If you want to provide default value for the parameter use ternary operator like described in this question.

Why are validations from my JSF composite facet being done when the facet is not rendered

This problem is two-fold.

First, the <cc:renderFacet> is never designed to work this way. It does not support the rendered attribute. That it somehow works is because the facet is internally re-interpreted as an UIPanel component and all attributes are (incorrectly) automatically inherited from the tag. You should not rely on that. The rendered attribute is incorrectly considered during render response, causing confusing behavior that it "works". This is technically a bug in the JSF implementation. The attributes are (correctly) not inherited during the postback, causing the trouble you observed. The components are still decoded and validated "in spite of" that they are not rendered.

Second, the <p:inputText> extends from UIInput which checks before validation if there's any submitted value. A submitted value of null is interpreted as complete absence of the input field in the form, so it's skipped. A submitted value of an empty string is interpeted as an empty value, so it's validated. The <p:selectOneMenu>, however, has overriden the standard UIInput behavior and considers null the same way as an empty string. Even when the submitted value is null (which means that the input field wasn't in the form at all), it's still being validated. This is technically a bug in PrimeFaces side.

Your intent is at least clear: conditionally render a facet. The <cc:xxx> tags are evaluated during Facelets compile time (which is a step before view build time), so conditionally building the <cc:renderFacet> using JSTL <c:if> will also not ever work.

Your best bet is redefining "render lower panel" as a composite attribute, and create a backing component to explicitly copy this attribute into the facet after it's being added to the view.

<cc:interface componentType="entityDetailPanelComposite">
...
<cc:facet name="lowerPanel" />
<cc:attribute name="renderLowerPanel" type="java.lang.Boolean" default="false" />
</cc:interface>
<cc:implementation>
<f:event type="postAddToView" listener="#{cc.init}" />
...
<cc:renderFacet name="lowerPanel" />
...
</cc:implementation>

@FacesComponent("entityDetailPanelComposite")
public class EntityDetailPanelComposite extends UINamingContainer {

public void init() {
UIComponent lowerPanel = getFacets().get("lowerPanel");
ValueExpression renderLowerPanel = getValueExpression("renderLowerPanel");

if (renderLowerPanel != null) {
lowerPanel.setValueExpression("rendered", renderLowerPanel); // It's an EL expression.
} else {
lowerPanel.getAttributes().put("rendered", getAttributes().get("renderLowerPanel")); // It's a literal value, or the default value.
}
}

}

This has the additional benefit you can specify it from client on.

<my:entityDetailPanel ... renderLowerPanel="true" />

Why UIComponent inside f:facet is not accesible to UIComponent#getChildren()?

Well, because a facet is a facet, not a child. You can get facets by simply using getFacets() method instead of getChildren().

Map<String, UIComponent> facets = component.getFacets();

The key represents the facet name. You can even get a specific facet by getFacet() shortcut.

UIComponent facet = component.getFacet("name");

You can get an iterator over facets and children by getFacetsAndChildren() method.

Iterator<UIComponent> iter = component.getFacetsAndChildren();

It's time to learn to find and explore the javadocs. All those answers were already in there.



Related Topics



Leave a reply



Submit