JSF: Datatable excecuting remove method twice - ajax

I'm facing a strange behavior in my jsf datatable component and couldn't figure out what`s going on. This is the scenario: I have a datatable with a remove button on each row. When I click on the button of the last row, it is correctly deleted. When I click on the button in the row before the last row, it deletes the row itself and also the next row. No row above it is affected.
My environment: Eclipse Neon + Tomcat 8 + Primefaces 6.0
I'm running the project from inside Eclipse.
The datasource of the p:dataTable is being modified by data selected from a p:autoComplete component.
In debbuging mode I could check that the remove method is being called multiple times with different parameters each time. Bellow is a part of the code.
It seems (looking at the browser developer tool) that the Ajax is calling the server method just once, so the multiple execution is happening at the server side.
I've already googled for similar issues in links like Link 1 and Link 2.
The page.xhtml:
<p:autoComplete id="ddl" dropdown="false"
value="#{bean.chosenItem}" var="item"
itemLabel="#{item.name}" itemValue="#{item}"
converter="convertItem"
emptyMessage="No item found" queryDelay="1000"
minQueryLength="3" autocomplete="off"
completeMethod="#{bean.findItemsCompleteText}"
forceSelection="true" placeholder="Type item name"
cache="true" widgetVar="dllWGV">
<p:ajax event="itemSelect"
listener="#{bean.addToDataTable}"
update="dtb ddl" />
</p:autoComplete>
<p:dataTable id="dtb"
value="#{bean.chosenItems}" var="rowItem"
sortBy="#{rowItem.name}" scrollable="true" scrollHeight="90"
scrollWidth="337" tableStyle="#{bean.dtbStyle}"
widgetVar="dtbWGV">
<p:column style="border: none; padding-left: 2px;">
<p:commandButton actionListener="#{bean.removeFromDataTable(rowItem)}"
update="dtb"
style="margin-right: 2px;" icon="fa fa-trash" />
<h:outputText value="#{rowItem.name}" />
</p:column>
<p:column style="border: none; width: 28%;">
<p:spinner suffix="%" min="0" max="100" stepFactor="0.25"
value="#{rowItem.dAux}" size="5" />
</p:column>
</p:dataTable>
The managed bean (ViewScoped):
private ItemClass chosenItem;
private List<ItemClass> chosenItems;
private String dtbStyle;
//getters and setters with no logic inside
//beyond getting and setting the properties
#PostConstruct
public void init(){
if (chosenItems == null) {
chosenItems = new ArrayList<ItemClass>();
}
setDtbStyle("visibility: hidden; width: 320px;");
}
//each time, during the multiple executions,
//the parameter localItem has a different value
public void removeFromDataTable(ItemClass localItem) {
this.chosenItems.remove(localItem);
if(chosenItems.size() == 0) {
setDtbStyle("visibility: hidden; width: 320px;");
}
}
public void addToDataTable(SelectEvent event) {
this.chosenItems.add(this.chosenItem);
setDtbStyle("visibility: visible; width: 320px;");
this.chosenItem = null;
}
Thanks for any clue about what could be happening.
Juliano

After reading here and here, I tried put process="#this" on the remove p:commandButton in the p:dataTable. It has made the trick, but I don`t know excactly how. I've understood that #this tells the server to process just the methods in the actionLinstener of the p:commandButton, ignoring any other actions in other components of the page. Well, the fact that this modification has worked points that the problem is in the overall logic of my page. Actually, I don't know where exactly my mistake is, but as the page is pretty heavy, I'm almost sure there really is a silly mistake of mine somewhere in it.
[1]:Clicking p:commandButton causes the value of p:selectOneMenu being set twice
[2]:Understanding process and update attributes of PrimeFaces
The page.xhtml was modified to:
<p:dataTable id="dtb"
value="#{bean.chosenItems}" var="rowItem"
sortBy="#{rowItem.name}" scrollable="true" scrollHeight="90"
scrollWidth="337" tableStyle="#{bean.dtbStyle}"
widgetVar="dtbWGV">
<p:column style="border: none; padding-left: 2px;">
<p:commandButton actionListener="#{bean.removeFromDataTable(rowItem)}"
update="dtb"
process="#this" <!--solution: adding this attribute-->
style="margin-right: 2px;" icon="fa fa-trash" />
<h:outputText value="#{rowItem.name}" />
</p:column>
<p:column style="border: none; width: 28%;">
<p:spinner suffix="%" min="0" max="100" stepFactor="0.25"
value="#{rowItem.dAux}" size="5" />
</p:column>
</p:dataTable>

