Action not triggered when button is enabled/disabled with ajax - ajax

I am stuck with a problem that doesnt make any sense to me. I have a listbox which fires selectionChange-Events with simple Ajax. The idea is that the edit-button isnt enabled until a item in the list is selected. So I created the following code.
<h:form>
<h:selectManyListbox value="#{bean.selectedIds}">
<f:selectItems value="#{bean.listOfItems}" />
<f:ajax render="edit"
listener="#{bean.selectionChanged}" />
</h:selectManyListbox>
<br />
<h:commandButton id="add" value="#{msgs.add}"
action="#{bean.addNew}" />
<h:commandButton id="edit" value="#{msgs.edit}"
disabled="#{bean.editButtonDisabled}"
action="#{bean.edit}" />
</h:form>
The button is enabled and disabled as I wish but as it turns out, the edit-button isnt triggering any action (I added some sysout to the add- and edit-method in the bean and the edit-method is never called)...instead the html changes. The above code is nested in a simple div. When I click edit, the whole form is outside of that div.
When I add this ajax-behavior to the add-button, the same happens there and vice versa, when I remove the disabled-attribute from the edit-button everything works???
I already had a look at BalusC answer here but I couldnt find any mistake related to that list. No nested forms and so on...its just a simple page with a template.
I am using Mojarra 2.1.2 on JBoss 7.1.Final.
Any help is appreciated. Thanks

This issue is covered by point 5 of the answer which you've linked.
The rendered attribute of the component and all of the parent components should not evaluate to false during the apply request values phase of the form submit request. JSF will namely recheck it then as part of safeguard against tampered/hacked requests. Putting the bean in the view scope and/or making sure that you're preinitializing the condition in (post)constructor of the bean should fix it. The same applies to the disabled attribute of the component, which should not evaluate to true during processing the form submit.
I suggest to change #RequestScoped on BikeManagementPanelBean to #ViewScoped.

try something like this
<h:commandButton id="edit" value="#{msgs.edit}"
disabled="#{bikeManagementPanelBean.editButtonDisabled eq false}"
action="#{bean.edit}" />
try to wrap it again with the <h:panelGroup> and render the instead of the button...

Related

Primefaces p:selectOneMenu or p:selectBooleanCheckbox not firing change-event depending on if I use h:form

