When use ajax inside h:commandLink, FacesMessage is not displaying - ajax

In jsf. i'm using h:commandLink for adding objects in list. without selecting mandatory fields objects not added in list and showing warning message.its working fine when not using ajax 'render' inside the h:commandLink.
later i decide, i don't want to load my page. so i added ajax inside h:commandLink. but warning message not showing.Please help to fix this problem.
With ajax working:
<h:commandLink value="ADD" action="#{uomGroupBean.goToAddItem}" class="btn-secondary">
<f:ajax render="ITEM_TABLE"></f:ajax>
</h:commandLink>
Without ajax working:
<h:commandLink value="ADD" action="#{uomGroupBean.goToAddItem}" class="btn-secondary"/>
Method for adding:
public String goToAddItem(){
System.out.println("calling......");
if(uomGroup.getBaseUOM()==null){
Util.addWarn("Please select Base UOM");
return null;
}
if(uomGroup.getUomGroupItems()==null || uomGroup.getUomGroupItems().size()==0){
uomGroup.setUomGroupItems(new ArrayList<UomGroupItem>());
}
uomGroup.getUomGroupItems().add(new UomGroupItem());
return "Called";
}
Thanks in advance.

Related

How to only update JSF/Primefaces component value upon Ajax sucess, but do nothing on Ajax failure

I have a JSF front end using Primefaces 5.3 which updates fields dynamically using Ajax. The problem that I am having is that sometimes my Ajax calls fail (ex: server responds with a 500), but my front end is still changing. Essentially, I'm looking to prevent the change of the input field if my ajax fails. Stated differently, I only want the input field to change upon a successful Ajax response.
I'm fairly new to JSF, so I'm not sure how to handle this. In regular HTML/JS, I would have been able to store the value onclick and in my ajax error handler restored the value, but I don't know how to do this using the PF framework.
<div class="Container25">
<p:selectOneRadio id="grid" value="#{cc.attrs.answer.singleAnswer.codeValue}" layout="grid" columns="1" >
<f:selectItems value="#{cc.attrs.menuItems}"
var="item" itemLabel="#{msg[item.code]}" itemValue="#{item.code}" itemLabelEscaped="false"/>
<p:ajax event="change" listener="#{cc.attrs.onChange}" update="#{cc.attrs.update}" disabled="#{cc.attrs.onChange == null }" global="false" />
</p:selectOneRadio>
</div>
I've tried adding the resetValues attribute to the ajax component, but that hasn't helped. Additionally, I've tried adding some custom JS in my onstart handler, but it is undefined.
I figured there must be a simple JSF/PF way of doing this, but can't seem to find it.
How can I either prevent the input value to change until the Ajax call returns successfully (ie: only change the value in the onsuccess handler) or reset my original radio button selection in the event that my Ajax call fails? What do I need to put in my onerror handler to restore the pre-ajax state?
You can use Primefaces RemoteCommand component for an easy solution, just embed it in your form:
<p:remoteCommand name="revertSomeValues"
actionListener="#{relatedBean.revertValuesToDefaults}"
update="componentId" />
And at the bean side you can manipulate the model:
#Named
#ViewScoped
public class relatedBean implements Serializable {
Integer codeValue;
//other model attributes and methods...
public void revertValuesToDefaults() {
setCodeValue(0); //supposing 0 is the default value
//handle other model attributes if needed
}
}
Now you can set the onerror callback alike -> onerror="revertSomeValues()"
You can also update the components wtih Primefaces RequestContext programatically from your bean if needed:
RequestContext context = RequestContext.getCurrentInstance();
context.update("componentId");

Primefaces Ajax updated form does not trigger commandButton action

