I'm working with JSF 2.0 and here's my form:
<h:form id="fff" onsubmit="reloadMap();">
<h:selectOneMenu value="#{rentCarPoolBean.state}">
<f:selectItems value="#{rentCarPoolBean.stateList}" id="stateList" />
<f:ajax event="change" render="cities stateSelected" onevent="showAlert"/>
</h:selectOneMenu>
<h:selectOneMenu id="cities" value="#{rentCarPoolBean.city}">
<f:selectItems value="#{rentCarPoolBean.cityList}"/>
</h:selectOneMenu>
<h:outputText value="#{rentCarPoolBean.state}" id="stateSelected" />
</h:form>
And the javascript function:
<script type="text/javascript">
function showAlert(data){
if (data.status == "complete")
alert(document.getElementById("stateSelected"));
}
</script>
What the above code does is on selecting a state from the first dropdown, it makes the ajax call and renders the 'cities' dropdown and the 'stateSelected' outputText.
Also, it calls the showAlert() javascript function.
What I want to do is call the javascript function after all the data is returned and both the dropdown and the outputText have been rendered.
But currently the javascript function is called before the elements are rendered and the alert displays null.
How do we make the javascript function execute in the end?
You need to hook on a status of success instead. This will run after the HTML DOM tree has been updated. The status of complete runs directly after the ajax response has been returned. This is admittedly a misleading status name, but you should try to interpret it in context of "HTTP request" like as the begin status.
Another problem is that the document.getElementById() selects items by the HTML element ID, not by JSF component ID. You need to give it exactly the ID as JSF has generated to the HTML. You can figure the right HTML element ID by viewing the page source in webbrowser.
All with all, your new function should look like this:
function showAlert(data){
if (data.status == "success")
alert(document.getElementById("fff:stateSelected"));
}
Here:
alert(document.getElementById("stateSelected"));
you're specifying only JSF component id, but you need to give a full clientId. Here's a link explaining this.
Related
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.
}
I have some jsf-code with a tag that is re-rendered by an ajax call. It contains something like
<h:outputScript>alert("Gotcha")</h:outputScript>
but this is only executed on first load, not on an ajax induced partial render.
This is but a minimal example, what I'm really trying to do is to trigger some server-generated javascript right after the ajax-call has returned, something like
<h:outputScript>#{scriptBean.getScript()}</h:outputScript>
I've seen calling .trigger("click") that is in javascript code returned from an ajax call, Asynchronize ajax calls and javascript code, how to run call some Javascript code with jQuery as soon as element loads to page by Ajax? and Running javascript code called by AJAX, but neither questions nor answers look like they address my question, least not without some additional hint or explanation.
And because I want to keep things small and simple, and because I could avoid anything above jsf:core (mostly), I'd prefer solutions that avoid using yafl (== yet another fancy library).
Edit: as for the comment from #BalusC I post more context:
<composite:implementation>
<h:form id="${cc.attrs.imgId}" styleClass="small" onchange="alert('Gotcha0');">
<f:event type="postAddToView" listener="#{mBean.register}" />
<f:event type="preRenderView" listener="#{mBean.init}" />
<f:attribute name="flav" value="#{cc.attrs.flav}" />
<h:graphicImage width="${cc.attrs.width}" id="${cc.attrs.imgId}"
onclick="if (event.isTrusted) this.nextSibling.value=mods(event);"
onmouseover="aa=this.id" alt="not found"
onchange="alert('Gotcha1');"
value="images/img?#{cc.attrs.flav}=#{mBean.getNextCount()}&imgId=#{cc.attrs.imgId}">
<f:ajax event="click" execute="#form"
onevent="function(data) { if (data.status === 'success') {
console.log('HiHo'+data.responseCode+'\n\n'+ data.responseText+'\n\n'+data.responseXML);
me=window.document.getElementById('#{cc.clientId}:#{cc.attrs.imgId}:#{cc.attrs.imgId}');
me.nextSibling.nextSibling.value=0;
me.nextSibling.value=0;
me.myfunc=function(event)
{
console.log('keyCode='+event.keyCode+' mods='+mods(event)+'/'+this.nextSibling.id);
this.nextSibling.value=mods(event);
this.nextSibling.nextSibling.value=String.fromCharCode(event.keyCode);
this.click();
}; }; }"
listener="#{mBean.handleEvent}" render="#this">
</f:ajax>
</h:graphicImage>
<h:inputHidden id="m" value="#{mBean.keyX}" />
<h:inputHidden id="k" value="#{mBean.key}" />
</h:form>
<h:outputScript>alert("Gotcha2")</h:outputScript>
<h:outputScript>var i=0;window.document.getElementById('#{cc.clientId}:#{cc.attrs.imgId}:#{cc.attrs.imgId}').myfunc=function(event)
{
aa='#{cc.clientId}:#{cc.attrs.imgId}:#{cc.attrs.imgId}';
this.nextSibling.value=mods(event);
this.nextSibling.nextSibling.value=String.fromCharCode(event.keyCode);
this.click();
};
</h:outputScript>
</composite:implementation>
"Gotcha2" shows up only at load time, once for each instance of the composite, but not when the component is re-rendered via ajax calls.
"Gotcha0" and "Gotcha1" are completely ignored.
The "HiHo" shows up for every ajax-call on the component, but I would like the function to fire only when the component is rendered, which is a subtle difference, because I might manipulate the render-list on server side, like
private void addToRenderMap(String obj) {
FacesContext context = FacesContext.getCurrentInstance();
Collection<String> renderIds = context.getPartialViewContext().getRenderIds();
renderIds.add(obj);
}
or even remove the calling component from the list.
(For example, for keypress "i", I want to only show image information in some other component and avoid unnecessary re-sending of the image data.)
Edit2: I see that onchange really is more a onvaluechange for fields that take input, so it's not a big surprise that this part of the code is ignored.
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?
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>
I've created a jsp page. In that when i select 1 check-box or both check-box or none, the corresponding text-boxes and list-box must be displayed in the same page.
For that i tried of calling a javascipt function when i click the checkbox. The javascript function contain code to display the textboxes. But it didn't work.
Since I'm doing this project in struts, I don't know how to get check-box value. And calling of JavaScript function works. But didn't enter into jsp code in JavaScript function.
My code is
<tr>
<td>SEJ:</td>
<td>SEJ 1:<html:checkbox property="sej1" value="on" onclick="checkbox_trial()"></html:checkbox></td>
<td>SEJ 2:<html:checkbox property="sej2" value="on" onclick="checkbox_trial()"></html:checkbox></td>
</tr>
<script type="text/javascript">
function checkbox_trial()
{
<% if(request.getParameter("sej1")=="on"){
%>
<tr><td>SEJ1 Age<html:text property="sej1_age"></html:text></td></tr>
<tr><td>SEJ1 DOI<html:text property="sej1_doi"></html:text></td></tr>
<%}
else if(request.getParameter("sej2")=="on"){%>
<tr><td>SEJ2 Age<html:text property="sej2_age"></html:text></td></tr>
<tr><td>SEJ2 DOI<html:text property="sej2_doi"></html:text></td></tr>
<%}
else if((request.getParameter("sej1")=="on")&&(request.getParameter("sej2")=="on")){%>
<tr><td>SEJ1 Age<html:text property="sej1_age"></html:text></td></tr>
<tr><td>SEJ1 DOI<html:text property="sej1_doi"></html:text></td></tr>
<tr><td>SEJ2 Age<html:text property="sej2_age"></html:text></td></tr>
<tr><td>SEJ2 DOI<html:text property="sej2_doi"></html:text></td></tr>
<%}
else{%>
NOTHING <% } %>
}
This is how it works: Java/JSP runs at webserver, produces HTML/CSS/JS, webserver sends it to webbrowser, webbrowser runs HTML/CSS/JS. Not Java/JSP. Rightclick the page in webbrowser and choose View Source. If Java/JSP has done its job right, you shouldn't see any line of it in there.
If you want to invoke Java/JSP code using JavaScript, you've got to invoke another HTTP request to the webserver so that it can execute the Java/JSP code based on the specific request. You can do that by either submitting the form or firing an asynchronous (ajaxical) request.
Given the skills shown as far and the fact that you're using Struts, I think ajax is going to be a bit too complex. I'd suggest to just submit the form on click of the checkbox
<input type="checkbox" name="show" value="true" onclick="submit()" />
and then let JSP conditionally display the input fields (just a JSTL example since I don't do Struts)
<c:if test="${param.show == 'true'}">
<input type="text" />
<select />
</c:if>
Update: you've by the way another major problem in the code. You can't compare string values by == in Java code (you can do so in EL only). In Java code you need to use equals() method. Otherwise they will be compared by reference instead of by value. I'd suggest to learn basic Java as well.