How to programmaticallty create a <f:facet name="header"> for HtmlPanelGrid - 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

f:facet equivalent in Java [duplicate]

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>.

PrimeFaces Datatable - What is f:facet actually doing?

Looking through some PrimeFaces code in an app I noticed the following line:
<f:facet name="header">#{trainSearch.trainCount} Trains</f:facet>
It looks like it is overriding the header, which makes sense, but can someone explain this to me in a little more detail?
What is actually happening with this line of code?
Complete code listed below:
<p:dataTable id = "results" value = "#{trainSearch.trains}" var = "train" rendered="#{not empty trainSearch.trains}" styleClass = "train-search-table horizontal-border">
<f:facet name="header">#{trainSearch.trainCount} Trains</f:facet>
<p:column headerText = "Train ID">
<p:panelGrid columns="1" styleClass = "train-id-grid" layout = "grid">
<h:outputText styleClass = "train-id-label" value="#{train.trainI}"/>
<h:outputText value="#{train.originCityState} > #{train.destinationCityState}" />
</p:panelGrid>
</p:column>
<p:column headerText="Scheduled Departure">
<h:outputText value="#{train.formattedScheduledDepartureText}" />
</p:column>
<p:column headerText="Scheduled Arrival">
<h:outputText value="#{train.formattedScheduledArrivalText}" />
</p:column>
<p:column headerText="Loco Count">
<h:outputText value="#{train.locoCount}" />
</p:column>
<p:column headerText="Car Count">
<h:outputText value="#{train.carCount}" />
</p:column>
</p:dataTable>
Facets in JSF are used to customize the rendering of a component, without touching its code, like the header facet in datatable, where you can put custom code in datatable header, without touching actual PrimeFaces datatable code.
The DataTableRenderer (class that writes html code of datatable) gets the xhtml code you put inside a facet and renders it inside a div.
You can see this in the method encodeFacetof DataTableRenderer:
protected void encodeFacet(FacesContext context, DataTable table, UIComponent facet, String styleClass) throws IOException {
if(facet == null)
return;
ResponseWriter writer = context.getResponseWriter();
writer.startElement("div", null);
writer.writeAttribute("class", styleClass, null);
facet.encodeAll(context);
writer.endElement("div");
}
The line facet.encodeAll(context); renders the code you put inside facet as html, in RENDER_RESPONSE jsf phase.

Add a row to rich:datatable manually for input text

I want to add a row at the end of my rich:datatable that shows information
and in this row I want to put some input that enable user to add new data
I read this answer :
RICH:dataTable - add new row
but for me is a little different
I don't have any list
my xhtml is like this :
<rich:dataTable value="#{serverMB.allServer}" var="servers1" iterationStatusVar="it" id="table" rows="15"
style="direction: rtl ; text-align: right">
<rich:column>
<f:facet name="header">#</f:facet>
#{it.index+1}
</rich:column>
<f:facet name="header">
<h:outputText value="#{msgs.servers}"/>
</f:facet>
<rich:column filterValue="#{serverMB.serverNameFilter}"
filterExpression="#{fn:containsIgnoreCase(servers1.server_name,serverMB.serverNameFilter )}">
<f:facet name="header">
<h:outputText value="#{msgs.server_name}"/>
<h:inputText value="#{serverMB.serverNameFilter}">
<a4j:ajax event="blur" render="table" execute="#this"/>
</h:inputText>
</f:facet>
<h:outputText value="#{servers1.server_name}"/>
</rich:column>
.
.
.
and my managedbean is like this
public List<Server> getAllServer() {
return serverFacade.findAll();
}
I use this method to show information so there is not any list that I personally can add a row to it and so on ...
so what I must do ?
Your serverList should be populated and set as a class-level variable. Use an #PostConstruct method to populate the list:
#PostConstruct
public void initServerList(){
//declare serverList as a class-scoped variable in your managed bean
serverList = serverFacade.findAll();
}
Declare a method in your managed bean that will add to the serverList
public void incrementList(){
Server server = new Server(); //create a dummy Server object
serverList.add(server); // List has been incremented. Be sure to AJAX-refresh the datatable after calling this method to reflect the new row.
}
Collect information from the JSF view which you'll then use to fill the fields of the dummy object:
public void updateLatestServer(){
Server lastServer = serverList.get(serverList.size-1);
lastServer.setName(serverNameFromView);
lastServer.setIP(IPFromView);
}
The serverNameFromView and IPFromView are hypothetical variables you'll collect in your JSF Form.

Dynamic Column in JSF Datatable JSF2.0

