Primefaces event pass attribute only first time - jsf

I got an issue for a while and I can't get rid of it. In my data table I have a column with a button to display a dialog with further information on click.
When I click the first time on the button the dialog opens with the right values, but when I click a second time on button of the same row or any other the values aren't displayed because my event handler findStfPack receive a null value attribute.
I tried to pass the PackageData object to be displayed directly to the method as parameter:
<p:column width="60">
<p:commandButton oncomplete="PF('dlgViewStfPack').show()"
update="search:dlgViewStfPackId"
value=""
title="#{msg['button.search']}"
action="#{budgetViewFulfiledController.findStfPack(_item.stfPack)}"
process="#this"/>
</p:column>
Handler method in view controller:
public void findStfPack(PackageData event){
System.out.println("event: "+event.getPackId());
stfPack= event;
}
Or with primefaces action event:
<p:column width="60">
<p:commandButton oncomplete="PF('dlgViewStfPack').show()"
update="search:dlgViewStfPackId"
value=""
title="#{msg['button.search']}"
actionListener="#{budgetViewFulfiledController.findStfPack}"
process="#this">
<f:attribute name="pack" value="#{_item.stfPack}"/>
</p:commandButton>
</p:column>
Handler method in view controller:
public void findStfPack(ActionEvent event){
PackageData packageData= (PackageData)event.getComponent().getAttributes().get("pack");
System.out.println("event: "+packageData.getPackId());
stfPack= packageData;
}
The dialog:
<p:dialog id="dlgViewStfPackId"
header="#{budgetViewFulfiledController.stfPack.staff.stfName} - Package salarial"
modal="true"
widgetVar="dlgViewStfPack">
<div class="groupDataBox">
<my:outputCurrentPackage currPack="#{budgetViewFulfiledController.stfPack}"/>
</div>
</p:dialog>
And the outcome is the same in the 2 scenarios: on the first event trigger the value is properly passed and displayed but on the second event trigger I got a NullPointerException.
I should specify that, I don't know why but without the update="search:dlgViewStfPackId" the values are not displayed in the dialog.

I don't know exactly the reason, but if you don't update dialog, data can't refresh, it's will be cached the last result.
Try to change like this :
XHMTL
<p:column width="60">
<p:commandButton oncomplete="PF('dlgViewStfPack').show()"
update="#([$id=dlgViewStfPackId])"
value=""
title="#{msg['button.search']}"
action="#{budgetViewFulfiledController.findStfPack(_item.stfPack)}"
process="#this">
</p:commandButton>
</p:column>
JAVA
public void findStfPack(PackageData pd){
System.out.println("event: "+pd.getPackId());
this.stfPack= pd;
}
If it's not working, try to process ID_TABLE

Related

How to update a specific cell on a PrimeFaces dataTable