Related

JSF PrimeFace: p repeat ajax update with class not working

totalListSumA is an ArrayList inside java. Inside debug mode, the arraylist work just fine. New value assigned into this list.
When user input a new value in a box, program will recalculate new sum and display inside the code shown below.
<p:inputNumber
class="caseType1"
rendered="#{inputFormTemplateView.allowEdit}"
inputStyle="text-align: center"
minValue="0"
maxValue="99999999"
decimalPlaces="0"
thousandSeparator=""
emptyValue=""
value="#{inputFormView.selectedInputFormDetail.data[dataField]}" >
<p:ajax update="dataField, #{inputForm4_1View.getColTotal()}"/>
<p:ajax update="#(.totalRow3)"></p:ajax>
</p:inputNumber>
<tr>
<td align='center'>Total</td>
<p:repeat var="item" value="#{inputForm4_1View.totalListSumA}" class="totalRow3">
<td class="cell_cal" style='text-align:center;' >
<h:outputLabel
class="totalRow3"
value="#{item}" />
</td>
</p:repeat>
</tr>
I have tried
h:panelGroup id='...'
ui:repeat id='....'
Still the value remain unchanged inside p:repeat. Any method I can try to get and show the latest value inside totalListSumA?
This is wrong
<p:ajax update="dataField, #{inputForm4_1View.getColTotal()}"/>
<p:ajax update="#(.totalRow3)"></p:ajax>
1) Ajax should have event="change" or other events, but most wrong thing is that calling bean method inside update.
2) Use listener="#{inputForm4_1View.getColTotal()}"
3) Don't use 2 same ajaxes.
Solution:
<p:ajax event="change" update="dataField, #(.totalRow3)" listener="#{inputForm4_1View.getColTotal()}"/>
If this doesn't solve your problem, try update form like update="#form" or update="yourFormId"

<p:spinner> max value won't change anymore into other value after getting error validation form [duplicate]

This question already has answers here:
How can I populate a text field using PrimeFaces AJAX after validation errors occur?
(3 answers)
How to reset input fields in a form after validation fail when updating it with new values
(2 answers)
Closed 3 years ago.
So, it worked fine, until it get error required validation in form. myMaxDuration won't change anymore in xhtml, but when I sysout it in console it changed.
If, the myMaxDuration I send into bean is 30, Ajax worked fine.
But, if myMaxDuration when I send into bean is 10, ajax won't work.
already tried using ajax update in bean
<p:panelGrid columns="1" columnClasses="ui-grid-col-6" layout="grid" styleClass="ui-panelgrid-blank">
<p:outputLabel value="Name"/>
<p:inputText value="#{myBean.nEmp.name}" required="true"/>
<p:outputLabel value="Status" styleClass="labelSmall"/>
<p:selectOneMenu required="true" value="#{myBean.nEmp.employmentStatusID}"
<f:selectItem itemValue="10" itemLabel="10"/>
<f:selectItem itemValue="20" itemLabel="20"/>
<f:selectItem itemValue="30" itemLabel="30"/>
<p:ajax listener="#{myBean.maxDuration()}" update=":form:durasiID"></p:ajax>
</p:selectOneMenu>
</p:panelGrid>
<p:outputPanel>
<p:panelGrid columns="1" columnClasses="ui-grid-col-3" layout="grid" styleClass="ui-panelgrid-blank" rendered="#{myBean.nEmp.employmentStatusID != 6}">
<p:outputLabel value="Durasi" styleClass="labelSmall"/>
<p:spinner min="1" max="#{myBean.myMaxDuration}" id="durasiID" value="{myBean.nEmp.monthDuration}"/>
</p:panelGrid>
</p:outputPanel>
<p:commandButton value="save" action="#{myBean.saveNewDecreeEmployee()}" />
on my bean
public void maxDuration() {
if(nEmp.getEmploymentStatusID() == 10) {
myMaxDuration = 10;
}
else if(nEmp.getEmploymentStatusID() == 20) {
myMaxDuration = 20;
}
else {
myMaxDuration = 30;
}
nEmp.setMonthDuration(myMaxDuration);
System.out.println(myMaxDuration + " - maxDuration");
}
the value of in xhtml should be changed like in console, after someone get error form validation field name required.
So, I solved this problem by reference of #Kukeltje
Based on this, How can I populate a text field using PrimeFaces AJAX after validation errors occur?
I just add resetValues="true" into my <p:ajax>
and it's worked fine.

