a4j:commandButton oncomplete javascript ignored - javascript

I have this snippet:
<h:form>
<h:panelGrid columns="2" styleClass="modalYesNo">
<a4j:region id="confirmActionReloadYes">
<a4j:commandButton value="Yes" ajaxSingle="true"
action="#{MyBacking.reloadConfig}"
oncomplete="window.location.reload()"
reRender="blah" />
</a4j:region>
<a4j:commandButton value="No"
onclick="#{rich:component('confirmActionReload')}.hide();return false;" />
</h:panelGrid>
</h:form>
and I notice that when the yes button in the a4j:region above is selected, once the backing bean method reloadCongi() is complete, the javascript window.location.reload() is not run. Why is this? I also notice that elements in the reRender attribute are also not reRendered. Why is this?
EDIT
The method from the first comment to this question is:
public void reloadConfig() {
logger.info("Reloading config.");
pct = pctBackup;
feeds = pct.getFeed();
setSysMsg("Reloaded config OK.", "ok");
}
I'm thinking maybe I need to set the return type to true or false based on the above and see if that works.

Some addons may compromise the firing of the 'oncomplete' event.
If you are out of options, start disabling some addons to see if it works.
Specifically I had the same problem with Firefox 14.0.1 and Firebug 1.7.3.
Once I disabled Firebug, the 'oncomplete' worked again.

Related

Access bean properties in f:ajax onevent function [duplicate]

In my JSF 2.0 (on JBoss AS 7) project, I would like on my ajax submitted forms to display a little icon status triggered on begin and complete phases, to let the end user know that something is still happening.
The primefaces p:ajaxStatus is not useful here, as I'd like to have many different icons at different places in my page.
I found a bit of the solution in this question: "How show different ajax status in same input?", but I still have a problem: in order to make my javascript function reusable, I need to provide an extra parameter to the call.
I did something like this:
<h:commandLink value="do something boy!">
<f:ajax render="#form" execute="#form" listener="#{myBean.doStuff}"
onevent="showProgress" />
<f:param name="extraParam" value="extraValue" />
</h:commandLink>
and I can see the parameter "extraParam" sent to the server through the request, but in my javascript showProgress method I cannot recover it through the only given parameter.
So my questions is: can I provide to my f:ajax onevent javascript method an additionnal parameter through f:param (or maybe f:attribute, or anything else)?
Wrap it in an anonymous function wherein you pass it as extra argument.
<h:commandLink value="do something boy!">
<f:ajax render="#form" execute="#form" listener="#{myBean.doStuff}"
onevent="function(data) { showProgress(data, 'extraValue') }" />
</h:commandLink>
with
function showProgress(data, extraParam) {
// Use "data" argument the usual way.
// The "extraParam" argument will contain "extraValue" in above example.
}

JSF execute javascript after f:ajax

In my JSF 2 web application, I use the following code to display and switch the contents of a rich:dataTable according to the selectedStatus:
<h:selectOneRadio id="statusSelection" value="#{backingBean.selectedStatus}" style="width:auto; float:left;">
<f:selectItem itemValue="AVAILABLE" itemLabel="Available" />
<f:selectItem itemValue="INACTIVE" itemLabel="Inactive" />
<f:ajax render="itemsDataTable" execute="#{backingBean.sortByTitel('ascending')}" />
<f:ajax render="itemsDataTable" event="click" />
</h:selectOneRadio>
The dataTable contains a4j:commandLink s, which unintentionally need to be double clicked in some IE versions after changing table content - I found out, that executing the following Javascript code (on IE's debugging console, after table contents have changed) solves the issue:
document.getElementById(<dataTableClientId>).focus()
My question is: How can I achieve automatic execution of the javascript code after the table contents have changed?
In order to execute JS code after the <f:ajax> is successfully completed, the following inline solution will do:
<f:ajax
render="itemsDataTable"
onevent="function(data) { if (data.status === 'success') {
// Put your JS code here.
document.getElementById('dataTableClientId').focus();
}}" />
Or the following external function solution (note: do not put parentheses in onevent, only the function name):
<f:ajax
render="itemsDataTable"
onevent="scriptFunctionName" />
function scriptFunctionName(data) {
if (data.status === 'success') {
// Put your JS code here.
document.getElementById('dataTableClientId').focus();
}
}
Also take a look at this answer: JSF and Jquery AJAX - How can I make them work together?
Also, double check the need of the event="click" in your f:ajax , because the default event in <h:selectOneRadio> is change which I think you better use... See also What values can I pass to the event attribute of the f:ajax tag?

