ActionListener not calls with ajax=false - ajax

I'm facing a strange issue with JSF, primefaces 5.2, glassfish 4, CDI ViewScoped Named beans. I've searched the forum but mostly people got stuck with ajax not working, while here Command button actionListener works with process="#form" but with ajax="false" it does not, rather just a full page refresh occurs. What i
understand that JSF default behavior is process="#form" but here i have to explicitly define it, without which ajax does not work. I've double checked and there are no nested forms in the hierarchy. Could it be something wrong with my development environment or am i doing something terribly wrong. Here is my jsf page
<h:panelGroup id="selectedtestpanel3">
<h:form id="SelectedTests3" >
<p:dataTable id="selectedTestDataTable3" value="#{aTestRegController.testprofilelist}" var="seltestprofile"
rowKey="#{aTestRegController.selectedToString(seltestprofile)}" tableStyle="width:auto" resizableColumns="true"
selectionMode="single" selection="#{aTestRegController.selected}" style="vertical-align:top;"
>
<p:ajax event="rowSelect" listener="#{aTestRegController.testprofilePull(aTestRegController.selected)}"
update="patientRegWizard:SelectedTests3, patientRegWizard:displayprices"/>
<p:column headerText="Test/Profile Name" width="10">
<h:outputText value="#{aTestRegController.selectedTestProfileName(seltestprofile)}"/>
</p:column>
<p:column headerText="Price" width="10">
<h:outputText value="#{aTestRegController.selectedTestProfilePrice(seltestprofile)}"/>
</p:column>
<p:column headerText="Container" width="10">
<h:outputText value="#{aTestRegController.selectedTestProfileContainer(seltestprofile)}"/>
</p:column>
</p:dataTable>
<p:commandButton id="saveReg" icon="ui-icon-plus" value="Save Test Registration01"
actionListener="#{aTestRegController.createVoucher()}"
disabled="#{empty aTestRegController.testprofilelist}"
ajax="false"
/>
</h:form>
</h:panelGroup>
Here are some lines of managed bean
#Named("aTestRegController")
#ViewScoped
public class ATestRegController implements Serializable {
#EJB
private facades.PatientFacade patientFacade;
#Inject
private facades.VoucherFacade voucherFacade;
#Inject
private facades.TestFacade testFacade;
public void createVoucher(){
this.biolist2=null;
this.hemolist2=null;
this.microlist2=null;
this.speclist2=null;
this.radiolist2=null;
try{
//if(this.getItem()!=null){
if(true){
tempSessionVars();
this.item=fillVoucher();
this.create();
List<Voucherdetails> cashvdlist = new ArrayList<>(this.item.getVoucherdetailsCollection());
String testprofilecashsliplist=AReportPrint.convertVoucherdetailsToString(cashvdlist);
AReportPrint.printCashSlip(testprofilecashsliplist, item);
iterateSelection();
profilelist=new ArrayList();
profilemap.clear();
testlist=new ArrayList();
testmap.clear();
}
}catch(Exception e){
e.printStackTrace();
}
}

Related

Site doesn't reload after button click

I developed a view to save Child-objects. Everything works fine but to see my additional objects in the <p:dataTable> I always have to reload the site manually.
Below the code for the <p:commandButton> which sends the form-data to my controller class.
<h:panelGrid columns="3">
<p:commandButton value="Save"
action="#{childController.doSaveChild}"
oncomplete="PF('childAddDialog').hide()"
update=":childForm"/>
</h:panelGrid>
I already tried to use ajax="false", but it doesn't work.
What can I do to get the site reloaded after click on save-button?
UPDATE:
<p:dataTable> from my view.xhtml:
<h:form id="childForm">
<p:dataTable id="childTable" var="child"
widgetVar="childTable" value="#{childController.children}"
paginator="true" rows="10" paginatorPosition="bottom"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink}
{PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}
{Exporters}"
rowsPerPageTemplate="10,25,50">
<p:column headerText="Firstname"
filterBy="#{child.firstName}"
sortBy="#{child.firstName}" filterStyle="display:none">
<h:outputText value="#{child.firstName}"/>
</p:column>
<p:column headerText="Lastname"
filterBy="#{child.lastName}"
sortBy="#{child.lastName}"
filterStyle="display:none">
<h:outputText value="#{child.lastName}"/>
</p:column>
<p:column headerText="Birthday"
filterBy="#{child.birthday}"
sortBy="#{child.birthday}"
filterStyle="display:none">
<h:outputText value="#{child.birthday}"/>
</p:column>
</dataTable>
</form>
Here the methods for providing the children for the view:
public Collection<Child> getChildren(){
return children;
}
#PostConstruct
public void initList(){
setChildren(childService.getAllChildren());
}
The xhtml-code from above is fine.
To get the site auto-updated it is necessary to load the list with all children again after the save-method in controller.
public void doSaveChild(){
childService.saveChild(child);
child = null;
initNewChild();
initList(); //this is needed to get up-to-date list in view
}
You could either do it via javascript:
<p:commandButton value="Save"
action="#{childController.doSaveChild}" process="#form" update="#none" oncomplete="location.reload();"/>
or a return String in your action method:
public String doSaveChild(){
//your logic
return "/yourpage?faces-redirect=true"}