How Close PrimeFaces PhotoCam?

I'm using photocam for take picture with camera but capture option is always open. I am using photocam autostarts property with created to button which invite a method like that:
public void pcFotoStarter()
{
if (pcFoto == Boolean.FALSE)
pcFoto = Boolean.TRUE;
else
pcFoto = Boolean.FALSE;
}
This method makes my method's pcFoto field true or false , and then I defined <f:ajax execute="button" render="PhotoCam" />
According to the pcFoto Boolean Value(true or false), photocam is working or not. Problem is, photocam starts at once and I can close only 1 time photocam.Ant than I am unable to restart photocam. And my webcam usage yellow led is flashing. It's like webcam is already in usage.
try execute this Javascript code when you want to off camera
Webcam.stream.getTracks().forEach(x=> x.stop());
In my case i turn on camera while open p:photoCam in p:dialog (dynamic) and has p:ajax callback on "close" event. Like this
<p:dialog id="modalDialog" widgetVar="photoEditDialog"
modal="true" onHide="PF('photoEditDialog').toggleMaximize();"
resizable="false" closeOnEscape="true"
dynamic="true"
>
<p:ajax event="close" update="photo #this" onsuccess="Webcam.stream.getTracks().forEach(x=> x.stop());"/>
<div style="display: flex;">
<section>
<h1>Camera</h1>
<p:photoCam widgetVar="photoCam" listener="#{cc.attrs.value.onPhotoCapture}" update="preview"
width="400" height="300" photoWidth="1024" photoHeight="768"
/>
<p:commandButton type="button" value="Capture" onclick="PF('photoCam').capture()"/>
</section>
<section>
<h1>Preview</h1>
<p:graphicImage id="preview" value="#{cc.attrs.value.photo}" stream="false"/>
</section>
</div>
</p:dialog>

JSF input file tag + ajax

