f:facet equivalent in Java [duplicate] - jsf

i am createing header for <h:panelgrid> from bean.
now this is jsf required code(if i written code in jsf page).
<f:facet name="header">
<h:outputText value="Search Template ">
</h:outputText>
</f:facet>
My Problem is how to add this in bean file with below code.
HtmlPanelGrid mainPanel = new HtmlPanelGrid();
mainPanel.setColumns(1);
mainPanel.setStyleClass("searchtabtemplate");
HtmlOutputLabel htmlOutputLabelObj = new HtmlOutputLabel();
htmlOutputLabelObj.setValue(ApplicationConstants.NO_RECORD_FOUND);
mainPanel.getChildren().add(htmlOutputLabelObj);
I have tried with this code but where i have to use facetTag i dont get idea .
FacetTag facetTag = new FacetTag();
facetTag.setName("header");
HtmlOutputLabel htmlOutputLabel = new HtmlOutputLabel();
htmlOutputLabel.setValue("Search Template");

The UIComponent superclass has a getFacets() method. Guess what it does :)
mainPanel.getFacets().put("header", htmlOutputLabel);
Unrelated to the concrete problem, the HtmlOutputLabel represents the <h:outputLabel> which is the wrong tool for the purpose. Use HtmlOutputText instead which represents <h:outputText>.

Related

How to use ajax with Primefaces components programmatically

I'm trying to create Primefaces UIComponents programmatically and somehow I'm not able to get the data to the Backing Bean. Not sure if it's the Ajax or the value I set for the InputText.
My code that I want to write programmatically:
<p:inputText id="id_test" value="#{myBean.value}">
<p:ajax />
</p:inputText>
This is how I tried to solve the problem:
private String value; // Getter&Setter
public void buildComponent(){
FacesContext fc = FacesContext.getCurrentInstance();
Application ap = fc.getApplication();
InputText inputText = (InputText) ap.createComponent(fc, "org.primefaces.component.InputText", "org.primefaces.component.InputTextRenderer")
inputText.setValue(value);
inputText.setId("id_test");
AjaxBehavior ajaxBehavior = (AjaxBehavior) ap.createBehavior(AjaxBehavior.BEHAVIOR_ID);
inputText.addClientBehavior(inputText.getDefaultEventName(), behavior);
}
You will need to create a ValueExpression that resolves to your bean property. How else should your dynamic input know where to send input values to?
Instead of:
inputText.setValue(value);
Do this:
ExpressionFactory expressionFactory = FacesContext.getCurrentInstance()
.getApplication().getExpressionFactory();
ValueExpression veBinding = expressionFactory.createValueExpression("#{myBean.value}", String.class);
inputText.setValueExpression("value", veBinding);
I'm not sure what you intend to do, but it might be better to render the component dynamically instead of creating it. Something like that:
<p:inputText id="id_test" value="#{myBean.value}" rendered="#{myBean.isSomeCondition">
<p:ajax />
</p:inputText>
or
<p:inputText id="id_test" value="#{myBean.value}" rendered="#{myBean.value != 'whatever'">
<p:ajax />
</p:inputText>

Contextmenu and target with dataTable