I have a problem with a form not triggering its commandButton action method.
When I submit the form without prior update (not selecting any node in the tree), the method triggers just fine.
As soon as the form is Ajax-updated, the commandButton won't call its action anymore.
Here is the JSF code:
<p:layoutUnit position="center">
<p:tree orientation="horizontal" value="#{flightTypeController.tree}" var="node"
selectionMode="single" selection="#{flightTypeController.selectedNode}">
<p:ajax event="select" listener="#{flightTypeController.onNodeSelect}" update=":typesTree"/>
<p:treeNode>
<h:outputText value="#{node.name}"/>
</p:treeNode>
</p:tree>
<h:form id="typesTree">
<p:inputText disabled="true" id="outputParent" value="#{flightTypeController.selectedOne.name}"/>
<p:inputText id="outputName" value="#{flightTypeController.current.name}"/>
<p:commandButton ajax="false" icon="ui-icon-disk" value="#{bundle.general_create}" action="#{flightTypeController.create()}"/>
</h:form>
</p:layoutUnit>
And the java listener:
public void onNodeSelect(final NodeSelectEvent event) {
final Object res = event.getTreeNode().getData();
if (res instanceof FlightType) {
selectedOne = (FlightType) res;
} else {
selectedOne = null;
}
}
I already check BalusC's bible and JS Fix but without success.
I've seen similar behaviours quite often (and had to find workarounds) so I might have misunderstood something fundamental.
Oh, yes, I checked multiple times : no nested forms in my code.
The JS fix which you found is hooking on jsf.ajax.addOnEvent which is only triggered by <f:ajax>, not by PrimeFaces components which use jQuery under the covers.
To cover PrimeFaces ajax requests as well, grab the current version of the JS fix (I have recently updated that post) and add the following to apply this fix on jQuery ajax requests as well:
$(document).ajaxComplete(function(event, xhr, options) {
if (typeof xhr.responseXML != 'undefined') { // It's undefined when plain $.ajax(), $.get(), etc is used instead of PrimeFaces ajax.
fixViewState(xhr.responseXML);
}
}
Disclaimer: I haven't tried your specific use case. But, theoretically, it should solve your problem.

PrimeFaces: Dialog closes on validation errors [duplicate]

Minimal example dialog:
<p:dialog header="Test Dialog"
widgetVar="testDialog">
<h:form>
<p:inputText value="#{mbean.someValue}"/>
<p:commandButton value="Save"
onsuccess="testDialog.hide()"
actionListener="#{mbean.saveMethod}"/>
</h:form>
</p:dialog>
What I want to be able to do is have the mbean.saveMethod somehow prevent the dialog from closing if there was some problem and only output a message through growl. This is a case where a validator won't help because there's no way to tell if someValue is valid until a save is submitted to a back end server. Currently I do this using the visible attribute and point it to a boolean field in mbean. That works but it makes the user interface slower because popping up or down the dialog requires hitting the server.
The onsuccess runs if ajax request itself was successful (i.e. there's no network error, uncaught exception, etc), not if action method was successfully invoked.
Given a <p:dialog widgetVar="yourWidgetVarName">, you could remove the onsuccess and replace it by PrimeFaces RequestContext#execute() inside saveMethod():
if (success) {
RequestContext.getCurrentInstance().execute("PF('yourWidgetVarName').hide()");
}
Note: PF() was introduced in PrimeFaces 4.0. In older PrimeFaces versions, you need yourWidgetVarName.hide() instead.
If you prefer to not clutter the controller with view-specific scripts, you could use oncomplete instead which offers an args object which has a boolean validationFailed property:
<p:commandButton ...
oncomplete="if (args && !args.validationFailed) PF('yourWidgetVarName').hide()" />
The if (args) check is necessary because it may be absent when an ajax error has occurred and thus cause a new JS error when you try to get validationFailed from it; the & instead of & is mandatory for the reason explained in this answer, refactor if necessary to a JS function which you invoke like oncomplete="hideDialogOnSuccess(args, 'yourWidgetVarName')" as shown in Keep <p:dialog> open when validation has failed.
If there is however no validation error and the action method is successfully triggered, and you would still like to keep the dialog open because of e.g. an exception in the service method call, then you can manually trigger validationFailed to true from inside backing bean action method by explicitly invoking FacesContext#validationFailed(). E.g.
FacesContext.getCurrentInstance().validationFailed();
Using the oncomplete attribute from your command button and really simple script will help you a lot.
Your dialog and command button would be something similar to this:
<p:dialog widgetVar="dialog">
<h:form id="dialogView">
<p:commandButton id="saveButton" icon="ui-icon-disk"
value="#{ui['action.save']}"
update=":dataList :dialogView"
actionListener="#{mbean.save()}"
oncomplete="handleDialogSubmit(xhr, status, args)" />
</h:form>
</p:dialog>
An the script would be something like this:
<script type="text/javascript">
function handleDialogSubmit(xhr, status, args) {
if (args.validationFailed) {
dialog.show();
} else {
dialog.hide();
}
}
</script>
I've just googled up this solution. Basically the idea is to use actionListener instead of button's action, and in backing bean you add callback parameter which will be then check in button's oncomplete method. Sample partial code:
JSF first:
<p:commandButton actionListener="#{myBean.doAction}"
oncomplete="if (!args.validationFailed && args.saved) schedulesDialog.hide();" />
Backing bean:
public void doAction(ActionEvent actionEvent) {
// do your stuff here...
if (ok) {
RequestContext.getCurrentInstance().addCallbackParam("saved", true);
} else {
RequestContext.getCurrentInstance().addCallbackParam("saved", false);
}
}
Hope this helps someone :)
I use this solution:
JSF code:
<p:dialog ... widgetVar="dlgModify" ... >
...
<p:commandButton value="Save" update="#form" actionListener="#{AdminMB.saveTable}" />
<p:commandButton value="Cancel" oncomplete="PF('dlgModify').hide();"/>
Backing bean code:
public void saveTable() {
RequestContext rc = RequestContext.getCurrentInstance();
rc.execute("PF('dlgModify').hide()");
}
I believe this is the cleanest solution.
Doing this you don't need to change your buttons code.
This solution overrides the hide function prototype.
$(document).ready(function() {
PrimeFaces.widget.Dialog.prototype.originalHide = PrimeFaces.widget.Dialog.prototype.hide; // keep a reference to the original hide()
PrimeFaces.widget.Dialog.prototype.hide = function() {
var ajaxResponseArgs = arguments.callee.caller.arguments[2]; // accesses oncomplete arguments
if (ajaxResponseArgs && ajaxResponseArgs.validationFailed) {
return; // on validation error, prevent closing
}
this.originalHide();
};
});
This way, you can keep your code like:
<p:commandButton value="Save" oncomplete="videoDetalheDialogJS.hide();"
actionListener="#{videoBean.saveVideo(video)}" />
The easiest solution is to not have any "widget.hide", neither in onclick, neither in oncomplete. Remove the hide functions and just put
visible="#{facesContext.validationFailed}"
for the dialog tag

JSF f:ajax listener not called

I am trying to have an h:inputText switch out with a different one when an h:commandButton is clicked. To do this, I am trying to tie an f:ajax command with the h:commandButton, with the listener setting a value on the bean (deciding which one to display), and re-rendering the area.
I have tried using listener on the f:ajax, actionListener on the h:commandButton, action on the h:commandButton with execute on the f:ajax. Nothing worked. The mothed I am trying to call is not being called at all - there is no println (see what follows).
The panelGroup is being re-rendered, which is why I need the onevent attribute that re-attaches some JavaScript hint text based on the title (I had an earlier question involving this).
The method I am trying to call:
public void morePressed(AjaxBehaviorEvent e) {
easySearch = !easySearch;
System.out.println("Made it!");
}
The JSF segment that is not working (note the last h:commandButton is trying to re-render the panelGroup):
<h:form>
<h:panelGroup id="switchSearchTexts">
<h:inputText accesskey="s" alt="Search" id="searchBoxPeople" title="Search Plebeians" valueChangeListener="#{peopleBean.simplePersonQuery}" size="25" rendered="#{peopleBean.easySearch}">
<f:ajax render="peopleDataTable" event="keyup" />
</h:inputText>
<h:inputText accesskey="s" alt="Search First Name" id="searchBoxFN" title="Search First Name" size="25" rendered="#{!peopleBean.easySearch}">
<f:ajax render="peopleDataTable" event="keyup" />
</h:inputText>
</h:panelGroup>
<div id="expandBox">
<h:inputText id="searchBoxLN" alt="Search Last Name" styleClass="hideToggle" title="Search Last Name" size="25" />
<h:inputText id="searchBoxAddress" alt="Search Address" styleClass="hideToggle" title="Search Address" size="25" />
</div>
<h:commandButton type="button" styleClass="moreButtonAsText" id="moreButtonAsText" value="â–¸More">
<f:ajax listener="#{peopleBean.morePressed}" render="switchSearchTexts" event="click" onevent="callFunctionAjaxRequest" />
</h:commandButton>
This is the JavaScript (jQuery) that I attach to the More button on pageload. I give it not because I think it could help, but I don't know if this could interfere with the ajax listener in any way:
$(function() {
textboxHint();
$('input[id$="moreButtonAsText"]').toggle(function(e) {
$(this).prop('value', '\u25c2Less');
$(".hideToggle").show(300);
}
, function () {
$(this).prop('value', '\u25b8More');
$(".hideToggle").hide(100);
$('input[id$="searchBoxAddress"]').prop('value', function() {
return $(this).prop('title');
});
$('input[id$="searchBoxAddress"]').blur();
});
});
I have no idea. As I said, I have tried actionListener on h:commandButton with various appraoches there, as well as various approaches to the listener on the ajax. Can anybody see why the listener does not work?
Update:
What I ended up doing, before having an answer, is converting everything to display and hide based on JavaScript, with stuff I needed hidden if they didn't have javascript initially hidden, etc.
However I need the f:ajax elsewhere, now.
The solution is to take out event="click" on the h:commandButton. I still do now know why this was causing it to break, but hey, whatever works.
I had an issue like this. It turned out that an inputText somewhere had a value="#{something.something}" where the property wasn't settable. The exception wasn't being reported anywhere. I had to put a breakpoint on Exception and all subclasses to find it.
Do you really have a function named callFunctionAjaxRequest in your js code? cause if not it may cause the button not to work (because its being referenced to a not existing function) ,
look at the firebug for a possible errors...
try this version of your command button (event="click" can be removed too... and self execute too)
<h:commandButton type="button" styleClass="moreButtonAsText" id="moreButtonAsText" value="More">
<f:ajax listener="#{peopleBean.morePressed}" render="switchSearchTexts" />
</h:commandButton>
Another thing , in your ajax calls of the upper input texts you got reference to searchBoxPeople twice (instead to searchBoxFN in the second f:ajax), fix it cause otherwise when working with searchBoxFN its f:ajax will try to execute an element that its not being rendered ... (can cause serious issues...)
p.s prependId="false" in your h:form will simplify your selectors in jQuery...
The issue is that the managed bean needs to be set up with the right signature event as an input param. Through lots of testing, I was trying to use the same class taking an AjaxBehaviorEvent. As in the same example on the previous forum.
when I declared an ActionListener event (compliant with the button jsf action), the bean is executed!
I had the same problem and followed your example to help me exactly. I simply (20 hrs) fixed this by including the following in my bean:
The first one now gets fired!
public void actionListener(ActionEvent actionEvent) {
// Add event code here...
System.out.println("Made it!");
}
public void morePressed(AjaxBehaviorEvent e) {
System.out.println("Made it!");
}

Keep p:dialog open when a validation error occurs after submit

Minimal example dialog:
<p:dialog header="Test Dialog"
widgetVar="testDialog">
<h:form>
<p:inputText value="#{mbean.someValue}"/>
<p:commandButton value="Save"
onsuccess="testDialog.hide()"
actionListener="#{mbean.saveMethod}"/>
</h:form>
</p:dialog>
What I want to be able to do is have the mbean.saveMethod somehow prevent the dialog from closing if there was some problem and only output a message through growl. This is a case where a validator won't help because there's no way to tell if someValue is valid until a save is submitted to a back end server. Currently I do this using the visible attribute and point it to a boolean field in mbean. That works but it makes the user interface slower because popping up or down the dialog requires hitting the server.
The onsuccess runs if ajax request itself was successful (i.e. there's no network error, uncaught exception, etc), not if action method was successfully invoked.
Given a <p:dialog widgetVar="yourWidgetVarName">, you could remove the onsuccess and replace it by PrimeFaces RequestContext#execute() inside saveMethod():
if (success) {
RequestContext.getCurrentInstance().execute("PF('yourWidgetVarName').hide()");
}
Note: PF() was introduced in PrimeFaces 4.0. In older PrimeFaces versions, you need yourWidgetVarName.hide() instead.
If you prefer to not clutter the controller with view-specific scripts, you could use oncomplete instead which offers an args object which has a boolean validationFailed property:
<p:commandButton ...
oncomplete="if (args && !args.validationFailed) PF('yourWidgetVarName').hide()" />
The if (args) check is necessary because it may be absent when an ajax error has occurred and thus cause a new JS error when you try to get validationFailed from it; the & instead of & is mandatory for the reason explained in this answer, refactor if necessary to a JS function which you invoke like oncomplete="hideDialogOnSuccess(args, 'yourWidgetVarName')" as shown in Keep <p:dialog> open when validation has failed.
If there is however no validation error and the action method is successfully triggered, and you would still like to keep the dialog open because of e.g. an exception in the service method call, then you can manually trigger validationFailed to true from inside backing bean action method by explicitly invoking FacesContext#validationFailed(). E.g.
FacesContext.getCurrentInstance().validationFailed();
Using the oncomplete attribute from your command button and really simple script will help you a lot.
Your dialog and command button would be something similar to this:
<p:dialog widgetVar="dialog">
<h:form id="dialogView">
<p:commandButton id="saveButton" icon="ui-icon-disk"
value="#{ui['action.save']}"
update=":dataList :dialogView"
actionListener="#{mbean.save()}"
oncomplete="handleDialogSubmit(xhr, status, args)" />
</h:form>
</p:dialog>
An the script would be something like this:
<script type="text/javascript">
function handleDialogSubmit(xhr, status, args) {
if (args.validationFailed) {
dialog.show();
} else {
dialog.hide();
}
}
</script>
I've just googled up this solution. Basically the idea is to use actionListener instead of button's action, and in backing bean you add callback parameter which will be then check in button's oncomplete method. Sample partial code:
JSF first:
<p:commandButton actionListener="#{myBean.doAction}"
oncomplete="if (!args.validationFailed && args.saved) schedulesDialog.hide();" />
Backing bean:
public void doAction(ActionEvent actionEvent) {
// do your stuff here...
if (ok) {
RequestContext.getCurrentInstance().addCallbackParam("saved", true);
} else {
RequestContext.getCurrentInstance().addCallbackParam("saved", false);
}
}
Hope this helps someone :)
I use this solution:
JSF code:
<p:dialog ... widgetVar="dlgModify" ... >
...
<p:commandButton value="Save" update="#form" actionListener="#{AdminMB.saveTable}" />
<p:commandButton value="Cancel" oncomplete="PF('dlgModify').hide();"/>
Backing bean code:
public void saveTable() {
RequestContext rc = RequestContext.getCurrentInstance();
rc.execute("PF('dlgModify').hide()");
}
I believe this is the cleanest solution.
Doing this you don't need to change your buttons code.
This solution overrides the hide function prototype.
$(document).ready(function() {
PrimeFaces.widget.Dialog.prototype.originalHide = PrimeFaces.widget.Dialog.prototype.hide; // keep a reference to the original hide()
PrimeFaces.widget.Dialog.prototype.hide = function() {
var ajaxResponseArgs = arguments.callee.caller.arguments[2]; // accesses oncomplete arguments
if (ajaxResponseArgs && ajaxResponseArgs.validationFailed) {
return; // on validation error, prevent closing
}
this.originalHide();
};
});
This way, you can keep your code like:
<p:commandButton value="Save" oncomplete="videoDetalheDialogJS.hide();"
actionListener="#{videoBean.saveVideo(video)}" />
The easiest solution is to not have any "widget.hide", neither in onclick, neither in oncomplete. Remove the hide functions and just put
visible="#{facesContext.validationFailed}"
for the dialog tag

Resources