I need one help from you. I am using JSF 2.0 and I have a datatable component . One of the column in the datatable is an action column and I need to create a toolbar which contains different type of actionsource component such as command button, link etc. The type of actionsource is determined at run time and number of actionsource is also done at run time. How I can implement this in JSF 2.0
<p:dataTable value="#{listBranchBean1.rowDataModel}" var="rowItem"
id="myId" paginator="true"
paginatorTemplate="{FirstPageLink}{PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}{RowsPerPageDropdown} "
rowsPerPageTemplate="10,5,2" previousPageLinkLabel="<"
nextPageLinkLabel=">" widgetVar="branchTable"
selection="#{listBranchBean1.selectedBranchesPrime}"
resizableColumns="true"
sortBy="#{rowItem.columnsValueMap['branchId'].value}">
<f:facet name="header">
<p:outputPanel>
<h:outputText value="Search all fields:" />
<p:inputText id="globalFilter" onkeyup="branchTable.filter()"
style="width:150px" />
</p:outputPanel>
</f:facet>
<p:column selectionMode="multiple" style="text-align:left">
<f:facet name="header">
<h:outputText value="Select" />
</f:facet>
<h:outputText value="#{rowItem.uniqueId}" />
</p:column>
<p:column
rendered="#{listBranchBean1.columnsMap['objectId'].hidden==false}"
sortBy="#{rowItem.columnsValueMap['objectId'].value}"
filterBy="#{rowItem.columnsValueMap['objectId'].value}">
<f:facet name="header">
<h:outputText
value="#{listBranchBean1.columnsMap['objectId'].displayLabel}" />
</f:facet>
<h:outputText
value="#{rowItem.columnsValueMap['objectId'].value}" />
</p:column>
<p:column
rendered="#{listBranchBean1.columnsMap['actions'].hidden==false}">
<f:facet name="header">
<h:outputText
value="#{listBranchBean1.columnsMap['actions'].displayLabel}" />
</f:facet>
<p:toolbar>
<p:toolbarGroup>
<ui:repeat var="action"
value="#{rowItem.columnsValueMap['actions'].value}">
<p:commandButton title="#{action}" type="button">
</p:commandButton>
</ui:repeat>
</p:toolbarGroup>
</p:toolbar>
</p:column>
</p:dataTable>
I want to replace the last column with something like
<p:toolbar binding="#{listBranchBean1.getActions(rowItem)}">
</p:toolbar>
I appreciate your help
Prajeesh Nair
There is a difference between build-time and render-time in JSF. Build-time tags like <ui:repeat> have the ability to create new components dynamically, but they can only use data that is available at build-time.
However, using Java you are also allowed to alter the component tree programmatically, but this too can not just happen at any moment. The safe moment to do this is the preRenderViewEvent, which is a good bit later than the build-time moment (which is the restore view phase) and you should have all the data you need by then.
Inside an event handler for this event you can reference the tool bar you bound to your backing bean, and programmatically add columns to it.
For examples see:
http://balusc.omnifaces.org/2006/06/using-datatables.html#PopulateDynamicDatatable
http://arjan-tijms.omnifaces.org/2011/09/authoring-jsf-pages-in-pure-java.html
Do note that if your backing bean is #ViewScoped, you'd better not use binding but use a manual lookup instead. This is due to some bugs with respect to the view scope and binding components in JSF.
below code will create dynamic column on the basis of selected country
public void loadDynamicList() throws Exception {
int i=0;
dynamicList = new ArrayList<List<String>>();
dynamicList.add(Arrays.asList(new String[] { "ID1" }));
existingCountryList = new ArrayList<Country>();
String countryCode="US";
existingCountryList.add(getCountryService().getCountryByCode(countryCode));
Country country=getCountryService().getCountryByCode(countryCode);
countryLanguageSet=country.getCountryLanguage();
i=country.getCountryLanguage().size();
dynamicHeaders = new String[i] ;
int j=0;
for (CountryLanguage count: countryLanguageSet) {
System.out.println(count.getLanguage().getLanguageName());
dynamicHeaders[j]=count.getLanguage().getLanguageName();
j++;
}
}
public void populateDynamicDataTable() {
debugLogger.debug("populateDynamicDataTable:Enter");
// Create <h:dataTable value="#{myBean.dynamicList}" var="dynamicItem">.
HtmlDataTable dynamicDataTable = new HtmlDataTable();
dynamicDataTable.setValueExpression("value", createValueExpression("#{relationBean.dynamicList}", List.class));
dynamicDataTable.setVar("dynamicItem");
// Iterate over columns.
for (int i = 0; i < dynamicHeaders.length; i++) {
// Create <h:column>.
HtmlColumn column = new HtmlColumn();
dynamicDataTable.getChildren().add(column);
// Create <h:outputText value="dynamicHeaders[i]"> for <f:facet name="header"> of column.
HtmlOutputText header = new HtmlOutputText();
header.setValue(dynamicHeaders[i]);
column.setHeader(header);
HtmlInputText input=new HtmlInputText();
column.getChildren().add(input);
}
dynamicDataTableGroup = new HtmlPanelGroup();
dynamicDataTableGroup.getChildren().add(dynamicDataTable);
debugLogger.debug("populateDynamicDataTable:Exit");
}
public HtmlPanelGroup getDynamicDataTableGroup() throws Exception {
// This will be called once in the first RESTORE VIEW phase.
if (dynamicDataTableGroup == null) {
loadDynamicList(); // Preload dynamic list.
populateDynamicDataTable(); // Populate editable datatable.
}
return dynamicDataTableGroup;
}
public List<List<String>> getDynamicList() {
return dynamicList;
}
public void setDynamicList(List<List<String>> dynamicList) {
this.dynamicList = dynamicList;
}
public void setDynamicDataTableGroup(HtmlPanelGroup dynamicDataTableGroup) {
this.dynamicDataTableGroup = dynamicDataTableGroup;
}
public ValueExpression createValueExpression(String valueExpression, Class<?> valueType) {
FacesContext facesContext = FacesContext.getCurrentInstance();
return facesContext.getApplication().getExpressionFactory().createValueExpression(
facesContext.getELContext(), valueExpression, valueType);
}

