add Dynamic Columns in addition to Static columns - jsf

I have a dataTable with some columns, which are not supposed to change.
<p:dataTable id="datatable" value="#{phase.tasks}" var="task">
<p:commandButton id="Testcycles"
action="#{testprojectProducer.doAddTestCycle(phase)}"
update=":formID:Tasks" title="add Test "
icon="ui-icon-plus fa fa-plus">
<!-- <p:ajax oncomplete="#{testprojectProducer.doAddTest(phase)}" update=":formID:Tasks"></p:ajax> -->
</p:commandButton>
<f:facet name="header">
<h:panelGrid>
<h:panelGroup columns="2"
style="display:block; text-align:right">
<p:column>
<f:facet name="header">
Task
</f:facet>
<h:outputText value="#{task.name}" id="description"
title="#{task.description}" />
<pe:tooltip for="description" value="#{task.description}" />
</p:column>
<p:column>
<f:facet name="header">
Tool
</f:facet>
<p:commandLink value="#{task.tool}" ajax="false"
action="#{fileLinkController.openFile()}" />
</p:column>
<p:column>
<f:facet name="header">
Result
</f:facet>
<h:outputText value="#{task.resultDocuments}" />
</p:column>
In addition to that, the user should have the possibility, to add new columns.
<p:columns value="#{task.listTest}"
var="sometest">
<f:facet name="header">
Test
</f:facet>
<p:inputText id="comment"
value="#{sometest.description}">
</p:inputText>
</p:columns>
</p:dataTable>
Here is the method where I add my new Tests.
public void doAddTest(Phase phase) {
for (Task task : phase.getTasks()) {
task.getListTest().add(new Test(task));
}
}
I'm aware of the fact that it is not possible to control the columns on a per-row basis, but I really need some advice, how I can keep my static columns and add the dynamic ones.
doAddTest() is invoked with a button, you can find under the Tag.
It is first of all important that the extra columns are displayed in the table and the user has the option to leave a comment. with this method, the content of the columns will be written into the database.
public String doSave() {
if (testprojectProducer.isAddMode()) {
testprojectAddEvent.fire(testprojectProducer.getTestproject());
}
} else {
testprojectUpdateEvent.fire(testprojectProducer.getTestproject());
}
return Pages.LIST_TESTPROJECT;
}

Related

Datatable does not update after rows removed

i have a datatable using the primefaces library, and while i have got all the functions working i have just one small issue, when i press the command link to remove the row, it works and the row gets removed but it does not automatically update the datatable to reflect this, ideally what i want is when the user presses the delete button it automatically updates the datatable to show this, how can i achieve this ?
here is the datatable
<p:dataTable id="UserTable"
widgetVar="usersTable"
value="#{userdetailsController.items}"
var="item"
emptyMessage="No details was found with given criteria">
<!--filteredValue="{userdetailsController.filteredUsers}" -->
<f:facet name="header">
<p:outputPanel>
<h:outputText value="Search all fields: " />
<p:inputText id="globalFilter" onkeyup="usersTable.filter()" style="width:150px" />
</p:outputPanel>
</f:facet>
<p:column id="USERID" filterBy="id"
headerText="i.d."
filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="#{bundle.ListUserdetailsTitle_id}"/>
</f:facet>
<h:outputText value="#{item.id}"/>
</p:column>
<!--There are four different match modes, "startsWith"(default), "endsWith", "contains" and "exact"-->
<p:column id="USERNAME" filterBy="username"
headerText="username."
filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="#{bundle.ListUserdetailsTitle_username}"/>
</f:facet>
<h:outputText value="#{item.username}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value=" "/>
</f:facet>
<p:commandLink action="#{userdetailsController.prepareView}" value="#{bundle.ListUserdetailsViewLink}"/>
<h:outputText value=" "/>
<div class="divider"/>
<p:commandLink action="#{userdetailsController.prepareEdit}" value="#{bundle.ListUserdetailsEditLink}"/>
<h:outputText value=" "/>
<div class="divider"/>
<p:commandLink action="#{userdetailsController.destroy}" value="#{bundle.ListUserdetailsDestroyLink}"/>
</p:column>
</p:dataTable>
You need to use the update attribute of the p:commandLink to tell PF you want to do the ajax request to obtain all data related to table UserTable like this:
<p:commandLink actionListener="#{userdetailsController.destroy}" value="#{bundle.ListUserdetailsDestroyLink}" ajax="true" update="UserTable"/>
Make sure to use actionListener as it is called before action atrib. A more detailed example is here
http://www.primefaces.org/showcase/ui/commandLink.jsf
Per the documentation, you need to make a call to Draw() after you remove a row.
var table = $('#example').DataTable();
$('#example tbody').on( 'click', 'img.icon-delete', function () {
table
.row( $(this).parents('tr') )
.remove()
.draw();
} );