Primefaces CommandButton not working inside DataTable

I have a primefaces commandButton outside of a data table which functions properly. Inside a dataTable, I have the exact same commandButton, but when the one inside the dataTable is clicked, it doesn't call the actionListener:
<h:body>
<h:form>
<p:messages autoUpdate="true" showDetail="true" closable="true"/>
<p:accordionPanel >
<p:tab title="Visualize data">
<p:commandButton value="Add Domain" actionListener="#{TripleStoreController.addDomain('Domain')}"
update="DomainSkillTable"/>
<p:dataTable
id="DomainSkillTable"
var="result"
value="#{TripleStoreController.domainResults}"
rowKey="#{result}">
<p:column>
#{result}
</p:column>
<p:column>
<p:commandButton value="Add Domain" actionListener="#{TripleStoreController.addDomain('Domain')}"
update="DomainSkillTable"/>
</p:column>
</p:dataTable>
</p:tab>
</p:accordionPanel>
</h:form>
</h:body>
it should be work.
there is no error, i had just copy and and make back bean for the same method TripleStoreController.addDomain('Domain') in my java class the method signature like public void addDomain(String s) and method worked.
even i got the value pass by command button as 'Domain' in my back bean.
in my case, i just made my bean from #RequestScoped to #ViewScoped and it solved my problem.

SelectOneRadio inside subtable ajax call not working

I'm using primefaces 3.4.1 and I'm trying to use a SelectOneRadio with an ajax call inside a subtable
but it doesn't work, the ajax listener isn't called
<p:dataTable id="competenciesTable" var="competency" value="#{evaluationControl.currentEvaluation.evaluatedCompetencies}">
<f:facet name="header">
<h:outputText value="#{gchmsg['global.competencies']}" />
</f:facet>
<p:subTable id="descriptorsTable" var="descriptor" value="#{competency.evaluationDescriptors}">
<f:facet name="header">
<h:outputText class="strong" value="#{competency.competency.name}" />
</f:facet>
<p:column>#{descriptor.descriptor.description}</p:column>
<p:column>
<p:selectOneRadio required="true" styleClass="calification_scale" id="descriptorCalification" value="#{descriptor.calification}" converter="calification">
<f:selectItems value="#{competency.competency.calificationSchema.scales}" var="scale" itemLabel="#{scale.qualitativeValue}" itemDescription="#{scale.description}" itemValue="#{scale}" />
<p:ajax process="#this" listener="#{evaluationControl.handleRadioChange}" update=":evaluationForm:finalResultText, descriptorCalificationMsg" />
</p:selectOneRadio>
<p:message id="descriptorCalificationMsg" for="descriptorCalification" display="icon" />
</p:column>
</p:subTable>
</p:dataTable>
The evaluationControl is a SessionBean and the method is
public void handleRadioChange() {
log.debug("Listener called");
}
Help is appreciated.
After too many debugging and tests I finally found the issue, the primefaces Subtable component doesn't put back the values to the Backing Bean for itself you must process the whole DataTable component, so I had to remove the required="true"(to avoid validation errors) for each selectOneRadio and add the process="competenciesTable" to the p:ajax
You can try, deleting process="#this". It worked in my case. I'm not sure why it happens with p:subTable because I've never had this issue with p:dataTable.

