Primefaces commandButton not updating datatable. Is update attribute required - jsf

I changed my <h:commandButton> tag to a PrimeFaces <p:commandButton> tag on a search page and my datatable stopped displaying the results. After adding an update attribute things worked again. I'm just trying to understand whether it is how I implemented the overall functionality (viewscope, action vs actionListener, etc) or is the update attribute really required?
<h:form id="search_form">
<p:inputText id="search" value="#{searchBean.searchString}" />
<p:commandButton update="search_form" value="Search" action="#{searchBean.searchByString}" >
</p:commandButton>
<p:dataTable id="output" var="res" value="#{searchBean.results}" emptyMessage="No results found with given criteria">
etc...
#ViewScoped
#ManagedBean
public class SearchBean {
#Inject
private SearchRepository searchRepository;
private List<Results> res;
private String searchString;
public SearchBean() {
}
public String searchByString()
{
this.setRes(searchRepository.searchBySingleString(searchString));
}

One of the differences between h:commandButton and p:commandButton is that the second one performs an ajax request by default, while the first executes a plain POST request.
In an ajax request, you must specify what you want to process when form is sent and what to update when response happens. The p:commandButton updates nothing by default, that's why your table is not being properly filled.
See also:
Prime Faces Command Button vs. Default Command Button
Primefaces commandButton

Related

hiding and showing commandButton in jsf

I am new to JSF(PrimeFaces).
I have two commandButtons Do and Undo. I want only one button to be visible at one time.
like, When I click Do button, onclicking Do button should hide(performing its action simultaneously) and Undo button should be visible
and when i click Undo button onclicking it should hide and Do button should come back to active
I tried using
enable() and disable() methods but were of no use.
Can I get some help in achieving this. any predefined methods available?
Heard rendered attribute will help but couldnt understand what exactly will the attribute do .
Can someone explain pls
JSF rendered attribute will define if the component should be rendered/visible or not.
If
<h:commandButton value="Undo" rendered="#{false}" />
Then your above Undo button will be hidden.
rendered attribute can be bound to a ManagedBean property. In case if you want this dynamic, you have to update the component to see the result.
Here is a Small Example:
XHTML:
<h:panelGroup id="doBtnPG">
<h:commandButton value="Do" rendered="#{myBean.showDo}" action="#{myBean.doAction}">
<f:ajax render="unDoBtnPG"/>
</h:commandButton>
</h:panelGroup>
<h:panelGroup id="unDoBtnPG">
<h:commandButton value="Un Do" rendered="#{myBean.showUndo}" action="#{myBean.undoAction}">
<f:ajax render="doBtnPG"/>
</h:commandButton>
</h:panelGroup>
ManagedBean:
#ManagedBean
#ViewScoped
public class MyBean{
private boolean showDo=true;
private boolean showUndo=true;
public void doAction(){
showUndo=false;
}
public void undoAction(){
showDo=false;
}
//SETTER and GETTERS
}
In the above example, on clicking on one button the corresponding action method makes the property on which other button is being rendered as false, f:ajax will re render/update the other button's panelGroup to reflect the changes.
Since you marked this question as Primefaces, here is the XHTML code for Primefaces:
<h:panelGroup id="doBtnPG">
<p:commandButton value="Do" rendered="#{myBean.showDo}"
action="#{myBean.doAction}" update="unDoBtnPG"/>
</h:panelGroup>
<h:panelGroup id="unDoBtnPG">
<p:commandButton value="Un Do" rendered="#{myBean.showUndo}"
action="#{myBean.undoAction}" update="doBtnPG"/>
</h:panelGroup>
Notice that on Primefaces commandButtons you dont need to use f:ajax or p:ajax explicitly because they are Ajax by default.
Please note that the functions enable() and disable() provided by Primefaces are only client side. When disabled attribute is false and if you enable the button using enable(), it will not fire your action method.

Set bean value on click of selectbooleancheckbox

I have a bean class and a selectBooleanCheckbox in xhtml page. I want that on the click of the box the value should be set in the backing bean.
Here is code:
<h:selectBooleanCheckbox id="provisioningTargetCollector"
value="#{targetSource.provisioningTargetCollector}">
</h:selectBooleanCheckbox>
Bean Class:
public boolean isProvisioningTargetCollector() {
return _provisioningTargetCollector;
}
public void setProvisioningTargetCollector(boolean provisioningTargetCollector) {
_provisioningTargetCollector = provisioningTargetCollector;
}
But the getter and setter are called only on page load. How can I set the value in bean method on click of checkbox.
The model with be filled with form data only when submit button will be pressed. If you want to do partial update to the server you need to send an AJAX request. Luckily, starting from JSF 2 it has been quite simple with the introduction of <f:ajax> tag. It adds ajax capabilities to UIComponent instances that implement the ClientBehaviorHolder interface, i.e. components that are capable of triggering ajax requests.
To do partial update of compenets you need to specify their client ids in execute attribute of <f:ajax> tag. As the default value of execute attribute evaluates to #this, or the component to which the tag is attached it. As soon as you want to update only the given <h:selectBooleanCheckbox> you can do it as simple as nesting a pure <f:ajax /> tag within you checkbox, i.e.:
<h:selectBooleanCheckbox id="provisioningTargetCollector" value="#{targetSource.provisioningTargetCollector}">
<f:ajax />
</h:selectBooleanCheckbox>

JSF2: action and actionListener

From this answer by BalusC here Differences between action and actionListener, Use actionListener if you want have a hook before the real business action get executed, e.g. to log it, and/or to set an additional property (by <f:setPropertyActionListener>,. However when I decide to write some code to test this, the result is a bit different. Here is my small code
<h:form id="form">
<h:panelGroup id="mygroup">
<p:dataTable id="mytable" value="#{viewBean.foodList}" var="item">
<p:column>
#{item}
</p:column>
<p:column>
<p:commandButton value="delete"
action="#{viewBean.delete}"
update=":form:mygroup">
<f:setPropertyActionListener target="#{viewBean.selectedFood}"
value="#{item}"/>
</p:commandButton>
</p:column>
</p:dataTable>
</h:panelGroup>
</h:form>
Here is my bean
#ManagedBean
#ViewScoped
public class ViewBean {
private List<String> foodList;
private String selectedFood;
#PostConstruct
public void init(){
foodList = new ArrayList<String>();
foodList.add("Pizza");
foodList.add("Pasta");
foodList.add("Hamburger");
}
public void delete(){
foodList.remove(selectedFood);
}
//setter, getter...
}
According to BalusC, actionListener is more suitable here, but my example show otherwise.
The above code work great with action, but if I switch over to actionListener, then it does not quite work. It will take two clicks for me to delete an entry of this table using actionListener, while if I use action, it delete entry every time I click the button. I wonder if any JSF expert out there can help me understand action vs actionListener
Note If I switch to actionListener, my delete method become public void delete(ActionEvent actionEvent)
You're confusing action with actionListener. The actionListener runs always before the action. If there are multiple action listeners, then they run in the same order as they have been registered. That's why it doesn't work as expected when you use actionListener to call the business action and <f:setPropertyActionListener> to set (prepare) a property which is to be used by the business action. This problem was pointed out and fixed in your previous question Is this Primefaces bug or Mojarra/MyFaces bug.
Whatever you have in the delete() method is clearly a business action and should be invoked by action instead. A business action typically invokes an EJB service and if necessary also sets the final result and/or navigates to a different view.
I tried your example with original JSF's tags <h:commandButton> but I also get the same symptom. I believe if you specify actionListener attribute and at the same time, declare another listener with <f:setPropertyActionListener>, the listener in the attribute actionListener will be fired before the other.
UPDATE: I test my assumption with the following code:
Change your delete function to this one:
public void delete(){
this.selectedFood = "Chicken";
//foodList.remove(selectedFood);
}
Add <h:outputText id="food" value="#{viewBean.selectedFood}" /> inside <h:panelGroup id="mygroup">.
You will see that the outputText is always Chicken.

p:commandButton does not fire action

Here is the problem: actionlistener does not want to be fired
#ManagedBean(name="hotelsController")
#SessionScoped
public class HotelsController implements Serializable {
public void requestHotelAvail(ActionEvent event) {
request = new Request(df.format(arrivalDate), df.format(departureDate));
}
}
and xhtml
<h:panelgroup id="rooms"/>
<h:form id="hotelSearch">
<p:commandButton actionListener="#{hotelsController.requestHotelAvail}" value="submit" update="rooms" />
</h:form>
I have tried everything I could search of changed #managedbean to #component set import to import javax.faces.event.ActionEvent;
But it still does not fire anything.
Form is in a p:accordion and when used with h:commandbutton it works fine
EDIT: sorry for mislead. rooms updates after click but actionListener is not fired. so rooms will not get any new data. Important code in requestHotelAvail needs to be fired before updating rooms and its not.
EDIT2: PrimeFaces 2.2.1 - I've read whole manual to primefaces but theres no explanation to this as I've done all that it states
I've tried using action instead of actionListener without ActionEvent but it never do anything. using <h:commandbutton action="#{hotelscontroller.requestHotelAvail}"/> works great but I want that ajax engine to refresh only that rooms panelgroup
UPDATE: Now it works. Form couldn't be in <p:accordion> but why and how to enable it there? Form now I'll work without it.
I suspect the different behavior from h:commandLink comes from ajax/non-ajax processing.
By default - if you don't use f:ajax - h:commandLink is non-ajax and entire page is rerendered. Primefaces p:commandLink is using ajax and you indicate rooms as component to be updated. In your case rooms is outside form so it should rather be addressed as :rooms (mind the colon) instead of just rooms.
update: have you tried ajax with h:commandLink? It would be:
<h:commandButton action="#{hotelscontroller.requestHotelAvail}" value="submit">
<f:ajax render=":rooms"/>
</h:commandButton>
Also I'm not that familiar with primefaces but maybe you can try to explicitly indicate the component to process with additional process="#this" - although I would assume this to be default as in basic library.
You try to inspect the response:
Open Chrome or Firefox -> Inspect Element -> Network and follow the ajax call.

h:commandButton not working inside h:dataTable

I am trying to execute an action through commandButton inside a dataTable, but the action is not invoked when the commandButton is placed inside the datatable as shown below
<h:form>
<h:dataTable value="#{bean.list}" var="item">
<h:column>
<h:commandButton value="submit" action="#{bean.submit}" />
</h:column>
</h:dataTable>
</h:form>
When I move the commandButton out of dataTable, the action is successfully executed. What is the problem when commandButton is inside datatable? The commandLink has the same problem.
This problem can happen when the list behind #{bean.list} is not exactly the same during the HTTP request of processing the form submit as it was during the request of displaying the form. JSF will namely re-iterate over the list to locate the button pressed and invoke its action.
If the bean is request scoped and the list is not repopulated during bean's (post)construction, or the list's population depends on a request scoped variable which was lost during the form submit, then JSF will retrieve an empty or a completely different list while processing the form submit and thus won't be able to locate the button pressed and won't invoke any action.
The best fix is to put the bean in the view scope and ensuring that you're loading the data model the proper way.
#ManagedBean
#ViewScoped
public class Bean implements Serializable {
private List<Item> list;
#EJB
private ItemService service;
#PostConstruct
public void init() {
list = service.list();
}
// ...
}
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated - point 4
Benefits and pitfalls of #ViewScoped

Resources