I tried to alternate pages using ui:include on click of ajax (PrimeFaces) treenodes. The first page that load by default loads properly with all the components active but when I click on the other treenode to display another page, the latter page loads abnormally like having the dialog box visible below and the page hands.
I feel if I can force the page to reload partially as default on nodeSelect
index.jsf (gets loaded on login)
<p:layoutUnit position="west" size="270" header="Menu" collapsible="false" resizable="true">
<p:ajaxStatus style="width:16px;height:16px;">
<f:facet name="start">
<h:graphicImage value="../design/ajaxloading.gif"/>
</f:facet>
<f:facet name="complete">
<h:outputText value=""/>
</f:facet>
</p:ajaxStatus>
<h:form id="appsMainControl">
<ui:include src="/ui/appServices.jsf"/>
</h:form>
</p:layoutUnit>
<p:layoutUnit position="center">
<h:form id="centerControl">
<ui:include src="/ui/#{amb.appToGet}.jsf"/>
</h:form>
</p:layoutUnit>
The treeview component with the listener action. On node selection I want the child page to load appropriately
<p:layoutUnit position="west" size="270" header="Menu" collapsible="false" resizable="true">
<p:ajaxStatus style="width:16px;height:16px;">
<f:facet name="start">
<h:graphicImage value="../design/ajaxloading.gif"/>
</f:facet>
<f:facet name="complete">
<h:outputText value=""/>
</f:facet>
</p:ajaxStatus>
<h:form id="appsMainControl">
<ui:include src="/ui/appServices.jsf"/>
</h:form>
</p:layoutUnit>
<p:layoutUnit position="center">
<h:form id="centerControl">
<ui:include src="/ui/#{amb.appToGet}.jsf"/>
</h:form>
</p:layoutUnit>
The backing bean:
public void onNodeSelect(NodeSelectEvent event) throws Exception {
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
try {
appToGet = appsMainDAO.appToGet(event.getTreeNode().toString());
// ec.redirect("index.jsf");
// System.out.println("Got "+appToGet);
// appSubList = appsMainDAO.appsSubServicesList(appToGet, "Forms");
} catch (Exception ex) {
ex.printStackTrace();
Logger.getLogger(appsMainBean.class.getName()).log(Level.SEVERE, null, ex);
} finally {
}
}
Don't do that. You are rubbing JSF the wrong way and thus heading into a major catastrophe.
It's impossible to explain the whole life cycle here, but - until you really know your way around JSF - just assume that facelet pages are _not_supposed_ to work like HTML pages.
Instead, they should work like window applications, where you have a certain number of widgets that don't really appear or disappear - they can be put in tabs, they can become disabled, but they stay where they were from the beginning.
If there is a finite number of things to include, the easiest option is to include them all and add some rendered="#{gui.current=='component1'}", so only one of the components is visible.
Related
I have strange problem. I got a dataTable in which I present list of objects. Here's the code:
<h:dataTable value="#{XXXX.questions}" var="q" binding="#{varQ}" id="YYY">
<h:column>
<f:facet name="header">
header
</f:facet>
#{q.question}
</h:column>
<h:commandButton value="-" action="#{XXX.removeQuestion(varSurvey.index, varSec.index, varQ.rowIndex)}">
<f:ajax execute="#this" render="YYY"/>
</h:commandButton>
</h:column>
</h:dataTable>
As you can see - I got a button to remove one item from list. Method works fine, it removes element I want to be removed, but the datatable is not refreshed. I have no idea why.
My bean is SessionScoped, I got almost identical table in other part of my page, and it works which completely confuses me.
My bean method is like this :
public void removeQuestion(Integer surveyIndex, Integer sectionIndex, int questionIndex){
surveyList.get(surveyIndex).getSections().get(sectionIndex).getQuestions().remove(questionIndex);
}
so as you can see - it's almost basic example.
Here is code for my other table from same page:
<h:dataTable value="#{XXX.answers}" id="ZZZ" var="ans">
<h:column>
<h:inputText value="#{ans.choice}" styleClass="form-control">
<f:ajax event="change" execute="#this"/>
</h:inputText>
</h:column>
<f:facet name="footer">
<h:commandButton value="+" action="#{XXX.addMoreQuestions()}">
<f:ajax execute="#this" render="ZZZ"/>
</h:commandButton>
</f:facet>
</h:dataTable>
and method:
public void addMoreQuestions(){
answers.add(new Choice("question"));
}
And this works - when I click button, it adds one more question to list, and rerenders datatable with one more option.
The problem is when i use global status for ajax requests and ExtendedDataTable together strange bug happens - when i scroll down (i have large data loaded in the table) ajax request keep spaming in the console and the ajax status (picture loading) keep flashing.
there is my code:
<h:head></h:head>
<h:body>
<h:outputText value="TEsts with Extended Table" />
<h:form id="form">
<a4j:status id="waithStatus"
onstart="#{rich:component('waithStatusPanel')}.show();"
onstop="#{rich:component('waithStatusPanel')}.hide();">
<f:facet name="start">
<rich:popupPanel id="waithStatusPanel" autosized="true">
<h:graphicImage library="images" name="waith.gif" />
</rich:popupPanel>
</f:facet>
</a4j:status>
<h:panelGrid columns="2">
<rich:extendedDataTable value="#{testKrasi.tableList}" var="row" id="table"
selectionMode="none" clientRows="10" style="height:250px;width:400px"
iterationStatusVar="it">
<rich:column>
<f:facet name="header">#</f:facet>
#{it.index}
</rich:column>
<rich:column filter="#{testKrasi.vendorFilter}" filterType="custom">
<f:facet name="header">
vendor
</f:facet>
<h:outputText value="#{row[1]}"/>
</rich:column>
<rich:column filter="#{testKrasi.modelFilter}" filterType="custom">
<f:facet name="header">
model
</f:facet>
<h:outputText value="#{row[2]}"/>
</rich:column>
</rich:extendedDataTable>
</h:panelGrid>
</h:form>
</h:body>
</html>
and there is screenshot of the firebug console
the AJAX response is
<partial-response>
<changes>
<update id="javax.faces.ViewState">-2313795786913874202:5967295793801101249</update>
</changes>
</partial-response>
I don't know what to do... i try to fix this problem over a week now...
Please help me.
As you are using ajax lazy data loading for the table, these data load requests cause status to show.
You need either disable ajax data loading if you don't need that (refer to RichFaces Showcase to know how).
Or to disable status to show on the table updates. You can wrap the table into a4j:region to do this.
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.
I have a webapp where I select some content to be deleted. A modal pops-up displaying a preview of the image/flash selected. I hit a button and everything works fine. But, when I select another content to be deleted, the modal pops-up and, for a microsecond, it displays the previously deleted file which is then replaced by the new content I want to delete.
The code for showing the dynamic content is as follows:
For images:
<p:graphicImage value="#{controller.tempImage}" height="110"
id="imageID" />
For flash:
<p:media value="#{controller.tempImage}" width="110" height="110"
id="imageID" player="flash" />
Controller:
public StreamedContent getTempImage() {
try {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getRenderResponse() ) {
return new DefaultStreamedContent();
}
else {
tempImage = new DefaultStreamedContent(new FileInputStream("pathToFile"), "image/jpeg");
}
} catch (FileNotFoundException e) {
tempImage = new DefaultStreamedContent();
}
return tempImage;
}
I tried setting tempImage to null before loading and autoUpdate=true in the modal but no luck.
Delete button (the one that shows the delete modal):
<p:commandButton id="btnDelete" value="Delete" onclick="deleteModal.show();" actionListener="#{controller.initDelete}" update=":deleteForm">
Delete form (xhtml):
<h:form id="deleteForm" enctype="multipart/form-data" >
<p:dialog id="deleteDialog" widgetVar="deleteModal" modal="true" resizable="false" draggable="false" autoUpdate="true">
<p:outputPanel autoUpdate="false" >
<p:panelGrid id="panelId">
<p:row>
<p:column>
<p:panelGrid id="bannerPanel">
<p:row>
<p:column>
<p:graphicImage value="#{controller.tempImage}" height="110" id="imageID" />
</p:column>
</p:row>
</p:panelGrid>
</p:column>
</p:row>
<f:facet name="footer">
<p:row>
<p:column>
<p:commandButton id="doDeleteBtn" value="Delete"
actionListener="#{controller.delete}" >
</p:commandButton>
</p:column>
</p:row>
</f:facet>
</p:panelGrid>
</p:outputPanel>
</p:dialog>
Change from:
onclick="deleteModal.show();"
to:
oncomplete="deleteModal.show();"
This will ensure that your dialog is viewed after AJAX request is completed, not before it is started.
You should use onclick, when you are creating so called push buttons, the buttons with type="button", which are just executing some JavaScript. Default type of buttons in Primefaces is submit.
I have a JSF view that lists items in a collection in a Primefaces DataTable. The rightmost columns contain remove buttons. When a remove button is clicked, it is supposed to make an Ajax call, remove the corresponding item from the session variable Cart and update the view in-place. I would like the request and the view change to be as minimal as possible.
Here is what I have for this purpose:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Register user</title>
</h:head>
<h:body>
<f:view>
<h:form id="itemsForm">
<p:outputPanel id="items">
<p:dataTable value="#{cart.itemList}" var="item">
<p:column>
<f:facet name="header">
<h:outputText value="name" />
</f:facet>
<h:outputText value="#{item.product.description}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="quantity" />
</f:facet>
<h:outputText value="#{item.quantity}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="" />
</f:facet>
<p:commandButton icon="ui-icon-close" title="remove from cart">
<p:ajax listener="#{cart.removeItem}"
update="form:itemsForm"
process="#this" />
</p:commandButton>
</p:column>
<f:facet name="footer">
Total amount: ${cart.totalAmount}
</f:facet>
</p:dataTable>
</p:outputPanel>
</h:form>
</f:view>
</h:body>
</html>
Accordingly, I have the following method in Cart.java
public void removeItem() {
System.out.println("REMOVE REQUEST ARRIVED");
}
However, the removeItem method isn't even executing when I click a remove button.
So my questions are:
1) What is wrong with my Ajax call? What changes should I make to my XHTML?
2) How do I handle the request in the removeItem method and return a response?
3) How do I update the footer, which displays the totalAmount?
You can pass #{item} as a parameter of your method call in the actionListener.
Your .xhtml page should look like this:
<p:dataTable id="cartTable" value="#{cart.itemList}" var="item">
<p:column>
<f:facet name="header">
<h:outputText value="" />
</f:facet>
<p:commandButton icon="ui-icon-close" title="remove from cart"
actionListener="#{cart.removeItem(item)}" update="cartTable" />
</p:column>
</p:dataTable>
And this is the method removeItem of your ManagedBean:
#ManagedBean
#ViewScoped
public class Cart {
private List<Item> itemList;
public void removeItem(Item item) {
itemList.remove(item);
}
}
1) <p:commandButton uses ajax by default , so instead placing the p:ajax use the action or actionListener of the <p:commandButton
2) I would use the action of the button and return null
3) update="#form" should update the entire form and this will update the entire table
here an example of a working button (link) from my page , i used the f:setPropertyActionListener to "pass" some data to the delete method
<p:commandButton action="#{cart.removeItem}" icon="ui-icon-close" title="remove from cart" update="#form" process="#this" >
<f:setPropertyActionListener
target="#{cart.selectedItem}"
value="#{item}" />
</p:commandButton>
in your class add this
private Item selectedItem;
public Item getSelectedItem() {
return selectedItem;
}
public void setSelectedItem(Item selectedItem) {
this.selectedItem = selectedItem;
}