Navigate to another page on rowselect of datatable in primefaces

I have a primefaces datatable where number of records are displaying.
I want navigate to another page on the rowSelect event (to edit the selected entity for example).
The closest sample/demo I could find was use the p:ajax tag to bind the rowSelect event to a listener method
http://www.primefaces.org/showcase-labs/ui/datatableRowSelectionInstant.jsf
I also got one article for the same http://forum.primefaces.org/viewtopic.php?f=3&t=14664
, I tried to implement in same as they did.But it also didn't worked.
I am trying in this way and guide me If I missed anything.
<p:dataTable var="product" value="#{addPatientBB.patientAddList}" paginator="true" rows="10"
selection="#{addPatientBB.pat}" selectionMode="single">
<p:ajax event="rowSelect" listener="#{addPatientBB.onRowSelect}" />
<p:column>
<f:facet name="header">
<h:outputText value="FirstName" />
</f:facet>
<h:outputText value="#{product.firstName}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Email" />
</f:facet>
<h:outputText value="#{product.email}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Gender" />
</f:facet>
<h:outputText value="#{product.gender}" />
</p:column>
</p:dataTable>
And Backing bean is :
#ManagedBean
#ViewScoped
public class AddPatientBB implements Serializable
{
private Patient pat;
public Patient getPat()
{
System.out.println("tried to get pat");
return pat;
}
public void setPat(Patient pat)
{
this.pat = pat;
System.out.println("tried to set pat");
}
public void onRowSelect()
{
System.out.println("inside onRow select Method");
ConfigurableNavigationHandler configurableNavigationHandler = (ConfigurableNavigationHandler) FacesContext.getCurrentInstance().getApplication().getNavigationHandler();
System.out.println("navigation objt created");
configurableNavigationHandler.performNavigation("Page?faces-redirect=true");
// Page is my navigation page where I wish to navigate named as
// "Page.xhtml"
System.out.println("Navigation executed");
}
}
So how can I navigate to another page on rowselect event? and how can display its values after navigationg the form.
I am able to go inside onRowSelect() method , actually problem is he is not able to get or understood that path :
configurableNavigationHandler.performNavigation("Page?faces-redirect=true");
so he is not able to print any logs after this line.
why is it so? is it because of I am using Liferay?
Pla guide me.
Well i think the onRowSelect is never executed because you defined it wrong.
Try this:
public void onRowSelect(SelectEvent event)
{
FacesContext.getCurrentInstance().getExternalContext().redirect("page.xhtml?id=" +pat.getId());
}
If u are using FacesServlet then use.jsf instead of .xhtml
public void onRowSelect(SelectEvent event)
{
FacesContext.getCurrentInstance().getExternalContext().redirect("page.jsf?id="+pat.getId());
}

DataTable Order by column erase values