How to pass parameter to valueChangeListener in p:dataTable?

I am calling valueChangeListener on a <h:selectBooleanCheckbox> which is inside a dataTable. and that dataTable is again inside another(outer) dataTable. In the valueChangeListener method I want the instance object of outer dataTable. Is there any way to get the object of outer dataTable instance?
EX:
<h:panelGroup id="panelId">
<p:dataTable id="outerDatatable"
var="supplier"
value="bean.supplierList">
<p:column>
<f:facet name="header">
<h:outputText value="Suppliers" />
</f:facet>
<h:outputText value="#{supplier.name}" />
</p:column>
<p:column>
<p:dataTable id="innerDataTable"
var="supplierAccount"
value="supplier.supplierAccountList">
<p:column>
<h:selectBooleanCheckbox id="booleanBoxId"
value="#{supplierAccount.supported}"
valueChangeListener="#bean.checkBoxListener}"
immediate="true"
onchange="this.form.submit();"/>
</p:column>
</p:dataTable>
</p:column>
</p:dataTable>
</h:panelGroup>
I found the following solution : I used <p:ajax> listener instead of valueChangeListener, and I could pass 'supplier' object as well as supplierAccount object to this listener method. We can pass any number of custom objects to <p:ajax> listener.
<p:column>
<h:selectBooleanCheckbox id="booleanBoxId"
value="#{supplierAccount.supported}"
immediate="true">
</h:selectBooleanCheckbox>
<p:ajax listener="#{bean.myListenerMethod(supplier,supplierAccount)}"
update=":formName:panelId"/>
</p:column>
In this particular case, you could get it by evaluating the #{supplier} programmatically:
public void checkBoxListener(ValueChangeEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
Supplier supplier = context.getApplication().evaluateExpressionGet(context, "#{supplier}", Supplier.class);
// ...
}
However, this is plain ugly, you're synchronously submitting the entire form by onchange="submit()". I recommend to throw in some ajax for that.
<h:selectBooleanCheckbox value="#{supplierAccount.supported}">
<f:ajax listener="#{bean.checkBoxListener}" render="???" />
</h:selectBooleanCheckbox>
(the render attribute is up to you)
with
public void checkBoxListener(AjaxBehavior event) {
Boolean value = (Boolean) ((UIInput) event.getComponent()).getValue();
FacesContext context = FacesContext.getCurrentInstance();
Supplier supplier = context.getApplication().evaluateExpressionGet(context, "#{supplier}", Supplier.class);
// ...
}
Or if your environment supports EL 2.2 and thus specifying method arguments in EL:
<h:selectBooleanCheckbox value="#{supplierAccount.supported}">
<f:ajax listener="#{bean.checkBoxListener(component, supplier)}" render="???" />
</h:selectBooleanCheckbox>
public void checkBoxListener(UISelectBoolean checkbox, Supplier supplier) {
boolean selected = checkbox.isSelected();
// ...
}
See also:
When to use valueChangeListener or f:ajax listener?
Unrelated to the concrete problem, as to using onchange="submit()", it may be useful to know that onchange doesn't work as expected for checkboxes in IE6/7. It get only fired on every 2nd click. You rather want to use onclick="submit()" instead.
I see that you forgot a brace ({) just before bean:
valueChangeListener="#{bean.checkBoxListener}" immediate="true"
Also, since you're using Primefaces, you could use it's components(that if you use version 3): http://www.primefaces.org/showcase-labs/ui/selectBooleanCheckbox.jsf
It isn't necessary to use outputText if you use jsf 2:
<f:facet name="header">
Suppliers
</f:facet>
Also it isn't necessary to use f:facet because the column component has an attribute called headerText:
<p:column headerText="Suppliers">
#{supplier.name}"
</p:column>
It's a lot simpler that way, isn't it?
PS: What's this? value="supplier.supplierAccountList" No #{ }?

Resources