Primefaces CommandLink only works the first time it's clicked - ajax

I have a datatable, and have links that allow the user to insert a row directly below the current row. This should then update the numbering.
It works perfectly once, creating a new row, populating the number and adding one to the numbering for all rows below.
If I click anything else though, it seems as though the ajax request completes but nothing happens.
You will see that I am using the #{table} variable to get the row index of the UIData element. I have tried using process="#form" and process="#this" in the commandLink, but to no avail sadly. Likewise, my method was returning void so I set it to return a null String, but the same result occurred.
XHTML
<h:form id="feForm">
<p:dataTable value="#{fichaExpandidaBean.feFlujoNormalList}" binding="#{table}" var="fn">
<p:column headerText="Paso:">
<h:outputText value="#{fn.orden}-"/>
</p:column>
<p:column headerText="Descripcion:">
<h:inputText value="#{fn.descripcion}" style="width:98%;"/>
</p:column>
<p:column headerText="Acciones">
<p:commandLink style="margin: 5px;" action="#{fichaExpandidaBean.agregarFilaFlujoNormal(table.rowIndex)}" update="#form">
<h:graphicImage title="Agregar fila abajo." value="/resources/imagenes/agregarFila.png" alt="AgregarFila"/>
</p:commandLink>
</p:column>
</p:dataTable>
</h:form>
Bean:
#Named(value = "fichaExpandidaBean")
#ConversationScoped
public class FichaExpandidaBean implements Serializable {
#Inject
private Conversation conversation;
...etc...
public String agregarFilaFlujoNormal(int row){
FeFlujonormal fn = new FeFlujonormal();
fn.setOrden(row + 2);
feFlujoNormalList.add(row + 1, fn);
for(int i = row + 2; i < feFlujoNormalList.size(); i++){
FeFlujonormal feTemp = feFlujoNormalList.get(i);
feTemp.setOrden(feTemp.getOrden()+1);
}
return null;
}
EDIT: I don't think it's a Primefaces issue, I get the same result with the following code:
<h:dataTable value="#{fichaExpandidaBean.feFlujoNormalList}" binding="#{table}" var="fn">
<h:column>
<f:facet name="header">Paso</f:facet>
<h:outputText value="#{fn.orden}-"/>
</h:column>
<h:column>
<f:facet name="header">Descripcion</f:facet>
<h:inputText value="#{fn.descripcion}" style="width:98%;"/>
</h:column>
<h:column>
<f:facet name="header">Acciones</f:facet>
<h:commandLink style="margin: 5px;" action="#{fichaExpandidaBean.agregarFilaFlujoNormal(table.rowIndex)}">
<f:ajax render="#form"/>
<h:graphicImage title="Agregar fila abajo." value="/resources/imagenes/agregarFila.png" alt="AgregarFila"/>
</h:commandLink>
</h:column>
</h:dataTable>

Related

Primefaces - Datatable not updated when value change

I'm working with primefaces and I'm having a problem when using p:dataTable.
<p:dataTable id="dataTable" var="label" value="#{myBean.labels}" editable="true" editMode="cell" widgetVar="dataTable" style="width: 350px;">
<p:ajax event="cellEdit" listener="#{myBean.onEdit}" update=":messages" />
<p:column headerText="Column 1" width="20">
<h:outputText id="current" value="#{myBean.currentTimeMillis}" />
</p:column>
<p:column headerText="Column 2" width="150">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{label.name}"/>
</f:facet>
<f:facet name="input">
<h:inputText value="#{label.name}"/>
</f:facet>
</p:column>
</p:dataTable>
I would like that when I update the value of the second column of a row, then the value of the first column of this row is updated with a new value (currentTimeMillis).
public void public void onEdit(CellEditEvent event)
{
UIData table = (UIData) event.getComponent();
String updateClientId = table.getClientId() + ":" + table.getRowIndex() + ":current";
FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add(updateClientId);
}
Although this method in being invoked the first column is not being updated. Why? It is not working only in Firefox. It works on IE and Chrome.
Thanks in advance

Unable to update p:datatable cell after ajax call on another cell's cellEdit event

In my cell edit event in my backing bean, if the cell value is changed I want to update the value of another column as well of the datatable. The value is getting correctly set in my list object but is not getting reflected in my datatable. I tried updating using the datatable using RequestContext as well, but still the list is not getting refreshed. What am I doing wrong? Should I call any row event for this change?
Code snippet :
Bean
#Named("editView")
#ViewScoped
public class EditTableView implements Serializable {
private List<Cars> carList;
private List<String> brands;
#PostConstruct
public void init() {
brands = new ArrayList<String>();
brands.add("BMW");
brands.add( "Mercedes");
brands.add("Volvo");
brands.add("Audi");
brands.add("Renault");
brands.add("Fiat");
brands.add("Volkswagen");
brands.add("Honda");
brands.add("Jaguar");
brands.add( "Ford");
brands.add("Maruti Suzuki");
carList = new ArrayList<Cars>();
modifiedList = new ArrayList<Cars>();
Cars car =new Cars();
car.setCarId(1);
car.setBrand("BMW");
car.setColor("Grey");
car.setModelNumber("2323");
car.setSelfDriven("Y");
car.setYear("1980");
car.setStatus("");
carList.add(car);
}
public void onCellEdit(CellEditEvent event) {
int rowIndex = event.getRowIndex();
Cars car = null;
LOGGER.info("Car Edited"+rowIndex);
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
DataTable carTable = (DataTable) event.getSource();
String index = carTable.getClientId(FacesContext.getCurrentInstance());
LOGGER.info(index);
if(newValue != null && !newValue.equals(oldValue)) {
LOGGER.info("Cell Changed Old: " + oldValue + ", New:" + newValue);
car=carList.get(rowIndex);
carList.get(event.getRowIndex()).setStatus("Changed");
modifiedList.add(car);
}
}
}
xhtml
<h:form id="cellEditForm">
<p:dataTable id="cars" var="car" value="#{editView.carList}"
editable="true" editMode="cell" widgetVar="cellCars">
<f:facet name="header">Cell Editing</f:facet>
<p:ajax event="cellEdit" listener="#{editView.onCellEdit}"
update=":cellEditForm:cars" />
<p:column headerText="Id">
#{car.carId}
</p:column>
<p:column headerText="Model Name" style="background-color:yellow">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{car.modelNumber}" />
</f:facet>
<f:facet name="input">
<p:inputText id="modelInput" value="#{car.modelNumber}"
style="width:96%" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Year" style="background-color:yellow">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{car.year}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{car.year}" style="width:96%" label="Year" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Brand" style="background-color:yellow">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{car.brand}" />
</f:facet>
<f:facet name="input">
<h:selectOneMenu value="#{car.brand}" style="width:100%">
<f:selectItems value="#{editView.brands}" var="man"
itemLabel="#{man}" itemValue="#{man}" />
</h:selectOneMenu>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Self Driven" style="background-color:yellow">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{car.selfDriven}" />
</f:facet>
<f:facet name="input">
<p:inplace>
<p:inputText value="#{car.selfDriven}" />
</p:inplace>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Color" style="background-color:yellow">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{car.color}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{car.color}" style="width:96%" label="Color" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column>
<h:outputText value="#{car.status}" id="statusLabel"></h:outputText>
</p:column>
</p:dataTable>
</h:form>
I used jquery eventually. Got the index of the updated row and called jquery function from my bean.
RequestContext requestContext = RequestContext.getCurrentInstance();
String call = "updateCell(" + event.getRowIndex() + ")";
requestContext.execute(call);
Jquery code
function updateCell(i) {
var index = "cellEditForm:cars:"+i+":statusLabel";
document.getElementById(index).innerHTML="Changed";
}
OmniFaces has a great util for this, called 'Ajax'
A StackOverflow post about this shows how to use it: How to use OmniFaces Ajax.updateColumn() or Ajax.updateRow() via p:ajax
Update form not table or put table in panel and update panel.
to be safe
<h:form id="cellEditForm">
<p:panel id="something" styleclass="pero">
<p:dataTable id="cars
update="#(.pero)"
be sure to put id on panel because class update will search for that id and use it. This solution is because i don't know rest of the code and it is one that will work on any code.

Update single row in JSF / Primefaces datatable using AJAX

How could I update a single row in a p:datatable when using AJAX?
I don't want to update the whole datatable because it has a lot of rows and it's going to take some time..
My layout:
<h:form id="visitForm">
<p:dataTable id="visitTable" var="visit" value="#{visitBean.findAllVisits()}">
<p:column headerText="${msgs['email']}"
<h:outputText value="#{visit.contactDetail.email}"/>
</p:column>
<p:column headerText="${msgs['clearance']}" id="clearance">
<p:commandButton value="${msgs['clearance.ok']}" actionListener="#{visitBean.makeClearanceNotOk(visit)}"/>
</p:column>
</p:dataTable>
</h:form>
I've tried out some things like update = "clearance" etc but it doesn't seem to work.
I'm using JSF 2.1 and Primefaces 5.2
You can use #row(n) search expression which does just that - it updates the nth row in a table. In order to update the current row, you need to pass row index as an argument. Set rowIndexVar="rowIdx" attribute on <p:dataTable> and then:
<p:commandButton ... update="#form:visitTable:#row(#{rowIdx})" />
Not sure if I'm late for the party but let me give my 5 cents on this subject on how to update content of a row using just plain ajax features from PrimeFaces.
1) Partial update: My first approach to update something in a specific row using PF is not exactly update the whole row, but update the regions of interest inside the row. This can be achieved by just defining the holding panels and updating them. For example:
<h:form id="testForm">
<p:dataTable id="myEntityTable" var="myEntity" value="#{myController.allEntities}">
<p:column headerText="id">
<h:outputText value="#{myEntity.id}"/>
</p:column>
<p:column headerText="last update">
<p:outputPanel id="lastUpdatePanel">
<h:outputText value="#{myEntity.lastUpdate}">
<f:convertDateTime pattern="HH:mm:ss" type="date" />
</h:outputText>
</p:outputPanel>
</p:column>
<p:column headerText="counter">
<p:outputPanel id="counterPanel">
<h:outputText value="#{myEntity.counter}"/>
</p:outputPanel>
</p:column>
<p:column headerText="increment">
<p:commandButton value="+"
actionListener="#{myController.increment(myEntity)}"
update="counterPanel, lastUpdatePanel"/>
</p:column>
</p:dataTable>
</h:form>
The trick is to update the target panels (in this example the fragment update="counterPanel, lastUpdatePanel"). This results in something like the following image:
2) Actually updating the row: Very often the previous approach works fine enough. However, if it is really needed to update the row one can follow the advice given in one of the previous answers and use the #row keyword:
<h:form id="testForm">
<p:dataTable id="myEntityTable" var="myEntity" value="#{myController.allEntities}" rowIndexVar="rowIndex">
<p:column headerText="id">
<h:outputText value="#{myEntity.id}"/>
</p:column>
<p:column headerText="last update 1">
<p:outputPanel>
<h:outputText value="#{myEntity.lastUpdate}">
<f:convertDateTime pattern="HH:mm:ss" type="date" />
</h:outputText>
</p:outputPanel>
</p:column>
<p:column headerText="last update 2">
<h:outputText value="#{myEntity.lastUpdate}">
<f:convertDateTime pattern="HH:mm:ss" type="date" />
</h:outputText>
</p:column>
<p:column headerText="counter">
<p:outputPanel>
<h:outputText value="#{myEntity.counter}"/>
</p:outputPanel>
</p:column>
<p:column headerText="increment">
<p:commandButton value="+"
actionListener="#{myController.increment(myEntity)}"
update="#form:myEntityTable:#row(#{rowIndex})"/>
</p:column>
</p:dataTable>
</h:form>
The trick is to hold each content from the columns inside a p:outputPanel and let update="#form:myEntityTable:#row(#{rowIndex})" make the job. I consciously leave the "last update 2" column without an outputPanel in order to illustrate this point:
Hence, whereas the columns "last update 1" and "counter" actually update after a click in "+" the "last update 2" column keeps unchanged. So, if you need to update a content, wrap up it with an outputPanel. It is noteworthy as well that the outputPanels holding each column content don't need an explicit id (you can add one if you want).
In the sake of completeness, in these examples I have used PF 6.2. The backbean is pretty straightforward:
package myprefferedpackage;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class MyController {
private List<MyEntity> entities;
#PostConstruct
public void init() {
this.entities = new ArrayList<MyEntity>(10);
for(int i = 0; i < 10; ++i) {
this.entities.add(new MyEntity(i));
}
}
public List<MyEntity> getAllEntities() {
return entities;
}
public void increment(MyEntity myEntity) {
myEntity.increment();
}
public class MyEntity {
private int id;
private int counter;
private Date lastUpdate;
public MyEntity(int id) {
this.id = id;
this.counter = 0;
this.lastUpdate = new Date();
}
public void increment() {
this.counter++;
this.lastUpdate = new Date();
}
public int getId() {
return id;
}
public int getCounter() {
return counter;
}
public Date getLastUpdate() {
return lastUpdate;
}
}
}
Either use the 'ajax' functionality of a utility library like OmniFaces or be creative with the PrimeFaces Selectors.
In both cases you need to get access to the e.g. the 'current' row or rowId. But since that you have the buttons IN the row, that should not be a problem. I unfortunately don't have the time to create examples for you
I try with uptate = "#parent:componentAnotherColumn" and works. Only update the same row
<p:column>
<p:selectBooleanCheckbox value="#{atributoVar.booleanValue}">
<p:ajax process="#this" update="#parent:componentAnotherColumn"/>
</p:selectBooleanCheckbox>
</p:column>
<p:column>
<p:selectBooleanCheckbox id="componentAnotherColumn" value="#{!atributoVar.booleanValue}"/>
</p:column>