In my dataTable I am linking each article with a specific task.
On the click of a commandButton a list of tasks shows up, so I want on the select of a task, update a specific cell in the dataTable (outputText with id="columnTache") without updating the rest of my dataTable.
<p:dataTable value="#{myController.articleList}"
id="tabArticle"
var="article"
rowKey="#{article.id}" >
<p:column headerText="quantite" >
<pe:inputNumber value="#{article.quantite}" />
</p:column>
<p:column headerText="taches" >
<h:outputText value="#{article.tache.libelleTache}" id="columnTache" />
</p:column>
<p:column headerText="taches" >
<p:commandButton oncomplete="PF('dialogTasks').show();" update=":formSelectAffecterTache">
<p:ajax event="click" listener="#{myController.setArticle(article)}" />
</p:commandButton>
</p:column>
</p:dataTable>
<p:dialog header="#{bundleTech.lbl_taches}" widgetVar="dialogTasks" >
<h:panelGrid columns="1" >
<h:form id="formSelectAffecterTache">
<ui:include src="/pages/listTacheSelect.xhtml">
<ui:param name="bean" value="#{myController}" />
<ui:param name="action" value="affecterTache" />
</ui:include>
</h:form>
</h:panelGrid>
</p:dialog>
The update of my dataTable is in the managed bean:
public void affecterTache() {
article.setTache(selectedSingleTache);
RequestContext.getCurrentInstance().update("form:tabArticle");
}
A dataTable is a naming container, so components within it will be prepended with the dataTable's id. Also, each iteration of data presented in the table (each row) will have effect of the generated ids. Since a form is also a naming container, your outputText component ids will be generated as formId:tabArticle:0:columnTache in the first row, formId:tabArticle:0:columnTache in the second row, etc.
If you would set an id on your commandButton you will get formId:tabArticle:0:myButton, formId:tabArticle:1:myButton etc. You can use this id in your click handler to create the corresponding inputText clientId. But, since you pass article to a method, you are not able to check which button was clicked. So first of all change the click listeners method to:
public void useArticle(AjaxBehaviorEvent event) {
UIComponent component = event.getComponent();
}
Now, you know which button was clicked (event.getComponent()), but you need your article as well. You can set that as an attribute to your button in XHTML:
<p:commandButton id="myButton"
oncomplete="PF('dialogTasks').show();"
update=":formSelectAffecterTache">
<p:ajax event="click"
listener="#{myController.useArticle}" />
<f:attribute name="article"
value="#{article}" />
</p:commandButton>
This attribute can be read in your listener:
Article article = (Article) component.getAttributes().get("article");
Now, for updating the inputText, simply use the button's clientId:
String update = component.getClientId().replace(":myButton", ":columnTache");
Store it in your bean, and when you are ready to do so, update:
RequestContext.getCurrentInstance().update(update);
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
Send additional parameter to Ajax event listener

submit button does not submit but only triggers InputText's onChange event

I am automatically selecting a value for radio button when the user types something in an input text using ajax.
The problem is: when the user types something in the input text and directly submits the form by clicking Get, the form does not submit but only the ajax is called because of the change event and the radio is updated.
A second click on the Get button, submits the form.
I also do not want to use keyup since it migth disturb the user while typing.
I use primefaces 5.1
here is my code:
<h:form id="myForm">
<p:selectOneRadio
value="#{myBean.include}" id="IncludeRadio">
<f:selectItem itemValue="Include" itemLabel="Include" />
<f:selectItem itemValue="Exclude" itemLabel="Exclude" />
<p:ajax process="#this" update="#form" />
</p:selectOneRadio>
<p:radioButton id="IncludeRadio0" for="IncludeRadio" itemIndex="0"/>
<p:radioButton id="IncludeRadio1" for="IncludeRadio" itemIndex="1"/>
<p:inputText
value="#{myBean.fieldValue}"
id="FieldValueInputText">
<p:ajax process="#this" update="#form" />
</p:inputText>
<p:commandButton id="GetButton"
action="#{myBean.execute}"
value="Get">
</p:commandButton>
</h:form>
and the bean:
#ManagedBean
#SessionScoped
public class MyBean {
public void setFieldValue(final String fieldValue) {
if (fieldValue != null && !fieldValue.trim().isEmpty()) {
if (!"Include".equals(getInclude())
&& !"Exclude".equals(getInclude())) {
setInclude("include");
}
} else {
setInclude("");
}
}
public void setInclude(String include) {
this.include = include;
}
public String getInclude() {
return this.include;
}
public void execute() {
// do something
}
}
submit button does not submit but only triggers InputText's onChange event
That happened because the blur event of the input field ajax-updates the submit button around the moment you click it. This way the JavaScript/Ajax logic associated with submit button is not guaranteed to work anymore, because the source element is removed from the DOM.
Make sure that you don't cover the submit button in the ajax update.
Instead of updating the entire form,
<p:ajax ... update="#form" />
update only the pieces which really need to be updated, which are only the inputs in your specific case:
<p:ajax ... update="IncludeRadio FieldValueInputText" />
Or if you'd rather like to not keep track of all those IDs when you have many inputs, grab PFS:
<p:ajax ... update="#(#myForm :input)" />

Blocking a p:commandButton displayed on a p:confirmDialog in addition to displaying a dynamic message on the dialog