Editor Calendar in Primefaces 3.5 cell value is lost?

is that I have a grid that dynamically genre, I mean I add empty rows to the grid, first thought to use primefaces in Cell Editor, so that the value is stored in the list of beans
List, works but the problem that I have is on the calendar, when I select one and is stored, it is stored in the list, I checked it does not execute the ajax event, you lose the value of the date.
<p:commandButton value="AƱadir dia" update="dataTable" actionListener="#{regDPNL.registrarNuevoDia}" />
<p:dataTable id="dataTable" var="dpnl" value="#{regDPNL.listdpnl}" paginatorPosition="top"
rows="20" rowIndexVar="rowIndex" editable="true" editMode="cell"
<p:ajax event="cellEdit" listener="#{regDPNL.onCellEdit}" />
<p:column width="25%">
<f:facet name="header">
<h:outputText value="NOMBRE" />
</f:facet>
<p:cellEditor>
<f:facet name="output"><p:inputText value="#{dpnl.nombre}" /></f:facet>
<f:facet name="input"><p:inputText value="#{dpnl.nombre}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column width="20%">
<f:facet name="header">
<h:outputText value="DESDE" />
</f:facet>
<p:cellEditor>
<f:facet name="output"><p:inputText value="#{dpnl.fechaDesde}" /></f:facet>
<f:facet name="input"><p:calendar value="#{dpnl.fechaDesde}" pattern="dd/MM/yyyy" /></f:facet>
</p:cellEditor>
</p:column>
<p:column width="20%">
<f:facet name="header">
<h:outputText value="HASTA" />
</f:facet>
<p:cellEditor>
<f:facet name="output"><p:inputText value="#{dpnl.fechaHasta}" /></f:facet>
<f:facet name="input"><p:calendar value="#{dpnl.fechaHasta}" pattern="dd/MM/yyyy" /></f:facet>
</p:cellEditor>
</p:column>
<p:column width="5%">
<f:facet name="header">
<h:outputText value="ELIMINAR" />
</f:facet>
<p:commandButton icon="ui-icon-editar" title="Delete Periodo" style="background:#fff">
</p:commandButton>
</p:column>
</p:dataTable>
Java code:
private List<DetallePeriodoBean> listdpnl = new PeriodoNoLaborable();
private DetallePeriodoBean detallePeriodoNoLaborable = new ArrayList<DetallePeriodoBean>();
public void registrarNuevoDia() {
detallePeriodoNoLaborable = new DetallePeriodoBean();
this.listdpnl.add(detallePeriodoNoLaborable);
}
public void onCellEdit(CellEditEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
if(newValue != null && !newValue.equals(oldValue)) {
System.out.println("==> Old: " + oldValue + ", New:" + newValue);
}
}
http://s2.subirimagenes.com/imagen/previo/thump_8690487captura.png
I have faced this problem.
The solution is very simple (after a lot of testing and error)
You must add id attribute to your tag,
for instance:
<p:calendar id="date_selector" value="#{dpnl.fechaHasta}" pattern="dd/MM/yyyy" />
At the facet named output use the tag h:outputText instead of p:inputText
make sure you use java.util.date for your date fields(i.e fechaDesde etc) in your bean.

p:dialog shows empty values when when I go to the next page of the p:datatable using paginator

