I have two datatables in one jsf page and both are having two different managed beans.
//master table
<p:dataTable id="dataTable" var="req" lazy="true"
value="#{emp.lazyModel}" paginator="true" rows="10"
selection="#{emp.selectedRequest}">
<p:ajax event="rowSelectRadio" listener="#{emp.onRowSelect}" />
<p:column selectionMode=">
<h:outputText value="#{req.empNo}" />
</p:column>
// detail table
<p:dataTable id="Det" var="det" lazy="true"
value="#{dept.lazyModel}" paginator="true" rows="1">
<p:column>
<f:facet name="header">
<h:outputText value="DeptNo" />
</f:facet>
<h:outputText value="#{det.deptNo}" />
</p:column>
Managed beans respectively
// Master table managed Bean
#Named("emp")
#ViewAccessScoped
public class EmployeeManagedBean implements Serializable {
#PostConstruct
public void init() {
initTable();
}
// Detail table managed Bean
#Named("dept")
#ViewAccessScoped
public class DepartmentManagedBean implements Serializable {
#PostConstruct
public void init() {
initTable();
}
initTable() is a method which populates LazyModel for both managed beans
When I select a row in master datatable, I am able to get selected row value in managed bean for first datatable which is EmployeeManagedBean
My question is what is the best approach to populate the second datatable by passing the selected row value of first datatable to second managed bean and thus populate the second datatable? The triggering point to display values in second datable should be based on the selection of a row in first datatable.
Any help is highly appreciable.
Thanks
I am new with this all, but I try doing like this:
pass selected row to second bean (DepartmentManagedBean)
took departments according to selected row
update second datatable, using p:ajax attribute update
Related
First my apology. I can't state the question well/clearly enough.
I have a web application built upon jsf 2.x + spring data jpa + hibernate frameworks. There is an editable dataTable in where you could add/remove/update a row. When you click "Add Row" button new instance of car object (entity domain model) is added to a list then when you press save button, it is persisted to database just fine. Very straight forward.
This is foo.xhtml page.
<p:panelGrid>
<p:row>
<p:column>....</p:column>
<p:column>
<h:form id="fooForm">
<p:dataTable id="fooTable" var="c" value="#{fooBean.cars}"
editable="true" rows="10" paginator="true">
......
<f:facet name="footer">
<p:commandButton value="Add Row" actionListener="#{fooBean.addCar}"
update="fooTable" process="#this" />
</f:facet>
</p:dataTable>
<p:commandButton value="Save" action="#{fooBean.save}" update="fooTable" process="#this"/>
</h:form>
</p:column>
</p:row>
</p:panelGrid>
This is bean.
#ManaagedBean
#Viewscoped
public FooBean class implements Serializable {
.....
public void addCar() {
....
}
public void save() {
// use spring abstraction layer to persist entity object
}
Issue I ran into:
However the trouble I am having is once I decided to remove "Save" button from foo.xhtml and
<p:commandButton value="Save" action="#{fooBean.save}" .../>
move save() method inside of addCar() method from the FooBean
public void addCar() {
....
save();
}
The following exception is thrown when I click "Add Row" button and I've been trying to understand why but failed so far.
SEVERE: org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient valu
e: com.yoon.model.Car.age; nested exception is org.hibernate.PropertyValueException: not
-null property references a null or transient value: com.yoon.model.Car.age
Update with self explanatory answer
It turns out to be a programmatic error of mine. When I click on "Add Row" from a table, it should handle only adding an instance of car model with its fields fully entered and add the object to a list. However when I relocated save method inside of addCar method that gets triggered by clicking "Add Row" button, empty car object in where fields are all NULL pushed by hibernate to DB before it grants a chance a user to fill out the required fields. In the table, those fields CAN NOT BE NULLABLE so in turn aforementioned exception was thrown.
I was able to achieve my initial objective of clicking "Add Row" button would capture user input and persist an instance of car to database.
Removing following button
<p:commandButton value="Save" action="#{fooBean.save}" />
Having ajax component.
<p:dataTable ....>
<p:ajax event="rowEdit" listener="#{fooBean.save}" />
....
</p:dataTable>
How do I do to get the selected data that dataTable? I use this way because it is the "Edit" of a register.
<p:dataTable id="dataTable" var="valor" style="width:100%; text-align:center"
value="#{beanMensagemXContato.dataModelMsg}"
selection="#{beanMensagemXContato.selectedMensagemAssociada}"
paginator="true" rows="6" >
<f:facet name="header">
Mensagens
</f:facet>
<p:column style="width:5%">
<p:selectBooleanCheckbox value="#{valor.associada}" >
<p:ajax process="#form" event="valueChange" listener="# {beanMensagemXContato.adicionarMensagemContato}">
<f:param name="messageSelecionada" value="#{beanMensagemXContato.msgAssociada}" />
</p:ajax>
</p:selectBooleanCheckbox>
</p:column>
...
</p:dataTable>
I would pick the data by Bean as the event SelectEvent:
public void adicionarMensagemContato (SelectEvent event){
Mensagem mensagem = ((MensagemAssociada) event.getObject()).getMensagem();
MensagemAssociada mensagemAssociada = (MensagemAssociada) event.getObject();
...
}
But I could not take the data with the event ValueChange. I've tried with SelectEvent by tag selectionMode = "multiple", managed to get the data selected at that moment, the data previously selected and read from the database does not appear, use only when the way listed above in xhtml.
Already I appreciate the help.
The selection is stored in your bean field:
selection="#{beanMensagemXContato.selectedMensagemAssociada}"
If the adicionarMensagemContato method is located in the same bean, you can access you selection without a problem:
public void adicionarMensagemContato (SelectEvent event){
doSomething(this.selectedMensagemAssociada);
}
Another way is to use f:setPropertyActionListener - it allows you to store element from current row in a bean field (example below shows how to access current element in action invoked by button click):
<p:dataTable var="objectFromCurrentRow" ...>
...
<p:column ...>
<p:button ... action=#{beanMensagemXContato.performAnActionOnCurrentElement} ...>
<f:setPropertyActionListener value="#{objectFromCurrentRow}" target="#{beanMensagemXContato.selectedMensagemAssociada}" />
</p:button>
...
<h:dataTable value="#{studentBean2.studentList}" var="student">
<h:column>
<f:facet name="header">
<h:outputText value="STUDENT-ID" />
</f:facet>
<h:outputText value="#{student.studentId}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="STUDENT-NAME" />
</f:facet>
<h:inputText value="#{student.studentName}" />
</h:column>
.........
.........
</h:dataTable>
<h:commandButton type="submit" action="#{studentBean2.action}" value="ENTER" />
As from the above code, datatable values can be edited in <h:inputText> field and submitted. Those edited values are seen in action() method of bean StudentBean2.
As I followed the log, it showed that when I submit the page in the phase "Apply Request Values" the getStudentList() method is called. In this method I do the JDBC call to fetch students from the Database and set the newly fetched studentlist.
But in the "Invoke Application" phase, in method action() I get the edited data in the list which I have submitted. How exactly does this happen?
JSF has set them for you during the update model values phase. During this phase, the processUpdates() method of every component will be invoked. In case of the <h:dataTable> it's the UIData#processUpdates(). For every row it will then invoke the same method of the input component, which is in your case UIInput#processUpdates().
Basically:
get data model of UIData; // studentList = studentBean2.getStudentList()
for (every row of data model) {
get the current row item by index; // student = studentList.get(index)
for (every child UIInput component of UIData) {
set its value; // student.setStudentName(value)
}
}
Unrelated to the concrete problem, doing the JDBC call inside the getter method is a bad idea. The getter method will be called more than once during bean's life, so the JDBC call will be unnecessarily made too many times. You should make the JDBC call in bean's (post)constructor instead. See also Why JSF calls getters multiple times.
I have a simple Richfaces 4 <rich:dataTable> with some <rich:column>s.
Now I want if I press on one row, that below the table the ID of the row should be displayed.
Here is what I did so far:
<rich:dataTable value="#{placeholder_control.lichtList}" var="licht" width="100%" id="lichtListe" columns="2">
<rich:column>
<f:facet name="header">
<h:outputText value="Beschreibung" />
</f:facet>
<h:outputText value="#{licht['beschreibung'].stringValue}" width="20" />
<a4j:ajax immediate="true" event="onclick" render="testingID" listener="#{placeholder_control.selectActiveLight}">
<f:attribute name="rowKey" value="#{licht['id'].stringValue}" />
</a4j:ajax>
</rich:column>
...
...
<h:outputText value="This is the id : #{placeholder_control.selectedLight}" id="testingID"></h:outputText>
The managed bean placeholder_control looks like this
#ManagedBean (name="placeholder_control")
#SessionScoped
public class ControlPlaceholder {
public void selectActiveLight(ActionEvent evt) {
String selectedRow = (String) evt.getComponent().getAttributes().get("rowKey");
System.out.println("Selected Light : " + selectedRow);
setSelectedLight(selectedRow);
}
Everything will be rendered correctly, but if I click on the row (on this column), nothing happens. I also tried to put a non existing method (on purpose) to the listener. I hoped that I get an error message but nothing happend.
If I look at the HTML source code, there is nothing with onclick at that <td> element.
Anyone has an idea?
hi friend take a look to rich:extended datatable, i used it to do a task that meet your requirements.
here is the showcase for richfaces 4 and explains the use of extended datatable: http://richfaces-showcase.appspot.com/richfaces/component-sample.jsf?demo=extendedDataTable&sample=exTableSelection&skin=blueSky
cheers
I have a problem using HtmlDataTable for viewing data from database.
When I create component, the table has sometimes (not always) twice number of columns.
It is shown correctly and after several refreshes (without move in dtb or something) there is for example 6 columns instead of 3 and application (sometimes) become unstable.
Since this time I can't work with table because it reports "duplicate Id for a component"..
Simple example (source: http://balusc.blogspot.com/2006/06/using-datatables.html):
<h:form id="bde">
<h:dataTable id="tbl"
binding="#{myBDE.dataTable}"
value="#{myBDE.dataList}"
var="bdeItem">
<h:column>
<f:facet name="header">
<h:outputText value="S" />
</f:facet>
<h:outputText value="#{bdeItem.s}" rendered="#{!myBDE.editModeRow}"/>
<h:inputText value="#{bdeItem.s}" rendered="#{myBDE.editModeRow}" required="true" size="3"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="ID" />
</f:facet>
<h:outputText value="#{bdeItem.id}"/>
</h:column>
</h:dataTable>
</h:form>
And java.class
protected HtmlDataTable dataTable;
public void setDataTable(HtmlDataTable dataTable)
{
this.dataTable = dataTable;
}
public HtmlDataTable getDataTable()
{
if (dataTable == null)
{
dataTable = new HtmlDataTable();
dataTable.setRows(DEFAULT_TABLE_ROWS);
}
return dataTable;
}
And the Error message:
javax.servlet.ServletException: Component ID j_idt92:bde:tbl:j_idt129 has already been found in the view.
javax.faces.webapp.FacesServlet.service(FacesServlet.java:422)
root cause
java.lang.IllegalStateException: Component ID j_idt92:bde2:tbl:j_idt129 has already been found in the view.
com.sun.faces.util.Util.checkIdUniqueness(Util.java:821)
com.sun.faces.util.Util.checkIdUniqueness(Util.java:805)
com.sun.faces.util.Util.checkIdUniqueness(Util.java:805)
com.sun.faces.util.Util.checkIdUniqueness(Util.java:805)
com.sun.faces.util.Util.checkIdUniqueness(Util.java:805)
com.sun.faces.util.Util.checkIdUniqueness(Util.java:805)
com.sun.faces.application.view.StateManagementStrategyImpl.saveView(StateManagementStrategyImpl.java:144)
com.sun.faces.application.StateManagerImpl.saveView(StateManagerImpl.java:133)
com.sun.faces.application.view.WriteBehindStateWriter.flushToWriter(WriteBehindStateWriter.java:225)
com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:418)
com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:410)
Followed by tree of components.
I thing there's nothing duplicated in code, but dataTable create a new columns and after that it's really duplicated
I have two working similar modules, and the third doesn´t work.
Have you ever met this kind of problem?
Thanks for advice
This can happen if the bean is session scoped instead of request scoped and you're sharing this bean among multiple views. Best is to keep the bean to which the component is been bound in the request scope.
As an alternative, you can also use DataModel as value instead of binding the table to HtmlDataTable if the functional requirement is to get the currently selected row.