Calling a JavaScript Function from Managed Bean

Calling Managed Bean Method From JavaScript

You have a few options. If you are using JSF 2.0 you can build a composite component around these area tags.

The easiest way however would be to invoke a hidden JSF input button.

<h:commandButton id="hdnBtn" actionListener="#{personBean.method}" style="display: none;" />

This will render as an input HTML element on the page that you can access from Javascript and invoke its click event.

onclick="jQuery('#form:hdnBtn').click();"

How to call JSF backing bean method using javascript only when The page is loaded

As it turned out you actually want to have a client side cache in localStorage and prevent business logic invocation if that client side cache is valid you
have to go the AJAX way:

I suggest to implement a javascript rendered conditionally which updates the local storage only if needed:

<h:panelGroup id="updateLocalStorageScript" style="display: none;">
<h:outputScript rendered="#{villeBean.updateLocalStorage}">
localStorage.setItem('date',date);
localStorage.setItem('ville', #{villeBean.villesList});
</h:outputScript>
</h:panelGroup>

The update can be triggered by a command action as proposed here: How to invoke a JSF managed bean on a HTML DOM event using native JavaScript?

<h:form id="frmHidden" style="display: none;">
<h:commandButton id="cmdDoUpdateLocalStorage" action="#{villeBean.doUpdateLocalStorage()}">
<f:ajax execute="@this" render=":updateLocalStorageScript" />
</h:commandButton>
</h:form>

Of course you can also use p:remoteCommand, the OmniFaces solution or other suggestions proposed in above QA.

This command action leads to the javascript being rendered and initializes the list value by invoking your business logic only once.

@ManagedBean (name="villeBean)"
@ViewScoped
public class Villes {
private boolean updateLocalStorage;

private String villesList;

public void doUpdateLocalStorage() {
updateLocalStorage = true;
villesList = dao.listeVilles();
}

public boolean isUpdateLocalStorage() {
return updateLocalStorage;
}

public String getVillesList() {
return villesList;
}

}

Trigger that command from within your javascript conditional blocks:

if(localStorage['ville'] == null || localStorage['date']==null){
document.getElementById('frmHidden:cmdDoUpdateLocalStorage').onclick();
}
else{
var oldDate = new Date(localStorage['date']).getTime();;
var currentDate = new Date().getTime();
var distance = currentDate - oldDate ;
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
if (days >= 15){
document.getElementById('frmHidden:cmdDoUpdateLocalStorage').onclick();
}
}

JSF comandButton execute action, then js function with bean value as a parameter

You may invoke JS code from Java, this execute when the response is rendering. View: https://www.primefaces.org/showcase/ui/misc/requestContext.xhtml

In action method Java you can coding:

PrimeFaces.current().executeScript("alert('This onload script is added from backing bean.')");

How to call managed bean methods with parameters via JavaScript

Just to add to Kishor's (halfway) answer, you need to have a to-be-updated component in your view (popup window as you call it) and ajax-update it after the request has been successfully completed.

You can use remote command to send the AJAX request with an extra parameter attached and ajax-update the JSF component responsible to be a popup window. Like so (for PrimeFaces 3.x):

<p:remoteCommand name="myRemote" actionListener="#{myBean.listen}" 
update="dialog" oncomplete="dlg.show()" />
...
<div onclick="myremote([{name:'poi_id', value:poi_id}]);">...</div>
...
<p:dialog id="dialog" widgetVar="dlg">
<h:outputText value="#{myBean.address}" />
...(display other information)
</p:dialog>

with

String address;
public void listen(){
String poi_id = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("poi_id");
address = getAddress(poi_id);
}

The alternative to using a remote command is to have a hidden form with a hidden input that will be used to transmit the parameter to the backing bean, that could be separated from other beans to handle the retrieval of necessary information based on your poi_id:

<h:form id="poi-form" styleClass="invisible">
<h:inputHidden id="poi" value="#{poiBean.poi}" />
<p:commandButton id="info" action="#{poiBean.info}"
update="dialog" oncomplete="dlg.show()" />
</h:form>
<div onclick="document.getElementById('poi-form:poi').value = poi_id;
document.getElementById('poi-form:info').click();">...</div>
...
<p:dialog id="dialog" widgetVar="dlg">
<h:outputText value="#{poiBean.address}" />
...(display other information)
</p:dialog>

with

@ManagedBean
@RequestScoped
public class PoiBean {

private String poi;//getter+setter
private String address;//getter
//other properties

public void listen(){
address = getAddress(poi);
//other properties
}

}

interrupt a Bean-method by calling a javaScript function?

Disclaimer: Code in the answer will contain untested code in PrimeFaces flavour and 'pseudo code'. Since I do not use/run IceFaces nor do I have the intention to, I cannot (will not) test the code and will only provide the PrimeFaces counterparts as an (untested) example

Answer

You seem to be stuck trying to get a technical solution to work that cannot work. JSF cannot 'pause' things and will only return data at the end of the bean method that is called. You are most likely mislead by the statement in the IcesFaces documentation

"Send immediately Javascript code to the client for evaluation and execution"

This cannot work due to the way JSF works and it is sort of not really good English. The developers should have stated something like

"Send Javascript code to the client at the end of the method call for immediate evaluation and execution"

The immediate means that it is not some <script> .... </script> that gets added to the page and that can be executed again and again by e.g. calling a function that is defined in the script. It does not mean you cannot call existing javasript functions (ones that are already in your DOM) from the returned script (effectively that is what we will be using)

So how to solve your problem. Start by breaking the method down in two, lets call them step1 and step2

void step1() {

// Do things

// return javascript

}

void step2() {

// Do other things using values that will be posted from the client by javascript

}

How to return javascript/call javascript from a bean is an existing Q/A here in Stackoverflow. For the IcesFaces counterpart I refer to their documentation. A PrimeFaces example is

PrimeFaces.current().executeScript("alert('This onload script is added from backing bean.'); clientSideFunction();");

But at the end of the javascript you want to call a server side method in a bean from javascript. The opposite of what you need in step one.

A PrimeFaces example being

<p:remoteCommand name="clientSideFunction" action="#{bean.step2}" />

And in since in calling step2() you want to pass parameters to the bean, you need to implement this as well.

clientSideFunction([{name:'x', value:10}, {name:'y', value:20}]);

You can use javascript variables in there (e.g. a complete json string in a variable) and need to process these variables (especially see the 'update' at the end)



Related Topics



Leave a reply



Submit