I'm using Primefaces (version 3.0.1) p:tabView component, which displays dynamic number of tabs backed by a list in a model. Tabs inside TabView are closable. I'd like to remove list element associated with a tab by close event.
Here is my view:
<p:tabView id="tabView" var="iterator" value="#{bean.list}">
<p:ajax event="tabClose"
listener="#{bean.removeElement(iterator)}" process="#this" />
<p:tab id="tab" closable="true">
<h:outputText value="#{iterator.text}" />
</p:tab>
</p:tabView>
My bean handler:
public void removeElement(Element e) {
this.list.remove(e);
}
Element e is null in this case
I've also tried to use p:collector inside p:ajax element. There is example at primefaces.org showcase. According to it my event handler should look like
public void removeElement(TabCloseEvent event) {
// ...
}
But I don't know how can I get associated with tab list element.
All answers will be appreciated. Thanks in advance
public void removeElement(TabCloseEvent event) should be used, imo.
According to TabCloseEvent it has a method getData(). This should give you access to your model class. Disclaimer: I haven't used TabView the way you do yet, but it works this way for Primeface's Tree component (i.e. selection of a node). Could you post back your findings?
Related
I created an InputText component dynamically. And then i created a valuexpression and bind it to component and i created an ajax behavior and added it to keyup event. the problem is after keyup event triggered, bounded veriable is not set. it is always null. I can see the value but it is not assigned yo bounded veriable.
I uploaded a video youtube. you can see the problem easyly. Link is under this line.
http://youtu.be/M_WXDiSp8pM
Alsoi i added codes to github. if you want, you can look.
https://github.com/kissoid/hata.git
`#Override`
`public void processAjaxBehavior(AjaxBehaviorEvent event) throws AbortProcessingException {`
`System.out.println(deger);`
`System.out.println(inputText.getValue());`
`System.out.println(event.getComponent().getAttributes().get("value"));`
`}`
`});`
`inputText.addClientBehavior("keyup", blurBehavior);`
`panelGrid.getChildren().add(inputText);`
`}
`<h:form id="form1">`
`<p:messages autoUpdate="true" />`
`<p:panelGrid id="deneme" columns="1">`
`<p:commandButton value="tıkla" ajax="false" actionListener="#{indexBean.islem}" update="#form" />`
`</p:panelGrid>`
`<p:outputLabel id="testLabel" value="#{deger1}" /> `
`</h:form>`
I'm using PrimeFaces with JSF 2.0, I have this layout:
<h:panelGroup layout="block" id="panelGroup" binding="#{bean.boundPg}" />
<p:commandButton value="Update" action="#{bean.updateMe}" update="panelGroup" />
in which, the bean is SessionBean. By using log4j to debug I found out that the binding process called getBoundPg before executing the action updateMe. So the view is always out-of-date.
Do you know why and how to reverse that order? Thanks!
------------- Edit ---------------
I'm making a web app for a quiz game.
<h:panelGroup layout="block" id="pgContents" binding="#{bean.boundContents}" />
<p:commandButton value="Prev page" action="#{bean.prevPage}" update="pgContents" />
<p:commandButton value="Next page" action="#{bean.nextPage}" update="pgContents" />
pgContents contains many h:pannelGroups, each sub-group contains a label showing the content of a quiz, a h:inputText for the player to give their answer. Because of some reasons, I had to generate the children of pgContents programmatically.
The Prev page and Next page buttons will retrieve the prev/next group of quiz
Below is the bean (getters & setters are skipped)
#ManagedBean(name = "bean")
#SessionScoped
public class LessonHelper {
private int currentPage;
private HtmlPanelGroup boundContents;
public void prevPage() {
// decrease currentPage
// fetch contents
// add children for boundContents (label, inputText)
}
// nextPage() is similar
}
My problem is that, when I click the Prev/Next button, the getter getBoundContents is called first in binding process, and the prevPage()/nextPage() is called later, which cause the content always out-of-date.
Because this is the natural way, as you can see in this wonderful tutorial by BalusC: http://balusc.blogspot.com/2006/09/debug-jsf-lifecycle.html
Tell me exactly what do you want to do, show what's inside that bean and a solution to your problem will be found!
I have the following piece of code with a simple h:outputText pointing to a int and a p:commandLink to set a value:
<h:form id="f1">
<h:outputText id="text" value="#{testBean.index}"/>
<p:commandLink actionListener="#{testBean.test}" update="text">
<f:setPropertyActionListener target="#{testBean.index}" value="5" />
<h:graphicImage url="/images.png"/>
</p:commandLink>
</h:form>
The managed bean looks like this:
#javax.faces.bean.ManagedBean #ViewScoped
public class TestBean implements Serializable{
private int index; // getter/setter
#PostConstruct public void init() {
index = 0;log.log(Level.WARNING, "#PostConstruct");}
public void test(ActionEvent ae){
log.log(Level.WARNING, "Index: "+index);}
}
The bean is constructed correctly, and after the first click on the image the h:ouputText is updated to 5. But in my log message I only see Index: 0 during the first click on the image.
It's something similar like Jsf updates model value with old value, but I have the JSF #ManagedBean annotation.
Action listeners are invoked in the order they're definied in the view. You want to use action instead of actionListener. Even more, the action should in first place have been used to invoke a business action.
<p:commandLink action="#{testBean.test}" update="text">
<f:setPropertyActionListener target="#{testBean.index}" value="5" />
<h:graphicImage url="/images.png"/>
</p:commandLink>
See also:
Differences between action and actionListener
What is happening is that the test ActionEvent is getting fired before the request values have been applied.
To get a better understanding of the JSF phase lifecycle and when lifecycle events and ActionEvents fire, implement the Debug PhaseListener as specified in the following blog article.
http://balusc.blogspot.com/2006/09/debug-jsf-lifecycle.html
This should help you understand when request values are being applied, and when events are being fired.
I have a an a4j:outputPanel that is rendered based on some boolean condition:
<a4j:outputPanel id="someDisplayRegion" rendered="#{doc.ready && someClass.someBooleanMethod}">
// bunch of stuff //
</a4j:outputPanel>
Then on the same .xhtml page, I have a drop-down menu and selecting one of its options should reRender the above region:
<rich:dropDownMenu>
<f:facet name="label">
<a4j:commandLink styleClass="btn-pulldown">
<span><h:outputText value="Export"></h:outputText></span>
<span class="opener"></span>
</a4j:commandLink>
</f:facet>
<rich:menuItem submitMode="none">
<s:link
rendered="#{someOtherBooleanMethod}"
value="#exportDoc"
action="#{runSomething.exportDoc()}"
reRender="someDisplayRegion"
target="downloadfile"
><s:conversationId /></s:link>
</rich:menuItem>
</rich:dropDownMenu>
However, when I click on the menu item from the drop-down menu, it does not go into someClass.someBooleanMethod and thus, does not re-render someDisplayRegion. Am I doing something wrong?
Consider this point of the RichFaces documentation:
As with most Ajax frameworks, you should not attempt to append or
delete elements on a page using RichFaces Ajax, but should instead
replace them. As such, elements that are rendered conditionally should
not be targeted in the render attributes for Ajax controls. For
successful updates, an element with the same identifier as in the
response must exist on the page. If it is necessary to append code to
a page, include a placeholder for it (an empty element).
So add a wrapper around your outputPanel and target the wrapper in the reRender attribute.
<a4j:outputPanel id="wrapper">
<a4j:outputPanel id="someDisplayRegion" rendered="#{doc.ready && someClass.someBooleanMethod}">
// bunch of stuff //
</a4j:outputPanel>
</a4j:outputPanel>
<s:link reRender="wrapper" [...] />
s:link doesn't have reRender attribute, it's only available on RichFaces components.
rich:menuItem and s:link aren't the best of friends. (especially not in earlier version of RichFaces).
Is there a specific reason why you want to use s:link here ?
Putting the action and the reRender on the menuItem itself should work fine.
I don't understand why you think clicking on the menu item should go into someClass.someBooleanMethod and not into runSomething.exportDoc(). At what point are doc.ready and someClass.someBooleanMethod being set to true? You might put a debugging statement in your code that verifies these are being set to true. If they are set to true and your a4j:outputPanel is still not rendering then you have a problem. I use the s:link as you do here and it works, but I remember having to fiddle with it. Make sure the action fired in the s:link returns a String. "actions" have to return strings that can be used for navigation though in my case the page navigates to itself (like yours).
I'm trying to embed a Primefaces commandLink and call an action listener from a link inside a column of a Primefaces dataTable. Is this not possible? The "Test" onclick alert gets fired but it never makes it to my bean's method.
<p:dataTable var="location" value="#{adminBean.locations}">
<p:column headerText="Options">
<p:commandLink value="delete" actionListener="#{admin.deleteLocation}" onclick="alert('test')"/>
</p:column>
</p:dataTable>
bean code:
public void deleteLocation(ActionEvent e){
//delete logic here...
}
This is possible. Your actionListener should be called. Keep in mind that the p:commandButton uses ajax by default. So you should use the update attribute in order to define the components to be updated.
However, I don't know if this affects the actionListener. Did you try it with action instead of actionListener?
Here is an example how I got it working:
<p:commandLink action="#{spc.selectPatient(item)}"
ajax="false"
value="Open"/>
The bean method looks as follows:
public String selectPatient(Patient p) {
// do something
// return some outcome
}