How to show a popup in primefaces with the requiredMessages, only if these messages exist?

I want to show a popup with the requiredMessages of some inputText fields when I click on a submit button. But just only in case of there are those messages. I have tried with bean variable and javascript on the oncomplete tag, but I'm not able to make it work properly. If I put visible="true" in p:dialog, the popup is always displayed, although I try to control it from the commandButton. Now, I have this, but the popup is never displayed:
<h:inputText id="Scheme"
required="true"
requiredMessage="Required.">
</h:inputText>
<h:commandButton id="submitModify" value="#{msg['systemdetail.modify']}"
action="#{sistem.modify}"
oncomplete="if (#{facesContext.maximumSeverity != null}) {dlg1.show();}">
</h:commandButton>
<p:dialog id="popup"
style="text-align:center"
widgetVar="dlg1"
modal="true">
<h:messages layout="table"/>
</p:dialog>
How can I do this? Thanks in advance.
Standard JSF and PrimeFaces does not support request based EL evaluation in on* attributes. RichFaces is the only who supports that. Besides, the standard JSF <h:commandButton> does not have an oncomplete attribute at all. You're probably confusing with PrimeFaces <p:commandButton>
There are several ways to achieve this:
Check the condition in the visible attribute of the <p:dialog> instead.
<p:dialog visible="#{not empty facesContext.messageList}">
or if you want to show validation messages only instead of all messages
<p:dialog visible="#{facesContext.validationFailed}">
Use PrimeFaces <p:commandButton> instead, the PrimeFaces JS API supports the #{facesContext.validationFailed} condition through the args object as well:
<p:commandButton ... oncomplete="if (args.validationFailed) dlg1.show()" />
If you need to check for what kind of messages, here is a way that I made work with primefaces. Since primefaces oncomplete is called after update, by updating the component holding the javascript function, the javascript function can be rebuilt using the latest #facesContext.maximumSeverity} values before executed.
<p:commandButton
oncomplete="executeAfterUpdate()"
update="updatedBeforeOnComplete"/>
<h:panelGroup id="updatedBeforeOnComplete">
<script language="JavaScript" type="text/javascript">
//
function executeAfterUpdate(){
if (#{facesContext.maximumSeverity==null
or facesContext.maximumSeverity.ordinal=='1'})
{
// your code to execute here
someDialog.show();
}
}
//
</script>
</h:panelGroup>

EL expression inside p:commandButton onclick does not update/re-render on ajax request?