I lost whole day on this issue and got nothing. I know that the question was asked but it was never answered. BalusC said that this issue is fixed in JSF 2.2.5 but either it is not or i do something wrong.
I use h:inputFile tag with ajax to render choosen image in preview div after chosing one from disk. However it's rendered only once and i have to reload page to see next chosen image. It causes more errors. For example when I use SUBMIT button to send chosen image to DB, ajax from commandLink is not executed (image is saved and rendered after page after refresh).
It looks to me like ajax is broken after chosing an image from disk and followed ajax actions are not executed, even they dont belong to h:inputfile.
This is my JSF form (one of its versions because i tried so many tricks)
<h:panelGroup class="photo-update" rendered="#{profileBean.page eq 'photo'}">
Dodaj lub zmień swoje zdjęcie profilowe[...]
<h:form enctype="multipart/form-data">
<h:panelGroup id="form-content">
<h:panelGroup id="current-image" class="current-image">
<p:graphicImage value="#{imageBean.getUserImage()}"/>
</h:panelGroup>
<h:panelGroup id="accept-container-ajax">
<h:panelGroup id="accept-container" class="accept-container"
rendered="true">
<div class="arrow">
<img src="resources/images/arrow.png"/>
<div class="change-text">Zamień na</div>
</div>
<h:panelGroup id="new-image" class="new-image">
<p:graphicImage value="#{profileBean.getConvertedImage()}"/>
</h:panelGroup>
<h:commandLink class="btn btn-default ok-button" value="zatwierdź"
action="#{profileBean.uploadPhoto}">
<f:ajax render="accept-container-ajax current-image"
execute="#form"/>
</h:commandLink>
</h:panelGroup>
</h:panelGroup>
<div class="btn btn-default change-image-container">
Zmień zdjęcie
<h:inputFile immediate="true" id="change-image"
class="change-image" value="#{profileBean.image}">
<f:ajax render="accept-container-ajax" execute="#form"/>
</h:inputFile>
</div>
</h:panelGroup>
</h:form>
</h:panelGroup>
This is fragment of the bean:
public StreamedContent getConvertedImage() throws IOException {
return userBo.convertPartToStream(image);
}
public void uploadPhoto() {
this.renderChangeContainer = false;
if (userBo.addImage(this)) {
FacesContext.getCurrentInstance().addMessage(
null, new FacesMessage(
FacesMessage.SEVERITY_INFO, "...", null));
} else {
FacesContext.getCurrentInstance().addMessage(
null, new FacesMessage(
FacesMessage.SEVERITY_ERROR, "...", null));
}
}
injected BO methods are OK.
Please give me a clue what is going on.
EDIT:
I also see ugly iframe with some response content i guess.

JSF: Is there a way to create animation effect when insert a new record into table?

I've been googling this question a lot and I dont seem to find a solution. I wonder if any developer out there that able to achieve this? I know there are couple ajax framework out there for JSF like Richfaces, primefaces, icefaces ... I have look at their showcase, and could not seems to find what I am looking for.
This is how it would work for h:dataTable assuming that we always append to the table:
<h:form>
<h:panelGroup id="animatedTableGroup">
<h:dataTable id="animatedTable" value="#{myBean.rows}" var="row">
<h:column>
<h:outputText value="#{row}"/>
</h:column>
</h:dataTable>
<rich:jQuery timing="onload"
selector="#animatedTable tr:last" query="fadeOut('slow')"/>
<rich:jQuery timing="onload"
selector="#animatedTable tr:last" query="fadeIn('slow')"/>
</h:panelGroup>
<a4j:commandButton value="Add row"
action="#{myBean.addRow}" reRender="animatedTableGroup"/>
</h:form>
And the bean:
public void addRow() {
rows.add(new Date().toString());
}
public List<String> getRows() {
return rows;
}
If you want to insert into selected position in the table, then it's better to use rich:extendedDataTable and use something like this as selector:
<rich:jQuery timing="onload"
selector="#animatedTable tr.rich-sdt-row-selected" query="..."/>
Richfaces has native support for jQuery using rich:jQuery component. You can use any effects that jQuery supports. For example:
<h:commandButton id="submitButton" value="Submit"
action="#{myBean.myAction}" style="display: none;"/>
<rich:jQuery selector="#submitButton"
query="fadeIn('slow')" timing="onload">
or
<h:commandButton id="submitButton" value="Submit"
action="#{myBean.myAction}"
onmouseover="jQuery(this).fadeOut('slow');"
onmouseout="jQuery(this).fadeIn('slow')"/>
You can find more examples here: http://docs.jboss.org/richfaces/latest_3_3_X/en/devguide/html/rich_jQuery.html

Resources