primefaces commandButton "update" not working

I have this dialog:
<p:dialog
id="dlgComment"
widgetVar="dialogComentario"
modal="true"
header="#{messages.comentarios}"
width="600px"
resizable="false" showEffect="clip" hideEffect="clip">
<h:form id="formComentario">
<p:panelGrid columns="2" style="width: 100%">
<f:facet name="header">
<h:outputText value="#{monitorarEventoControlador.eventoSelecionado.titulo}"/>
</f:facet>
<h:outputText value="#{messages.inicio}" />
<h:outputText value="#{monitorarEventoControlador.eventoSelecionado.inicio}" />
<h:outputText value="#{messages.gravidade}" />
<h:outputText value="#{monitorarEventoControlador.eventoSelecionado.gravidade}" />
</p:panelGrid>
<p:dataTable id="tableComentario" var="comentario" value="#{monitorarEventoControlador.eventoSelecionado.getComentariosAsList()}" emptyMessage="#{messages.noRecordsFound}">
<f:facet name="header">
#{messages.comentarios}
</f:facet>
<p:column headerText="#{messages.dataHora}">
<h:outputText value="#{comentario.dataHora}">
<f:convertDateTime pattern="dd/MM/yyyy HH:mm" timeZone="#{monitorarEventoControlador.buscaTimeZone()}"/>
</h:outputText>
</p:column>
<p:column headerText="#{messages.usuario}">
<h:outputText value="#{comentario.usuario.orgao.sigla} - #{comentario.usuario.apelido}"/>
</p:column>
<p:column headerText="#{messages.texto}">
<h:outputText value="#{comentario.texto}" />
</p:column>
</p:dataTable>
<p:panelGrid columns="2" style="width: 100%">
<h:inputText value="#{monitorarEventoControlador.comentarioSelecionado.texto}" maxlength="80"/>
<p:commandButton value="#{messages.comentar}" actionListener="#{monitorarEventoControlador.adicionarComentario()}" icon="ui-icon-check" update="tableComentario" />
</p:panelGrid>
</h:form>
</p:dialog>
And the bean:
public void adicionarComentario() {
comentarioSelecionado.setDataHora(new Date());
comentarioSelecionado.setEvento(eventoSelecionado);
comentarioSelecionado.setUsuario(autenticador.getUsuarioCorrente());
todosOsComentarios.colocar(comentarioSelecionado);
notificarComentario(comentarioSelecionado);
eventoSelecionado.getComentarios().add(comentarioSelecionado);
todosOsEventos.colocar(eventoSelecionado);
iniciarComentario(eventoSelecionado);
}
private void notificarComentario(Comentario comentario) {
Notificacao n = new Notificacao();
n.setDataHora(comentario.getDataHora());
n.setDescricao(DateUtil.dataHoraFormatada(n.getDataHora()) + " - " + comentario.getUsuario().getOrgao().getSigla() + "(" + comentario.getUsuario().getApelido() + "): " + comentario.getTexto());
n.setComentario(true);
n.setInforme(comentario.getEvento().getInforme());
comentario.getEvento().getInforme().getNotificacoes().add(n);
}
public void iniciarComentario(Evento evento) {
comentarioSelecionado = new Comentario();
setEventoSelecionado(evento);
}
The commandButton should update a dataTable. I have just moved from Prime 3.5 to 5.1 and among other problems I managed to figure out, there is this one that's realy annoying. It was working on Prime 3.5.
To be more specific about what is going wrong here: The action is fired normaly, the data is inserted correctly, but the dataTable is no longer updated. It is the very same code I was using yesterday with Prime 3.5, but now, using Prime 5.1 the dataTable does not refresh anymore.
Any ideas ? Thanks
use : before id
Remember
if you make a dialog
Before dialog old form tag should be close
then dialog content should be placed into another form.
use :dialogid, :dialogFormId