The onclick attribute of my commandButton has some EL dependent Javascript inside. To be more specific, here is that piece of code:
<p:commandButton
onclick="javascript: if('#{userBean.user.friendList.size() gt 0}' == 'true') deleteFriendsConfirmDialog.show(); else friendsAlreadyDeletedErrorDialog.show();"
value="Delete all friends?" />
deleteFriendsConfirmDialog clears the list of friends and updates the #form. The list of friends, commandButton and the dialogs are all in that form.
So I click the button, confirmation dialog comes up (because the length of friends' list is gt 0), I confirm and the list is emptied, the view is updated. However, when I click the Delete all friends? button once more, the confirmation dialog comes up again. Since the length of the list is now 0, I instead expect the error dialog to show.
That, I guess, is because the Javascript written inside onclick is not updated (although the button is in the form).
Edit: Changing #{userBean.user.friendList.size() gt 0} to #{not empty userBean.user.friendList} doesn't work neither.
How come? What's wrong here?
Any help appreciated. :)
Indeed. PrimeFaces (and standard JSF) does not re-evaluate the EL in on* attributes on a per-request basis. It only happens on a per-view basis. RichFaces however does that in <a4j:xxx> components.
You need to solve the problem differently. I suggest to use the visible attribute of the <p:dialog> instead.
<h:form>
...
<p:commandButton value="Delete all friends?" update=":deleteDialogs" />
</h:form>
...
<h:panelGroup id="deleteDialogs">
<p:dialog id="deleteFriendsConfirmDialog" visible="#{facesContext.postback and not empty userBean.user.friendList}">
...
</p:dialog>
<p:dialog id="friendsAlreadyDeletedErrorDialog" visible="#{facesContext.postback and empty userBean.user.friendList}">
...
</p:dialog>
</h:panelGroup>
An alternative is to use PrimeFaces' RequestContext in the bean's action method which allows you to execute JavaScript code programmatically in bean's action method (although this tight-couples the controller a bit too much with the view, IMO).
<p:commandButton value="Delete all friends?" action="#{userBean.deleteAllFriends}" />
with
RequestContext context = RequestContext.getCurrentInstance();
if (!user.getFriendList().isEmpty()) {
context.execute("deleteFriendsConfirmDialog.show()");
} else {
context.execute("friendsAlreadyDeletedErrorDialog.show()");
}
Unrelated to the concrete problem, your original onclick, while it does not work out in your particular case, shows some poor practices. The javascript: pseudoprotocol is superfluous. It's the default already. Remove it. Also the test against == 'true' is superfluous. Remove it. Just let the EL print true or false directly. The following is the proper syntax (again, this does not solve your problem, just for your information)
<p:commandButton
onclick="if (#{not empty userBean.user.friendList}) deleteFriendsConfirmDialog.show(); else friendsAlreadyDeletedErrorDialog.show();"
value="Delete all friends?" />
It would have worked if you were using RichFaces' <a4j:commandButton>.
<a4j:commandButton
oncomplete="if (#{not empty userBean.user.friendList}) deleteFriendsConfirmDialog.show(); else friendsAlreadyDeletedErrorDialog.show();"
value="Delete all friends?" />

Google Maps API issues with IE8

I am writing an HTML form that uses a google map, but to reduce the ammount of clutter on the screen I have removed the google interface and replaced it with some simple submit buttons to change the map type (eg Satellite, Hybrid and Normal). The problem that I am having is that IE refuses to accept the: map.setMapType(G_SATELLITE_MAP);
What is confusing me though, is the fact that my application works beautifally in Safari and FF, yet refuses to work at all in IE8.
Just for reference here is the function I am calling:
function map_type_sat()
{
map.setMapType(G_SATELLITE_MAP);
return true;
}
and here is how I am calling it:
<form action ="#" onsubmit="return map_type_sat()">
<input type="Submit" value="satellite">
</form>
can anyone see any issues that would be causing it to not work, or is it an issue with my version of IE having a required plugin to run this command.
I'm not sure why you are using a form submission to set the map type. This may, in fact, be handled differently in IE, potentially causing a full post back even with the '#' target action. Try changing it to use a click handler for a regular input button and omit the form. Note that this also eliminates the need to return a value from the function.
function map_type_sat()
{
map.setMapType(G_SATELLITE_MAP);
}
<input type='button' value='satellite' onclick='map_type_sat()' />
Or, even better,
function set_map_type( type )
{
map.setMapType( type );
}
<input type='button' value='normal' onclick='set_map_type(G_NORMAL_MAP);' />
<input type='button' value='satellite' onclick='set_map_type(G_SATELLITE_MAP);' />
<input type='button' value='hybrid' onclick='set_map_type(G_HYBRID_MAP);' />

Categories