How bind primefaces datatable from managedbean - jsf

How bind primefaces datatable in managedbean? How put the data, and how put columns?
My bean class:
public class BeanTest implements Serializable{
private String name;
private String email;
private int age;
//getters and setters
}
My managed bean:
public class TestTable implements Serializable{
private DataTable tabela;
private List<BeanTest> lista;
#PostConstruct
public void init() {
int age= 18;
this.lista = new ArrayList<>();
this.lista.add(new BeanTest("name1", "email1", age));
this.lista.add(new BeanTest("name2", "email2", age++));
this.lista.add(new BeanTest("name3", "email3", age++));
this.tabela = new DataTable();
Column column1 = new Column();
column1.setHeaderText("Nome");
Column column2 = new Column();
column2.setHeaderText("Email");
Column column3 = new Column();
column3.setHeaderText("Idade");
this.getTabela().getChildren().add(column1);
this.getTabela().getChildren().add(column2);
this.getTabela().getChildren().add(column3);
this.getTabela().setValue(this.lista);
}
}
JSF page:
<p:dataTable id="datalist" binding="#{testeTabela.tabela}">
</p:dataTable>
This display the table with three columns (correct, number and headers) and three rows(correct numbers), but there's no data in my rows. Empty table only with borders cells.
What's happening? How could i bind columns and data?

In general, a JSF component has 3 parts: a tag, a component class and a renderer.
The tag is responsible for the component configuration. It will instantiate your component and set the appropriate attributes, listeners and facets. Once configured, the component will be put on the component tree.
Using your example, the page code will look similar to this:
<p:dataTable id="dataTable" var="item" value="#{bean.list}">
<p:column headerText="Name">#{item.name}</p:column>
<p:column headerText="Email">#{item.email}</p:column>
<p:column headerText="Age">#{item.age}</p:column>
</p:dataTable>
It's easier to do that way. However, if you want to do in code, you need to add some components inside the columns to make it work.
First, set the var attribute on the datatable. The component (datatable) will iterate over your items and bind the current item to that name, so the child components can use an expression to dynamically get that value.
this.getTabela().setVar("item");
Second, add a child UIOutput to the column and add an expression to the its value property. For the name column, it would be something like this:
FacesContext context = FacesContext.getCurrentInstance();
//Creates the output and sets the value to an expression language
UIOutput output1 = new UIOutput();
output1.setValueExpression("value",context.getApplication().getExpressionFactory().createValueExpression(context.getELContext(),"#{item.name}", String.class));
//Add the output to the column
column1.getChildren().add(output1);
For the other columns, it's the same idea, except for the type of the third UIOutput's value:
...createValueExpression(context.getELContext(),"#{item.age}", Integer.class));
As you can probably see, this can be hard to maintain.
Using tags is cleaner and easier to read.

Related

How to set defalult selected items in selectOneRadio/selectCheckboxMenu by beans in primefaces