I have PrimeFaces dataTable that is been filled by a Ajax call.
When I click on a column title, to order its values, the values disappear.
<p:commandButton value="Pesquisar" actionListener="#{requestController.listRequests}" update="dataTable" />
Here is my view:
<p:dataTable id="dataTable" var="order" value="#{requestController.backing.requestsList}"
paginator="true" rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}">
<p:column sortBy="#{order.companyRequest}">
<f:facet name="header">
<h:outputText value="Pedido" />
</f:facet>
<h:outputText value="#{order.companyRequest}" />
</p:column>
<p:column sortBy="#{order.company.companyName}">
<f:facet name="header">
<h:outputText value="Cliente" />
</f:facet>
<h:outputText value="#{order.company.companyName}" />
</p:column>
<p:column sortBy="#{order.emissionDate}">
<f:facet name="header">
<h:outputText value="Data" />
</f:facet>
<h:outputText value="#{order.emissionDate}">
<f:convertDateTime pattern="dd/MM/yyyy"/>
</h:outputText>
</p:column>
<p:column sortBy="#{order.requestSituation.description}">
<f:facet name="header">
<h:outputText value="Status" />
</f:facet>
<h:outputText value="#{order.requestSituation.description}" />
</p:column>
<p:column>
<f:facet name="header">
</f:facet>
<h:form>
<h:commandLink value="Detalhes"/>
</h:form>
</p:column>
</p:dataTable>
EDIT
RequestController
#ManagedBean
#RequestScoped
public class RequestController implements Serializable
{
private RequestBacking backing;
public RequestController()
{
backing = new RequestBacking();
}
public void changeEventListener(ValueChangeEvent e)
{
backing.requestSearchType = e.getNewValue().toString();
}
public void change()
{
switch (backing.requestSearchType)
{
case "data":
backing.mask = "99/99/9999";
backing.maskSize = "10";
break;
case "cnpj":
backing.mask = " 99.999.999/9999-99";
backing.maskSize = "20";
break;
default:
backing.mask = "";
backing.maskSize = "50";
}
}
public void listRequests() throws ParseException
{
CompanyVO companyVO = new CompanyVO();
switch (backing.requestSearchType)
{
case "cnpj":
companyVO.setCnpj(backing.requestSearchValue);
break;
case "cliente":
companyVO.setCompanyName(backing.requestSearchValue);
break;
case "pedido":
backing.requestVO.setCompanyRequest(Integer.parseInt(backing.requestSearchType));
break;
}
SupplierVO supplierVO = new Support().getUserSession().getSupplier();
backing.requestVO.setEmissionDate(new Support().convertDate(backing.requestSearchValue));
backing.requestVO.setSupplier(supplierVO);
backing.requestVO.setCompany(companyVO);
backing.requestsList = new ArrayList<>(backing.getBo().getRequest(backing.requestVO));
if (backing.requestsList.isEmpty())
{
FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_WARN, "Nenhum registro encontrado!", null);
FacesContext.getCurrentInstance().addMessage(null, facesMessage);
backing.requestsList = null;
}
}
..backing getter and setter
}
My requestsList is on my RequestBacking where I have all my getters and setters, please correct me if there is a better way of doing this, I'm using it because it leaves my controller cleaner.
public List<RequestVO> requestsList;
Apparently the value="#{requestController.backing.requestsList}" didn't return the same value as it did on the initial request. That can happen if it's a request scoped bean and/or if the requestsList is populated on every request based on a request based variable.
That's just a design mistake. Put the managed bean in the view scope and make sure that you aren't doing any business logic in a getter method. The nested class backing is also suspicious or it must be a poor naming.
See also:
Why JSF calls getters multiple times
How to choose the right bean scope?
Update in a nutshell, your bean should look something like this:
#ManagedBean
#ViewScoped
public class Orders {
private String query; // +getter +setter
private List<Order> results; // +getter (no setter required)
#EJB
private OrderService service;
public void search() {
results = service.search(query);
}
// Add/generate normal getters/setters (don't change them!)
}
and your view should look like this:
<h:form>
<p:inputText value="#{orders.query}" />
<p:commandButton value="Search" action="#{orders.search}" update=":tableForm" />
</h:form>
<h:form id="tableForm">
<p:dataTable value="#{orders.results}" var="order" ... rendered="#{not empty orders.results}">
...
</p:dataTable>
<h:outputText value="No results found" rendered="#{facesContext.postback and empty orders.results}" />
</h:form>

Resources