I'm trying to block a <p:commandButton> which is displayed on a <p:confirmDialog> as follows.
<p:confirmDialog id="confirmDeleteDialog" widgetVar="confirmDelete" message="Message" closeOnEscape="true" appendTo="#(body)" closable="true">
<p:blockUI block="confirm" widgetVar="blockUI">
<h:outputText value="Demo"/>
</p:blockUI>
<p:commandButton id="confirm" value="Yes" onstart="PF('blockUI').show()" oncomplete="PF('blockUI').hide();"/> <!--Use PF('confirmDelete').hide() to dismiss the dialog.-->
<p:commandButton id="decline" value="No" onclick="PF('confirmDelete').hide()" type="button" />
</p:confirmDialog>
<p:commandButton oncomplete="PF('confirmDelete').show()"/>
This blocks Yes button (one with the id="confirm") held by <p:confirmDialog>.
The message to be displayed on the confirm dialog is dynamic. It is fetched from the associated backing bean based on certain conditions. Therefore, the dialog is required to be updated before it is displayed.
To update the dialog before it is displayed, the update attribute of <p:commandButton> is set as follows.
<p:commandButton oncomplete="PF('confirmDelete').show()" update="confirmDeleteDialog"/>
This of course, displays a desired message on the dialog dynamically (which is not demonstrated here for the sake of simplicity) but doing so prevents the <p:blockUI> from functioning - it does not block the <p:commandButton>, if the dialog is updated by it.
Neither errors on the browser console nor exceptions on the server terminal are seen.
What is the way of blocking a button held by a in addition to displaying a dynamic message on the dialog?
EDIT :- the answer provided by me is cross-mark.
As noted in the answer given by me, <p/pe:blockUI> needs to be updated, when the <p:commandButton> held by the confirm dialog is clicked, it takes some time to block the button - <p:commandButton> after it is clicked. In the meanwhile, the button can be clicked (either deliberately or accidently) before the initial request completes that may cause duplicate submits which is certainly against the use of <p/pe:blockUI>.
Nothing is preventing a user in my workaround, from clicking the button multiple times before it is blocked by <p/pe:blockUI>. Therefore, the answer provided by me is considered to be cross-mark.
Perhaps the way to meet this requirement is completely different.
EDIT 2:- the actual scenario.
//A view scoped bean.
//A list of selected rows in <p:dataTable>.
private List<WishUtils>selectedValues;
//The actual message to be displayed on the dialog.
private String deleteMsg;
//Associated with the rendered property of the "Yes" button on the dialog.
private boolean renderedYesButtonDelete=true;
//The header message/text of the dialog.
private String messageBoxHeader;
//The no button text (its value).
private String noButtonTextDelete="No";
//Getters and setters as required.
public void confirmDelete(ActionEvent actionEvent) {
if(selectedValues!=null && !selectedValues.isEmpty()) {
renderedYesButtonDelete=true;
noButtonTextDelete="No";
deleteMsg="A long message about a delete prompt from a resource bundle";
messageBoxHeader="Confirm Delete";
} else {
noButtonTextDelete="OK";
renderedYesButtonDelete=false;
deleteMsg="Please select the rows you want to delete";
messageBoxHeader="Confirm Item Select";
}
}
public void delete(ActionEvent actionEvent) {
if(actionEvent.getComponent().getId().equals("confirmDeleteMultiple")) {
//Delete the selected rows.
} else {
//Notify an error (generally never going to be executed).
}
}
The message box goes here :
<p:confirmDialog id="confirmDialogDeleteMultiple" widgetVar="confirmDeleteUIWidget" header="#{wishManagedBean.messageBoxHeader}" closeOnEscape="true" appendTo="#(body)" closable="true">
<p:blockUI id="blockDelete" block="confirmDeleteMultiple" widgetVar="blockDeleteUIWidget"/>
<p:remoteCommand name="blockDeleteCommand" update="blockDelete" process="#this"/>
<p:commandButton id="confirmDeleteMultiple"
value="#{messages['confirmdialog.yes']}"
onclick="blockDeleteCommand();"
onstart="PF('blockDeleteUIWidget').show();"
oncomplete="PF('blockDeleteUIWidget').hide();PF('confirmDeleteUIWidget').hide()"
actionListener="#{wishManagedBean.delete}"
process="#this"
rendered="#{wishManagedBean.renderedYesButtonDelete}"
update="a list of components to be updated"/>
<p:commandButton id="declineDeleteMultiple"
value="#{wishManagedBean.noButtonTextDelete}"
onclick="PF('confirmDeleteUIWidget').hide()"
type="button"/>
<f:facet name="message">
<p:outputPanel>
<h:outputFormat value="#{wishManagedBean.deleteMsg}" escape="false"/>
</p:outputPanel>
</f:facet>
</p:confirmDialog>
The <p:blockUI> indeed fails when the entire dialog is updated. Looks like just another bug. It works when you explicitly call the PrimeFaces.cw(...) "create widget" script of the <p:blockUI> component (exactly that script which you see in generated HTML output representation of <p:blockUI>) on complete of the dialog update.
Given those IDs,
<h:form id="formId">
<p:confirmDialog id="confirmDialogId">
<p:blockUI id="blockId" ... />
<p:commandButton id="confirmButtonId" ... />
The following oncomplete should do it:
<p:commandButton update="confirmDialogId"
oncomplete="PrimeFaces.cw('BlockUI','blockUI',{id:'formId:blockId',block:'formId:confirmId'});PF('confirmDialogId').show()" />
That explains why the <p:remoteCommand> trick works as it under the covers basically re-generates the <p:blockUI> component along with that PrimeFaces.cw(...) call, although it fires an unnecessary ajax request. It might be worth reporting an issue to PrimeFaces guys, telling that PrimeFaces.cw(...) of <p:blockUI> isn't properly executed when the confirm dialog widget is updated.
Another workaround would be to explicitly ajax-update only the parts you'd like to update instead of the entire dialog. That works for me. The header and the message attributes of the <p:confirmDialog> (and those of many other PrimeFaces components) supports being defined via <f:facet> on the attribute name. This allows you to wrap it in a <h:outputText> (or <h:panelGroup>) so that you can just update it individually. This way you don't need to update the entire dialog and the block UI keeps working as intented.
<p:confirmDialog ...>
<f:facet name="header">
<h:outputText id="confirmDeleteDialogHeader" value="#{bean.header}" />
</f:facet>
<f:facet name="message">
<h:outputText id="confirmDeleteDialogMessage" value="#{bean.message}" />
</f:facet>
<h:panelGroup id="confirmDeleteDialogContent">
<p:blockUI ... />
<p:commandButton ... />
<p:commandButton ... />
</h:panelGroup>
</p:confirmDialog>
<p:commandButton ...
update="confirmDeleteDialogHeader confirmDeleteDialogMessage confirmDeleteDialogContent"
oncomplete="PF('confirmDelete').show()" />
This requires the <p/pe:blockUI> to be updated, when the <p:commandButton> displayed on the confirm dialog is clicked.
The <p:blockUI> can be updated onclick using the <p:remoteCommand> (onstart also works).
The code goes here.
<p:confirmDialog id="confirmDeleteDialog" widgetVar="confirmDelete" message="Message" closeOnEscape="true" appendTo="#(body)" closable="true">
<p:blockUI id="blockConfirm" block="confirm" widgetVar="blockUI"/>
<p:remoteCommand name="confirmCommand" update="blockConfirm"/>
<!--Add PF('confirmDelete').hide() to oncomplete to dismiss the dialog, when this button is clicked.-->
<p:commandButton id="confirm" value="Yes" onclick="confirmCommand();" onstart="PF('blockUI').show()" oncomplete="PF('blockUI').hide()"/>
<p:commandButton id="decline" value="No" onclick="PF('confirmDelete').hide()" type="button" />
</p:confirmDialog>
<p:commandButton oncomplete="PF('confirmDelete').show()" update="confirmDeleteDialog" value="Submit"/>