I'm working with Primefaces 5.3.
First, I implemented functionality to change visibility of a p:selectOneMenu depending on the value of a p:selectBooleanCheckbox according to this post:
Enabling and disabling components via select checkbox
This works so far, if I use the h:form.
Next, I wanted to update the values in the bean, as chosen in the p:selectOneMenu. This is where my question starts: Even if i use p:ajax to explicitly call a listener, it won't get called. This is my code:
<h:panelGrid>
<p:selectOneMenu value="#{schedulerCDIBean.selectedParentTask}" var="parentTask" id="taskDependence" disabled="#{task.dependsOn != 'true'}">
<p:ajax event="change" listener="#{schedulerCDIBean.taskToAddListener}"/>
<f:selectItems id="taskDependenceItems" value="#{schedulerCDIBean.taskWebDataObjectList}" var="item" itemLabel="#{item.taskName}"
itemValue="#{item}" />
<p:column>
<h:outputText value="#{parentTask}"/>
</p:column>
</p:selectOneMenu>
</h:panelGrid>
And here is how I enable/disable the selectOneMenu:
<p:selectBooleanCheckbox id="dependsOnTask" value="#{task.dependsOn}" itemLabel="Depends On">
<p:ajax update="taskDependence" process="#this"/>
</p:selectBooleanCheckbox>
All this lives inside a p:tab of the p:accordionPanel where 'task' is the var of my DataObject-List.
As mentioned by #BalusC in this post: commandLink/commandButton/ajax backing bean action/listener method not invoked (Possible Causes: 2),
"You cannot nest multiple UIForm components in each other."
So, if i remove the h:form directive, the call to the listener in the bean works. But now, the value of the p:selectBooleanCheckbox is always set to 'false', and thus the component is not being updated to visible.
I found a post here, where OP had the same problem and solved it by adding the h:form directive.
EDIT:
My 'form' is a ui:composition and starts like this <ui:composition template="/templates/pages/mainPage.xhtml">, where mainPage.xhtml contains h:head and includes the 'header.xhtml' by using ui:include, and there is a h:form. But this h:form is already closed before, so the problem isn't here.
Well, I don't want to go the way with adding the h:form again, as it leads to unspecified behaviour. But what am I doing wrong, if my p:selectBooleanCheckbox values are not being set correctly?
Thank you for your help!
UPDATE
The problem was not the h:form, as it actually wasn't nested. Now I'm just still stuck with the listeners for the p:selectOneMenu, as they aren't being called. I also tried setting partialSubmit="true" on the <p:ajax />, which did not lead to a solution so far.
Thanks for your help, guys. With your help I fixed the problem.
Just as if someone else experiences similar problems, here a few things to check:
Check #BalusC's answer here, as also mentioned in #irieill's answer.
Check if you're having equals() and hashCode() of the object you're willing to show in the selectOneMenu.
The solution for my situation actually was mentioned in #irieill's comment:
[..]Not providing a proper converter does not raise any exceptions but faces error messages. So try to add a <p:growl autoUpdate="true" /> to your page to see if any conversion error is raised. If so, add a propper converter to your selectOneMenu.
I think, that's also what #BalusC said at point 3 of his list of possible causes.
See also: How to write a custom converter for <p:pickList>, Custom converter in JSF 2.0, PrimeFaces ShowCase: SelectOneMenu
As mentioned by #BalusC in this post: commandLink/commandButton/ajax backing bean action/listener method not invoked
Also note point 1. You must enclose your input components with a <h:form /> tag.
Well, I don't want to go the way with adding the h:form again, as it leads to unspecified behaviour.
As i understand, you are misusing the tag or you do not understand how to use it. Just enclose your whole page (or at least all input components) in one <h:form /> tag and it should work.
Can you please update your question with the page code also containing the lines where you placed the <h:form /> tag(s).

<f:ajax> executing different forms

So I have 2 forms and a command button with f:ajax attached on it. I want to execute the second form on click on button but it seems that it ignores when I'm passing the form's id on execute attribute. But when I replace it with 'execute=":form1"' it runs correctly(the information from the form is sent to server). Can someone tell me why won't work with the id of second form, or how can I achieve this: with one button to execute any form i want from the page.( as it is now no information is sent to server, only the listener is called).
Code bellow:
<h:form id="form1">
<h:panelGrid id="inputSection" >
<h:inputText id="input1" value="#{counterMB.number1}" />
<h:inputText id="input2" value="#{counterMB.number2}" />
</h:panelGrid>
<h:outputLabel id="sumResponse2" value="#{counterMB.sum}" />
</h:form>
<h:form id="form2">
<h:panelGrid id="inputSection" >
<h:inputText id="input1" value="#{counterMB.number1}" />
<h:inputText id="input2" value="#{counterMB.number2}" />
</h:panelGrid>
<h:outputLabel id="sumResponse2" value="#{counterMB.sum}" />
</h:form>
<h:commandButton value="Sum numbers">
<f:ajax event="click" execute=":form2" listener="#{counterMB.sum}" render=":form2 :form1"/>
</h:commandButton>
Update:
so to be more explicit: from what I have read I can use ajax to update/refresh etc some parts of a page instead of refreshing the whole page. What i have tried to do is group some components in different forms and execute a form at a time to see how it behaves. It works perfectly if I use the id of first group(form) but doesn't work at all if I use the id of the second form(it calls the action but doesn't submit any data from any form). I don't understand why. (PS for those who claim i lack some knowledge : this is the reason of asking questions isn't it? I'm trying to learn some new stuff)
It seems that you are lacking basic knowledge of how jsf works. A command button must be inside a form. And it's not possible to submit 2 forms with one single button.
The attribute execute of f:ajax tells which components to process, for example if you have 2 input texts, you can process only one and ignore the other using this attribute. but it's not possible to do what you are trying to do.
It doesn't really make sense to submit 2 forms and execute a single action method once.. there's no point in having 2 forms. why don't you put everything inside a single form?
In your current solution, you use a h:commandButton outside of any h:form - this is a little bit against HTML and JSF, so don't count on it. What I would suggest is
if you use Richfaces, put a a4f:jsFunction in every form and trigger the resulting Javascript from anywhere
if you use Primefaces, put a p:remoteCommand in every form and trigger the resulting javascript from anywhere
if you neither use any of them, put a <h:commandButton /> in every form, set the style hidden and use javascript to submit the form.
Hope it helps...