I have been using onEdit in the p:datatable and it works fine.My data table has a pagintor and shows 5 records per page.so when I click on the onEdit in the first page event.getObject gets the changed value in the bean.Now when I go the next page the event.getObject does not work and returns the old value only.
Same with the dialog box.In the table I have a link when clicked opens a dialog box in whcih I am populating few fields with the values from the row selected.It works fine in the first page and When I navigate to other pages gives empty values.
Here is my jsf code:
<p:dataTable value="#{mybean.userList}"
var="item"
id="dataTab"
widgetVar="usersTable"
tableStyleClass="data" paginator="true" rows="5"
filteredValue="#{userController.filteredUsers}"
editable="true"
rowKey="#{item}"
>
<p:ajax event="rowEdit" listener="#{mybean.onEdit}" update=":userForm:growl" />
<p:ajax event="rowEditCancel" listener="#{mybean.onCancel}" update=":userForm:growl" />
<f:facet name="header">
<p:outputPanel>
<h:outputText value="Search all fields:" />
<p:inputText id="globalFilter" onkeyup="('usersTable').filter()" style="width:150px" />
</p:outputPanel>
</f:facet>
<p:column sortBy="#{item.firstName}" filterBy="#{item.firstName}"
filterMatchMode="startsWith">
<p:cellEditor>
<f:facet name="header">
<h:outputText value="First Name" />
</f:facet>
<f:facet name="output">
<h:outputText value="#{item.firstName}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{item.firstName}" style="width:100%"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column sortBy="#{item.lastName}" filterBy="#{item.lastName}" filterMatchMode="startsWith">
<p:cellEditor>
<f:facet name="header">
<h:outputText value="Last Name" />
</f:facet>
<p:column headerText="Update" style="width:6%">
<p:rowEditor />
</p:column>
</p:dataTable>
<p:dialog id="modalDialog"
header="Delete User?"
modal="true"
resizable="false"
draggable="false"
widgetVar="delUserConf"
>
<h:panelGrid id="display" columns="2" style="width: 150px;">
<h:outputLabel value="Firat Name" style="font-weight: bold"/>
<h:outputText value="Last Name" style="border: none"/>
</h:panelGrid>
</p:dialog>
Here is the code in my bean for the edit functionality:
public String onEdit(RowEditEvent event)
{
User user=(User)event.getObject());
user.getFirstName();
}
I did not add the link that I have in my form which pops up the dialog.Also I read that this might be because of Lazy loading and I am not sure about it.I am populating my table with a list and not the model.
Could you let me know what should I do to make it work?
maybe you should switch to SessionBean scope because the scope view is released when there are changes in the view. Try SessionBean. Also you can call from view scope any sessionbean like this, where controladorMB is a sessionbean
public void detallesPersona() {
try {
FacesContext ctx = FacesContext.getCurrentInstance();
ValueExpression vex = ctx.getApplication().getExpressionFactory().createValueExpression(ctx.getELContext(), "#{controladorMB}", ControladorMB.class);
ControladorMB gMB = (ControladorMB) vex.getValue(ctx.getELContext());
this.setSelectedPersona(gMB.getPersonaBean().detallesPersonas(this.selectedPersona.getIdPersona()));
} catch (Exception e) {
JsfUtil.addErrorMessage(e, "Error: " + e.getMessage());
}
}

Row Editor does not update value object's fields displaying via "columns" tag