Ajax in JavaServer Faces

I’m trying to use ajax in jsf.
So, I have inputtextarea and datatable:
<h:form>
<h:inputTextarea id="mailstextarea" style="width:100%" value="#{newMembersBean.newMembersStr}">
<f:ajax event="keyup" render="newmembertable" execute="mailstextarea" />
</h:inputTextarea>
<h:dataTable id="newmembertable" styleClass="tableWidth" value="#{newMembersBean.newMembers}" var="member">
<h:column>
<f:facet name="header">#{msgs.name}</f:facet>
#{member.name}
</h:column>
<h:column>
<f:facet name="header">#{msgs.surename}</f:facet>
#{member.sureName}
</h:column>
<h:column>
<f:facet name="header">#{msgs.email}</f:facet>
#{member.email}
</h:column>
<h:column>
<f:facet name="header">#{msgs.phone}</f:facet>
#{member.phone}
</h:column>
</h:dataTable>
<h:commandButton type="submit" value="#{msgs.add}"/>
</h:form>
I want to change newMembersBean.newMembers List (and datatable newmembertable) on every value change in textarea…
In my bean I’m trying to do somethink like this (now only for testing, I want to show all users, if user have typed more then 3 characters):
#Named
#ConversationScoped
public class NewMembersBean implements Serializable {
private List<UsersEntity> newMembers = new ArrayList<UsersEntity>();
private String newMembersStr = "";
......
public List<UsersEntity> getNewMembers() {
UsersDao ud = new UsersDao();
if(newMembersStr.length() > 3)
{
newMembers = ud.getAllUsers();
}
return newMembers;
}
.....
}
But when I’m typing text in textare nothing happens.
Please help.
Thanks.

Resources