JSF Ajax Link performs partial ajax render before the link action

I have the following in a JSF page:
<h:commandLink action="#{manager.removeEntity(row.id)}" value="Remove">
<f:ajax event="action" render=":form:table" />
</h:commandLink>
The rendering works perfectly, though it renders the component before the action is performed. (I know this through logging)
Is there any way for me to render the components after the action function is performed on the server?
Any help will be greatly appreciated
Update 1
I removed the action attribute and added a listener to the tag, though unfortunately it doesn't seem to help, the method is still called after the component tree is rendered.
<h:commandLink action="#{manager.removeEntity(row.id)}" value="Remove">
<f:ajax event="action" render=":form:table" />
</h:commandLink>
The rendering works perfectly, though it renders the component before the action is performed. (I know this through logging)
This is not true. You must be misinterpreting the logging. Perhaps you have put a log statement inside the getter method of the table's value in a misassumption that it's only called during render response. This is thus not true. The getter is called as many times as an EL expression referencing the property is been evaluated. This can happen in a different phase before and after invoke action phase. As you've the command link inside a datatable, the table's value getter method will also be called during apply request values phase in order to find find the row associated with the link.
Pass FacesContext#getCurrentPhaseId() along with the log to learn during which phase the getter method is been called. Also note that doing business job (like calling database and so on) inside a managed bean getter method is a bad idea.
See also:
Why JSF calls getters multiple times
You can use the listener of the f:ajax to execute your logic and pass the row.id with one of the following ways (remove the action="#{manager.removeEntity(row.id)}")
Pass a parameter on ajax call 1
Pass a parameter on ajax call 1
kinda late but i had the same problem.
The ajax renders before my jsf logic completed. My solution? Well i added a confirmation dialog. I know it's not a technical solution but hey, it works. Once the user presses ok on the dialog(which takes about a sec, in this time the logic should be done) the component should be rendered. Good Luck Hope this helps.
Before changes:
<h:commandButton action="#{bean.buisnessLogic(param1, param2)}">
<f:ajax
execute="components"
render="table"
/>
</h:commandButton>
After Changes:
<h:commandButton onclick="javascriptCofirm();" action="#{bean.buisnessLogic(param1, param2)}">
<f:ajax
execute="components"
/>
</h:commandButton>
<h:commandButton id="button" style="display: none">
<f:ajax
render="table"
/>
</h:commandButton>
javascript:
function javascriptConfirm() {
bootbox.alert("Se agrego la accion con exito.", function () {
var boton = document.getElementById("button");
boton.click();
});
e.preventdefault();
return false;
}
What i did:
Ok so before changes were made. My commandButton would render the table before the registers were added. For example i would add row 2 and it would not show changes until the page was refreshed or row 3 was added. I did some research and my conclusion is that jsf translate the ajax tag to javascript, and javascript directly executes the code without waiting for the the action to finish.
Solution:
So now i remove the render attribute from ajax and i create another commandButton and in the new commandButton i add the render. The javascriptConfirm method calls the button and "clicks it". This renders the page, but by the time they confirm the buisness logic is complete. So yeah. This is probably confusing. Well whatever you just comment and i will try to respond as quickly as possible (probably not that quick).

How to execute another <h:form> using <f:ajax>?