I'm doing jsf with primefaces5.0 and here's my scenario:
I have a page contains a dataTable with contextmenu like this:
When I clicked the contextmenu, I want to popup another "window" (not "tab") with information about the selected data, for example, the String "data1".
However, it can't be done whether I use action or url parameter in the p:menuitem.
When I use action parameter, anotherPage shows but in the original window, while the opened new window is empty:
And if I change action="/anotherPage" into url="/anotherPage.xhtml",anotherPage shows in the new window but with no information about the selected data:(Please note that the title has changed into "Another Page")
Here's what I've done:
Facelet:
<h:form>
<p:contextMenu for="dataTable">
<p:menuitem value="clickMe" icon="ui-icon-gear"
onclick="window.open('', 'Popup', config = 'scrollbars=yes,status=no,toolbar=no,location=no,menubar=no,width=1300,height=370').focus();"
target="Popup" actionListener="#{mainBean.showPopup()}" action="/anotherPage"/>
</p:contextMenu>
<p:dataTable id="dataTable" value="#{mainBean.dataList}" var="data" rowIndexVar="index" emptyMessage="Loading..."
selectionMode="single" selection="#{mainBean.selectedStr}" rowKey="#{data}">
<p:column headerText="data">
<p:outputLabel value="#{data}"/>
</p:column>
</p:dataTable>
</h:form>
BackingBean:
private List<String> dataList=new ArrayList<>();
private String selectedStr="";
public void showPopup(){
Map<String, Object> reqMap=FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
reqMap.put("param", selectedStr);
}
AnotherPage.xhtml:
<p:outputLabel value="This is the selected String:"/>
<p:outputLabel value="#{anotherPageBean.txt}"/>
AnotherPageBean:
private String txt;
#PostConstruct
public void init(){
Map<String, Object> reqMap=FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
txt=(String) reqMap.get("param");
}
Thank you very much.
Update
I did a lot survey and find out something:
Target attribute of menuitem is not rendered for action, it's a known issue and won't be fixed.
Menuitem supports f:params to pass parameters according to optimus.prime.
When I use url, the parameters can't be find in request map, which probably means it's a brand new request so that I can't find what I put in the reqMap.
Maybe I can put parameters in session map instead of request map because of what I mentioned in 3.
Neither action nor actionListener be called if I use url.
According to what I've said in the update section of my question, I found a workaround.
Please note that I believe this is just a workaround, hope there are some normal ways to solve it.
As target attribute of menuitem is not rendered for action I can only use url.
So I tried using f:params to pass parameters with url but still in vain because the 3rd point I mentioned in the update section I think.
After that, I tried put parameters in session map through backing bean and use action to call the method. However, it still won't work because action is not called if I use url.
According to this thought, I call the method outside the menuitem.
I add a event to the dataTable and call method there:
<p:dataTable id="dataTable" value="#{mainBean.dataList}" var="data" rowIndexVar="index" emptyMessage="Loading..."
selectionMode="single" selection="#{mainBean.selectedStr}" rowKey="#{data}">
<p:ajax event="contextMenu" listener="#{mainBean.setParam()}"/>
<p:column headerText="data">
<p:outputLabel value="#{data}"/>
</p:column>
</p:dataTable>
And in the Backing Bean:
public void setParam(){
HttpSession session=(HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
session.setAttribute("param", selectedStr);
}
So I can get info through session in anotherPageBean like:
#PostConstruct
public void init(){
HttpSession session=(HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
txt=(String) session.getAttribute("param");
session.removeAttribute("param");
}
Please note that the attribute should be removed after the info is got.
And this is the result:
Just for those who have the same problem.

Jsf list of all facets

Hi i know that i can use some facet variables in jsf like this:
<h:dataTable>
<h:column>
<f:facet name="header">
<h:outputText value="Item Description" />
</f:facet>
<h:outputText value="#{item.description}" />
</h:column>
</h:dataTable>
is there any documentation which lists all available facets?
i already looked at the sourcecode of
javax.faces.component.html.HtmlDataTable
but cant find any information of the facets here, where are the defined?
The facets are available by UIComponent#getFacets().
Do note that you need to obtain the particular one in your code snippet from <h:column> (HtmlColumn; UIColumn), not from <h:dataTable> (HtmlDataTable; UIData).
UIData table = getItSomehow();
for (UIComponent child : table.getChildren()) { // child == UIColumn.
Map<String, UIComponent> facets = child.getFacets();
UIComponent headerFacet = facets.get("header");
// ...
}
By the way, looking in source code is funny, but looking in javadoc is the easiest first step. It also lists the methods inherited from superclasses which are otherwise not directly visible in the class' source. You'd immediately have noticed the self-explaining "getFacets()" method when searching for the word "facets" in the javadoc.

How to programmaticallty create a <f:facet name="header"> for HtmlPanelGrid

i am createing header for <h:panelgrid> from bean.
now this is jsf required code(if i written code in jsf page).
<f:facet name="header">
<h:outputText value="Search Template ">
</h:outputText>
</f:facet>
My Problem is how to add this in bean file with below code.
HtmlPanelGrid mainPanel = new HtmlPanelGrid();
mainPanel.setColumns(1);
mainPanel.setStyleClass("searchtabtemplate");
HtmlOutputLabel htmlOutputLabelObj = new HtmlOutputLabel();
htmlOutputLabelObj.setValue(ApplicationConstants.NO_RECORD_FOUND);
mainPanel.getChildren().add(htmlOutputLabelObj);
I have tried with this code but where i have to use facetTag i dont get idea .
FacetTag facetTag = new FacetTag();
facetTag.setName("header");
HtmlOutputLabel htmlOutputLabel = new HtmlOutputLabel();
htmlOutputLabel.setValue("Search Template");
The UIComponent superclass has a getFacets() method. Guess what it does :)
mainPanel.getFacets().put("header", htmlOutputLabel);
Unrelated to the concrete problem, the HtmlOutputLabel represents the <h:outputLabel> which is the wrong tool for the purpose. Use HtmlOutputText instead which represents <h:outputText>.

JSF dataTable with selectOneListbox

I have a dataTable that lists some objects and I want to set a property for those objects using a selectOneListbox. This is my dataTable
<h:dataTable value="#{someHandler.entities}"
binding="#{someHandler.dataTable}" var="entitiy">
<h:column>
<f:facet name="header">
<t:outputText value="Level" />
</f:facet>
<h:selectOneListbox id="level" value="#{entitiy.level}" size="1"
valueChangeListener="#{someHandler.changeLevel}"
onchange="submit()">
<f:selectItem itemValue="-" itemLabel="-" />
<f:selectItem itemValue="ALL" itemLabel="ALL" />
(and so on)
</h:selectOneListbox>
</h:column>
<h:column>
<f:facet name="header">
<t:outputText value="Name" />
</f:facet>
<h:outputText value="#{entitiy.name}" />
</h:column>
</h:dataTable>
The valueChangeListener looks like this:
public void changeLevel(ValueChangeEvent event) {
String newLevel = (String) event.getNewValue();
Logger logger = (Logger) dataTable.getRowData();
logger.setLevel(Level.toLevel(newLevel));
}
(dataTable is an HtmlDataTable object.)
However, the event object is always the same - no matter which row the selectOneListbox was in. (It seems always the logger in the first row). The Logger object I get is also not the one I want.
Any ideas? Thank you!
And anothers questions? Is the entitiy.setLevel() method called even though I have a valueChangeListener? I use entitiy.level because I want to show the chosen level as a default for those entity.
Thank you!
There are two potential problems here:
First, the onchange="submit()" submits the entire form. The valueChangeListener will be invoked on all input elements of which the submitted value differs from the initial value.
You need to preset the value behind #{entitiy.level} with the same value as the default menu option. E.g. in the constructor.
public Entity() {
level = "-";
}
Or, better, make the default value null.
<f:selectItem itemValue="#{null}" itemLabel="-" />
so that the valueChangeListener won't be invoked when the particular menu is not changed.
Or, when you are already on JSF 2.x (please always mention exact JSF impl/version in your JSF questions), you can use <f:ajax> tag for this without the need for a valueChangeListener with a hacky onchange="submit()".
Second, you need to ensure that the datatable value #{someHandler.entities} returns exactly the same list during the submit as it was during the initial request. So, do the data loading in the bean (post)constructor. In JSF 2.x you'd like to put the bean in the view scope as well.
Unrelated to the concrete problem, you can also just use <h:selectOneMenu> instead of a <h:selectOneListbox size="1">.

Resources