I want to create selectOneRadio list and selectCheckboxMenu which items get from related bean objects.
For non selected list it is working well.But how can i provide these lists with some item(s) selected by default.
My current selectCheckboxMenu code is like this.
<p:selectCheckboxMenu id="trdays"
value="#{mybean.selectedDay}"
label="Select Days">
<f:selectItems value="#{mybean.dayList}" var="day"
itemValue="#{day.value}" itemLabel="#{day.name}"/>
</p:selectCheckboxMenu>
it should look like this when page loaded and user haven't done anything yet.
EDIT
Day Class :-
public class Day{
private String name;
private String value;
//getters and setters
}
Value attribute of selectCheckboxMenu component should get the your default values.
On bean side you should write a getter for selectedDayList and all daylist.
Example:
#PostConstruct
public void init() {
dayList= new ArrayList<String>();
dayList.add("Mon");
dayList.add("Tue");
dayList.add("Wed");
dayList.add("Thu");
dayList.add("Fri");
dayList.add("Sat");
dayList.add("Sun");
selectedDayList= new ArrayList<String>();
selectedDayList.add("Tue");
selectedDayList.add("Wed");
}
public List<String> getDayList()
{
return dayList;
}
public List<String> getSelectedDaylist()
{
return selectedDayList;
}
.xhtml page should be like this.
<p:selectCheckboxMenu id="trdays"
value="#{mybean.selectedDaylist}"
label="Select Days">
<f:selectItems value="#{mybean.dayList}" var="day"
itemValue="#{day.value}" itemLabel="#{day.name}"/>
</p:selectCheckboxMenu>
Good Luck!
Just add default values in the selectedDay list (or array) in init method (with #PostConstruct annotation). These values should have same value as corresponding itemValue attribute (in your case this is day.value).

Changing h:datatable cell color or style dynamically in JSF

I have a datatable where I want to change the color of a cell based on some analysis that is run on the contents. The table is linked to an array of Comment objects, which I have given a String cssClass that gets updated once the analysis is run. This is what I have tried plugging into the rowClasses property of the datatable. It's not working and I think the issue may be that I cannot access the variable created for each row of the datatable, from inside the datatable declaration.
Datatable code:
<h:dataTable value="#{post.comments}" var="comment" class="hs-table" rowClasses="#{comment.cssClass}" >
<h:column>
#{comment.name}
</h:column>
<h:column>
#{comment.email}
</h:column>
<h:column>
#{comment.msg}
</h:column>
</h:dataTable>
The Comment class:
public class Comment {
private String msg;
private String email;
private String name;
private Date date;
private String cssClass;
public Comment(){
cssClass = "normColumn";
}
epublic String getCssClass() {
return cssClass;
}
public void setCssClass(String cssClass) {
this.cssClass = cssClass;
}
}
Where the cssClass is updated in the managed bean:
if(tone>0)
c.setCssClass("commentPos");
else if(tone<0)
c.setCssClass("commentNeg");
The class never gets assigned. Am I doing something wrong, or is this simply not possible?
In the standard JSF <h:dataTable> component, the rowClasses attribute is unfortunately not evaluated on a per-row basis. It's evaluated on a per-table basis. Component libraries like Tomahawk and PrimeFaces however support the kind of attribute which you're looking for on their <t:dataTable> and <p:dataTable>.
With the standard JSF <h:dataTable> component you need to supply a comma-separated string of all row classes. This can look something like this:
public String getRowClasses() {
StringBuilder rowClasses = new StringBuilder();
for (Comment comment : comments) {
if (rowClasses.length() > 0) rowClasses.append(",");
rowClasses.append(comment.getCssClass());
}
return rowClasses.toString();
}
which is then to be referenced as
<h:dataTable ... rowClasses="#{post.rowClasses}">
See also:
<h:dataTable> tag documentation - lists all attributes and the accepted values

How to populate JSF inputText with initial value and submit control value to another property?

Let's say
I have
<h:dataTable var="s" value#{somebean.properties}>
<h:column>
<h:inputText initial=#{s.min} value=#{somebean.mintmp}/>
<h:commandButton action=#{filterbean.addProretryFilter(s.id, somebean.mintmp)} />
</h:column>
</h:dataTable>
"initail" attribute don't exit in inputText.
Is there any way to implement desired functionality?
You can bind your input text field to backing bean and initialize it in constructor or #PostConstruct and set the initial value.
#ManagedBean
public class Bean{
private HtmlInputText inputComponent = new HtmlInputText();
private String min = "5";
private String minData;
#PostConstruct
public void init(){
inputComponent.setValue(min);
}
//....get/set other logic
}
In view you can have
<h:inputText value="#{bean.minData}" binding="#{bean.inputComponent}"></h:inputText>
I think you need to rethink your design. Even without populating the default value, you have a problem. This pseudocode is roughly analogous to your logic:
//beans
SomeBean somebean = ...
DataModel model = ...
FilterBean filterbean = ...
//apply request values phase
for(int i=0; i<model.getRowCount(); i++) {
model.setRowIndex(i)
S s = model.getRowData()
//inputText's state is set to the submitted row state by the dataTable
Object submittedValue = inputText.getSubmittedValue()
somebean.mintmp = submittedValue
}
//invoke application phase
for(int i=0; i<model.getRowCount(); i++) {
model.setRowIndex(i)
S s = model.getRowData();
//commandButton's state is set to the submitted row state by the dataTable
if(commandButton.clicked()) {
filterbean.addProretryFilter(s.id, somebean.mintmp)
}
}
somebean will always be populated with the last row value.
See the JSF lifecycle and the DataModel for more details.
in your managed bean's getter you could return a default value. E.g.
private String mintmp=null;
public String getMintmp()
{
if(mintmp == null)
return "default min";
return mintmp;
}
Use primefaces! There's this really nice update attribute on buttons that update the components you want to refresh. It's magical.

Display all rows in tomahawk paginated, sortable datatable

I'm trying to create a paginated, sortable datatable using MyFaces. The sorting works fine; I can click on a column header and it will sort the data based on the column. Also the pagination works fine for the most part. The datatable will split itself appropriately with some number of items per page. In addition, I want the user to be able to change the number of items displayed per page. Again, this seems to be working until I want all of the items displayed on one page.
According to this reference (also here), if you set the "rows" attribute of t:datatable to "0", it will display the remaining rows in the table. However, when I try this, I get an exception that includes this message:
javax.faces.FacesException - You need to set a value to the 'rows' attribute of component 'myComponent'
I'm trying to set the number of items per page using an attribute in a backing bean. My t:datatable looks like this:
<t:dataTable id="myComponent" var="cur"
value="#{backingBean.list}" sortAscending="#{backingBean.ascending}"
sortColumn="#{backingBean.sortColumn}" sortable="true"
styleClass="myClass" rowClasses="oddRow,evenRow"
rows="#{backingBean.itemsPerPage}" preserveDataModel="false">
<!-- data here -->
</t:datatable>
Later, I have a t:dataScroller to control the pagination:
<t:dataScroller id="pageNavigation" for="myComponent"
paginatorActiveColumnStyle="font-weight:bold;"
renderFacetsIfSinglePage="false"
binding="#{backingBean.scroller}"
paginator="true" >
<!-- facets here -->
</t:dataScroller>
Then, I have a h:selectOneMenu to select the number of items per page
<h:selectOneMenu id="myScroller"
value="#{backingBean.itemsPerPage}"
required="true" onchange="this.form.submit();"
valueChangeListener="#{backingBean.updateItemsPerPage}">
<f:selectItems value="#{backingBean.itemsPerPageArray}" />
</h:selectOneMenu>
My backing bean looks something like this:
public class BackingBean {
private boolean ascending;
private Long itemsPerPage;
private String sortColumn;
private ArrayList<SelectItem> itemsPerPageArray;
private ArrayList<SomeObject> list; // data for table
private HtmlDataScroller scroller;
// constructors, getters, setters, and other stuff here
public void updateItemsPerPage(ValueChangeEvent valueChangeEvent) {
itemsPerPage = (Long) valueChangeEvent.getNewValue();
resetScrollerIndex();
}
private void resetScrollerIndex() {
if (scroller!=null && scroller.isPaginator())
scroller.getUIData().setFirst(0);
}
// called in constructor
private void constructItemsPerPageArray() {
itemsPerPageArray = new ArrayList<SelectItem>();
itemsPerPageArray.add(new SelectItem(new Long(10), "10"));
itemsPerPageArray.add(new SelectItem(new Long(50), "50"));
itemsPerPageArray.add(new SelectItem(new Long(100), "100"));
itemsPerPageArray.add(new SelectItem(new Long(0), "All"));
}
}
To sum up, when I select the "All" item from the h:selectOneMenu, I get the exception mentioned above. Hopefully, I've included an appropriate level of detail. Thanks!
Alright, I think I found the answer...
If I remove the first line from the updateItemsPerPage method, the problem is fixed. The method now looks like:
public void updateItemsPerPage(ValueChangeEvent valueChangeEvent) {
resetScrollerIndex();
}
It thought I had tried that...

jsf datatable row selection problem

I have a problem with selecting rows in the Primefaces Datatable. I use dynamic columns, so the standard row selection mechanism is not usable here, I implement checkbox selection myself.
To help, here's s simplified version of what I have in my xhtml:
<h:form>
<p:dataTable id="table"
var="result"
value="#{tableBean.results}">
<p:columns value="#{tableBean.columnNames}" var="column" columnIndexVar="colIndex">
<f:facet name="header">
#{column}
</f:facet>
<h:panelGroup rendered="#{colIndex==0}">
<h:outputLabel>#{rowIndex}</h:outputLabel>
<h:selectBooleanCheckbox value="#{tableBean.selectedRows[result[0]]}"/>
</h:panelGroup>
</p:columns>
</p:dataTable>
<h:commandButton value="Submit"></h:commandButton>
</h:form>
And here's what I have in the managed bean to select the checkboxes:
package testpackage;
import java.util.*;
import javax.faces.bean.*;
#ManagedBean
#SessionScoped
public class TableBean
{
private Map<String, Boolean> selectedRows = new HashMap<String, Boolean>();
List<List<String>> results = new LinkedList<List<String>>();
public TableBean()
{
List<String> row1 = new LinkedList<String>();
List<String> row2 = new LinkedList<String>();
row1.add("row1.ref");
row1.add("row1.id");
row1.add("row1.status");
row2.add("row2.ref");
row2.add("row2.id");
row2.add("row2.status");
results.add(row1);
results.add(row2);
//selectedRows.put("row2.ref", true);
}
public Map<String, Boolean> getSelectedRows()
{
return selectedRows;
}
public String submit()
{
List<List<String>> selectedResults = new ArrayList<List<String>>();
for (List<String> result : results)
{
if (selectedRows.get(result.get(0)) != null)
{
selectedResults.add(result);
selectedRows.remove(result.get(0));
}
}
return null;
}
public List<List<String>> getResults()
{
return results;
}
public List<String> getColumnNames()
{
List<String> columnNames = new LinkedList<String>();
columnNames.add("");
columnNames.add("REF");
columnNames.add("ID");
columnNames.add("STATUS");
return columnNames;
}
}
The getSelectedRows method works great, but the problem is that the setSelectedRows method is never called, so I don't know which checkboxes the user has selected. Maybe I overlook something very trivial, but cannot find the solution.
Any ideas on this? I would be very glad if you helped, or give any other row selection solution for the dynamic columns.
Thx in advance,
Levi
To me it looks you are rendering the wrong field in selectBooleanCheckBox.
You should be using variable or field from the result variable.
My solution:
In your situation you are rendering an object from List as a form of table row so if you want to make some changes and retrieve the status of that row then you should be using the variable from that object only.
I understand you are submitting the whole form and want to pickup all updated rows, in that case you will have to loop through the whole List and find all the rows which have been updated by checking the status in Request Handler(Action) bean.
Hope that helps.
The setter is never called for nested objects. You're the one who's responsible for creating them, not JSF. JSF just gets the nested object and then calls the setter on it (which is the put() method in case of a Map). You just need to determine the selected rows in the action method. Add an action method to the commandbutton:
<h:commandButton value="Submit" action="#{bean.submit}"></h:commandButton>
which is definied like follows (guessing/assuming that var="result" is in essence an Object[]):
public String submit() {
List<Object[]> selectedResults = new ArrayList<Object[]>();
for (Object[] result : results) {
if (selectedRows.get((String) result[0])) {
selectedResults.add(result);
selectedRows.remove(result[0]); // Reset.
}
}
// Now selectedResults contains all selected results.
}

Resources