When i click on any link it should Open in the same New Window in JSF, Primefaces

In my JSF page i have few Links{link1,link2,link3,link4}-{Student Id's}.
What i tried is when i click on the Link it Opens the Student-Information in a "NEW WINDOW".
When i am clicking on the next Link it is Opening a New Window,but i want to open in the Same New Window i.e., the TARGET should be the Same NEW Window which is opened.
Diagramatical Representation:
My Piece of Code which i had tried from collecting things from STACKOVERFLOWOpen Page in New Window :
<p:dataTable id="studentDtTble" var="studData" value="#{studentController.dataList}">
<p:columnGroup type="header">
<p:row>
<p:column headerText="StudentId"></p:column>
<p:column headerText="StudentName"></p:column>
<p:column headerText="Add" ></p:column>
</p:row>
</p:columnGroup>
<p:column>
<p:commandLink id="sidlink" action="/studentinfo.xhtml" target="_blank">
<h:outputText value="#{studData.studentId}" styleClass="txtlink" />
</p:commandLink>
</p:column>
<p:column>
<h:outputText value="#{studData.studentName}" />
</p:column>
<p:column >
<p:selectBooleanCheckbox value="#{studData.add}" />
</p:column>
</p:dataTable>
Edited After #Nosnhoj Reply :When i Click on any of the SID Link then there Details Should Opened in the "Same NEW Window".
Use <h:commandLink> instead of <p:commandLink>.
I tried your code and make a little change like this:
<h:commandLink id="sidlink" action="#{studentController.selectStudent(studData)}" target="_blank">
<h:outputText value="#{studData.studentId}" styleClass="txtlink" />
</h:commandLink>
I changed <p:commandLink> to <h:commandLink>, and call a method in the backing bean to set the selected Student.(For the New Window should need the student information.)
Here is the code of studentController.selectStudent :
private Student selectedStu;
public String selectStudent(Student stu) {
selectedStu = stu;
return "/studentinfo.xhtml";
}
And the following is the code of New Window:
<h:form>
<h:commandLink value="Another Link" action="/anotherinfo.xhtml" target="_self"/>
<br/>
Student: <h:outputText value="#{studentController.selectedStu.studentName}"/>
</h:form>
Which is just showing name of the selected Student, and another link you want.
Note that the target attribute is _self because you want the new page show in the same window.
Finally, the anotherinfo.xhtml is just an empty page I created via NetBeans, so there's no need to post it.
And here's what you may see:
After clicking the id of "Johnson" :
After clicking "Another Link" :
Update
As #User2561626 explain what he/she intended to, I update my answer as follow:
If you want a New Window pop up in stead of New Tab, you should change the code like:
<p:commandLink id="sidlink" actionListener="#{studentController.selectStudent(studData)}" oncomplete="window.open('studentinfo.xhtml', 'newwindow', 'width=300, height=250');">
<h:outputText value="#{studData.studentId}" styleClass="txtlink" />
</p:commandLink>
I change <h:commandLink> back to <p:commandLink>, make action as actionListener because we want to set the selected Student first, finally I add window.open in oncomplete attribute so that the new page will open in a new window but not tab.
Of course we need to edit the method studentController.selectStudent(), like this:
public void selectStudent(Student stu) {
selectedStu = stu;
}
As you can see, the return type is void now, and the only thing this method do is just set the selected Student.
Hope this may help.

how to show loading dialogue while bean method working?

i have a commandbutton that when i click i activate a methode as an action but this action take same time like 10 second. in this time i want to show a dialogue that have as msg loading and to be closed automatiquly when the action is finished. i tryed this like that but doesnt work its apear with last message that confirm that the action is finished well.
in JSF code :
<p:dialog id="basicDialog4" header="Information" widgetVar="dlg1" visible="#{gestionduplanning.displaydialog4}" style="background-image: none;background-color: #ffffff;">
<h:panelGrid columns="1" cellpadding="5" id="pn13236549532">
<h:outputText value="Chargement..." style="font-size: 16px;font-family:Times New Roman;" />
</h:panelGrid>
</p:dialog>
<p:commandButton icon="ui-icon-disk" onstart="#{gestionduplanning.chargementstart()}" action="#{gestionduplanning.planificationmanualglobal(gestionduplanning.chefequipedateplanifequipe)}" update="basicDialog2 basicDialog3" />
JSF managed bean :
public void chargementstart()
{
displaydialog4=true;
}
public void chargementstop()
{
displaydialog4=false;
}
any solution to show the loading dialogue waiting the action finish ??
You should look into BlockUI compoent which helps to block the UI when ajax request is procesing
https://www.primefaces.org/showcase/ui/misc/blockUI.xhtml

Resources