I've noticed that this doesn't work for me and I'm wondering if it's just not possible:
<h:form id="one" prependid="false" >
<h:commandButton>
<f:ajax execute=":two">
</h:commandButton>
</h:form>
<h:form id="two" prependid="false">
... content ...
</h:form>
Whenever I click the button above ,I can see that the values on form two are not executed as expected.
Is this the normal JSF behavior?
To 'trick' it, I usually insert a hidden button in form two and trigger it using JavaScript code when the button in form one is clicked. But that's a 'trick' and makes me work extra when I'm not sure I have to.
I should mention the rendering another form is possible.
Could the prependid attribute be causing problems?
Thanks in Advance!
UPDATE Adding more information that might be relevant - adding the prependid="false" to the forms as it is used in the actual code.
No, that's not possible with <f:ajax>. It just submits the parent form. The execute merely tells JSF which components it has to process based on the submitted data, not which request parameters the client side have to send. The button has really to go in the form where it belongs.

p:commandButton update doesn't work in ui:include

I want to update a part of a page by PPR.
This is the part of page that i want to update:
<h:panelGroup id="aggiungiAuto"
rendered="#{!autoBean.operazioneOk}">
<ui:include src="../component/aggiungi_auto.xhtml"/>
</h:panelGroup>
While this is the commandButton present in aggiungi_auto.xhtml
<p:commandButton value="Submit"
update="growl aggiungiAuto aggiungiFoto"
actionListener="#{autoBean.insert}"/>
Any Idea?
JS/Ajax works on the client side, not on the server side. JSF works on the server side, not on the client side. When you instruct JSF to not render the component to HTML, then nothing will be present in the client side, so JS/Ajax will be unable to locate the HTML element to refresh/update.
You need to wrap it in another <h:panelGroup>.
<h:panelGroup id="aggiungiAuto">
<h:panelGroup rendered="#{!autoBean.operazioneOk}">
<ui:include src="../component/aggiungi_auto.xhtml"/>
</h:panelGroup>
</h:panelGroup>
This way the <span id="aggiuniAuto"> is always present in the client side, so JS/Ajax will be able to update it with the new HTML data generated by JSF.
So I was having this kind of a problem with PrimeFaces (the above answer not being sufficient this time), and I also discovered a solution.
Part of the problem I think was that I was using ui:include recursively. For whatever reason, PrimeFaces was irrationally causing UI components to be bound to the backend data out-of-sync; e.g., when an "Add" button was clicked, a new value would be created in the UI, but then the data for it would be ripped out of the values for the section below, etc...
The explanation? "[O]n a viewscoped bean, a hidden field is added to the form to hold post-back data[;] if that field is not included with the process, then the bean will lose context." This particular problem is prevalent with ui:include recursion especially. Solution (all regarding the p:commandButton or other actionable component):
Ensure that update and process are pointing to a JSF component, not a regular HTML component.
update the next scope up if it breaks (goes out-of-sync with the binding).
Use styleClass's for update (not e.g. PF ID's or #this:#parent kind of stuff), so that jQuery is utilized instead of PF, e.g.: #(.fieldset-class).
process whatever scope is being updated. (This is needed for the post-back data so that the Bean keeps its context for the update...) process="#this" is not needed here, provided that the button is contained by the process value component.
For all buttons without validation wanted, set immediate="true".
If none of the above works (which happened with the Add buttons, probably due to ui:include recursion), set process="#this", immediate="true", and update="#none", and then oncomplete="remoteCommandName();", and have a p:remoteCommand instead with that name with the process, immediate, and update mentioned in the above points.
If none of the above works (which happened with some other buttons, probably due to being yet another layer deeper in the ui:include recursion)... wrap a h:panelGroup around the next c:forEach up and then update the PrimeFaces ID of that in the button itself while keeping its remoteCommand call afterwards, as specified above.
If none of the above works (which happened yet again to me)... Try the following code:
In the p:commandButton(s): oncomplete="$('.FixButtonSC').click();"
In the p:fieldset with a style class of FieldsetSC:
<!-- Fix (hidden) button. -->
<p:commandButton id="FixButton" styleClass="FixButtonSC"
process="#this" update="#(.FieldsetSC)" style="display: none;" />
Hope that helps...

Resources