I try to devise flexible table containing dynamic columns for CRUD operations.
I use p:columns component to make dynamic columns, but those columns do not change value when I try to update it.
<h:form id="form">
<p:dataTable id="dataTable"
var="item"
value="#{tableEditorController.items}"
editable="true"
paginator="true"
rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15">
<p:ajax event="rowEdit" listener="#{tableEditorController.onEdit}" />
<f:facet name="header">
#{tableEditorController.tableName}
</f:facet>
<p:columns value="#{tableEditorController.columns}"
var="column"
columnIndexVar="colIndex">
<f:facet name="header">#{column.header}</f:facet>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{item[column.property]}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{item[column.property]}" style="width:100%"/>
</f:facet>
</p:cellEditor>
</p:columns>
<p:column>
<f:facet name="header">test</f:facet>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{item['activityName']}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{item['activityName']}" style="width:100%"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Edit" style="width:6%">
<p:rowEditor />
</p:column>
</p:dataTable>
</h:form>
When I click on link in "Edit" column all the cells in selected row turn into text input fields.
If I edit a value in the "test" column and save, it saves properly as I expect.
But if I edit value using an input field in column which was generated by p:columns tag and try to save, it does not save changes.
I monitored http requests by Chrome Tools. The requests contain changed value in every case.
I ran my code under debugger and a RowEditEvent contains new data in first case and unchanged data object in second.
I cannot realize my mistake and only thing left I doubt is square braces notation.
I checked square braces notation using in "test" column and it works fine.
I use JSF 2.1.3 and Primefaces 3.3
Controller class is following:
#ManagedBean
#RequestScoped
public class TableEditorController {
private static List activityList;
static{
activityList = new ArrayList();
ActivityType at = new ActivityTypeImpl();
at.setActivityId(1L);
at.setActivityName("FirstActivity");
activityList.add(at);
at = new ActivityTypeImpl();
at.setActivityId(2L);
at.setActivityName("Second Activity");
activityList.add(at);
}
public void onEdit(RowEditEvent event){
FacesMessage msg = new FacesMessage("Row Edited");
msg.setDetail(event.toString() + event.getObject());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public void delete(Object id){
}
public List getItems(){
return activityList;
}
public String getTableName(){
return "Name of the Table";
}
public List<ColumnModel> getColumns(){
ColumnModel m1 = new ColumnModel("ID", "activityId");
ColumnModel m2 = new ColumnModel("Activity", "activityName");
return Arrays.asList(m1, m2);
}
}
I will appreciate any suggestion and/or idea.
I have found a way around p:columns. I replaced it with following code.
<c:forEach items="#{tableEditorController.columns}" var="column">
<p:column>
<f:facet name="header">#{column.header}</f:facet>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{item[column.property]}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{item[column.property]}" style="width:100%" disabled="#{not column.editable}"/>
</f:facet>
</p:cellEditor>
</p:column>
</c:forEach>
It works but I had to add JSTL library to project dependencies.

Binding a subtable inside a datatable with JSF

My product is using JSF with Primefaces 2.2. What I need is to process a sub-datatable inside another datatable. The code is as below.
<h:form>
<p:dataTable id="myInvoiceTable"
value="#{globalBean.invoices}" var="invoice">
<p:column>
<f:facet name="header">
<h:outputText value="Bill ID" />
</f:facet>
<h:outputText value="#{invoice.billId}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Item" />
</f:facet>
<h:outputText value="#{invoice.item}" />
</p:column>
<p:rowExpansion>
<h:selectOneMenu id="reasons" value="#{invoiceAction.reason}">
<f:selectItem itemLabel="Reason 1" itemValue="Reason 1"></f:selectItem>
<f:selectItem itemLabel="Reason 2" itemValue="Reason 2"></f:selectItem>
</h:selectOneMenu>
<p:inputText id="activity_amount" value="#{invoiceAction.activity_amount}"/>
<p:commandButton value="PROCESS" action="invoice_process" update="actions_table">
</p:commandButton>
<p:dataTable id="actions_table" value="#{invoice.actions}" var="invAction">
<p:column>
<h:outputText value="#{invAction.reason}" />
</p:column>
<p:column>
<h:outputText value="#{invAction.activity_amount}" />
</p:column>
</p:dataTable>
</p:rowExpansion>
</p:dataTable>
Here's my bean.
public class Invoice {
private int billId;
private String item;
private List<InvoiceAction> actions;
// Getter & setter here
}
public class InvoiceAction {
private String reason;
private double activity_amount;
private int billId;
// Getter & setter here;
}
But when the HTML is generated, it's not processed as desired. Only the select menu in the last row of datatable can receive the data chosen by user, others can't. Because all select menus in all rows are using the same object (#{invoiceAction}), and the bean just gets the value of the last component in the page. I knew the root cause but I don't know how to solve it. How to let they submit in the specified row?
First of all, I think your Invoice and InvoiceAction classes look just like normal Java objects. I feel that they should not be Managed Bean.
Besides, you're right that your #{invoiceAction} is not correctly binded to one of the actions in List<InvoiceAction> actions. Since you are using nested <p:dataTable>, I think you can take advantage of <p:cellEditor>. It would be something like this:
<p:rowExpansion>
<p:dataTable id="actions_table" value="#{invoice.actions}" var="invAction">
<p:column>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{invAction.reason}" />
</f:facet>
<f:facet name="input">
<h:selectOneMenu id="reasons" value="#{invoiceAction.reason}">
<f:selectItem itemLabel="Reason 1" itemValue="Reason 1" />
<f:selectItem itemLabel="Reason 2" itemValue="Reason 2" />
</h:selectOneMenu>
</f:facet>
</p:cellEditor>
</p:column>
<p:column>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{invAction.activity_amount}" />
</f:facet>
<f:facet name="input">
<p:inputText id="activity_amount" value="#{invoiceAction.activity_amount}" />
</f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
<p:commandButton value="PROCESS" action="invoice_process" update="actions_table" />
</p:rowExpansion>

Resources