How to Invoke a Jsf Managed Bean on a HTML Dom Event Using Native JavaScript

How to invoke a JSF managed bean on a HTML DOM event using native JavaScript?

Several ways.

  1. Use <h:commandScript>. Note that this is only available since JSF 2.3.

    <h:form>
    <h:commandScript name="commandName" action="#{bean.action}" render=":results" />
    </h:form>
    <h:panelGroup id="results">
    ...
    </h:panelGroup>

    You can invoke it in JS as below:

    commandName();

    The parameters can be passed as below:

    commandName({ name1: "value1", name2: "value2" });

    And obtained as below:

    String name1 = externalContext.getRequestParameterMap().get("name1"); // value1
    String name2 = externalContext.getRequestParameterMap().get("name2"); // value2

    To invoke it during load event, set autorun="true".

    <h:commandScript ... autorun="true" />

  2. If you're using PrimeFaces, use its <p:remoteCommand>.

    <h:form>
    <p:remoteCommand name="commandName" action="#{bean.action}" update=":results" />
    </h:form>
    <h:panelGroup id="results">
    ...
    </h:panelGroup>

    You can invoke it in JS as below:

    commandName();

    This however doesn't use JSF native jsf.ajax.request(), instead it uses PrimeFaces native jQuery (you know, PrimeFaces is a JSF component library on top of jQuery/UI).

    The parameters can be passed as below:

    commandName([{ name: "name1", value: "value1" }, { name: "name2", value: "value2" }]);

    And obtained as below:

    String name1 = externalContext.getRequestParameterMap().get("name1"); // value1
    String name2 = externalContext.getRequestParameterMap().get("name2"); // value2

    To invoke it during load event, set autoRun="true".

    <p:remoteCommand ... autoRun="true" />

  3. If you're using OmniFaces, use its <o:commandScript>. The usage is exactly the same as with <h:commandScript> but then available for older JSF 2.x versions.

    Simply replace h: by o: in the first example. Historical note: the <h:commandScript> is entirely based off <o:commandScript>.


  4. Use the "hidden form" trick (actually, "hack" is given the ugliness a better wording).

    <h:form id="form" style="display:none;">
    <h:commandButton id="button" action="#{bean.action}">
    <f:ajax render=":results" />
    </h:commandButton>
    </h:form>
    <h:panelGroup id="results">
    ...
    </h:panelGroup>

    You can invoke it in JS as below:

    document.getElementById("form:button").onclick();

    Note the importance of triggering onclick() instead of click() in case of <h:commandButton>. The onclick() immediately invokes the onclick function while the click() only triggers the "click" event on the element, which is not supported in IE. If you were using a <h:commandLink>, you can safely use click() instead.

    You can pass parameters via <h:inputHidden> in same form which you fill by JS beforehand. This is demonstrated in How to pass JavaScript variables as parameters to JSF action method?

    To invoke it during load event, consider putting it in <h:outputScript target="body">. The target="body" automatically puts the <script> in end of <body>, thus a $(document).ready() wrapper is unnecessary.

    <h:outputScript target="body">
    document.getElementById("form:button").onclick();
    </h:outputScript>

  5. Or, create a custom UIComponent which extends UICommand and generates the necessary JSF native jsf.ajax.request() call. As an example you could look at source code of OmniFaces <o:commandScript>.

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();
}
}

How to invoke a managed bean action method in on* attribute of a JSF component

Like as all other on* attributes on all JSF components, the onidle attribute must represent a JavaScript callback, not a JSF backing bean action method. Any EL expressions in on* attributes would be evaluated immediately as String value expressions during generating the HTML output in expectation that they print (part of) JavaScript code.

It's exactly like as if you're doing <h:outputText value="#{mybean.processTimeout()}">. If you had removed the parentheses (), you'd have faced a PropertyNotFoundException which was also a hint at its own of it being evaluated as a value expression instead of a method expression.

In order to invoke a JSF backing bean method using JavaScript, you need an additional <p:remoteCommand>.

<p:idleMonitor onidle="processTimeout()" timeout="180000" /> 
<p:remoteCommand name="processTimeout" action="#{mybean.processTimeOut}" />

If you're not on PrimeFaces, head to the alternatives posted in this related answer: How to invoke a JSF managed bean on a HTML DOM event using native JavaScript?

How to call JSF backing bean method only when onclick/oncomplete/on... event occurs and not on page load

This approach will not work. You seem to be confusing/mixing the basic web development concepts of the "server side" and "client side" and to be misunderstanding the role of JSF and EL.

JSF is a server side language which runs on the webserver upon a HTTP request and produces HTML/CSS/JS code which get returned with the HTTP response. All EL expressions in form of ${} and #{} will be executed in the server side during generating the HTML output. JavaScript is a client side language which runs on the webbrowser and works on the HTML DOM tree. The HTML onclick attribute should specify a JavaScript function which will be executed in the client side on the particular HTML DOM event.

In order to invoke a JSF managed bean method, you need the action or *listener attribute. JSF provides components to generate the desired HTML and specify the desired ajax actions which would change the server side state. An <input type="image"> can be generated using a <h:commandButton image>. A bean method can be invoked by the action attribute of that component. That component can be ajaxified by embedding the <f:ajax> tag.

So, the following should do it for you:

<h:form>
<div class="sidebarOptions">
<h:commandButton image="images/homeButton.jpg" action="#{home.setRendered(1)}">
<f:ajax execute="@this" render=":sidebar" />
</h:commandButton>
</div>
<div class="sidebarOptions">
<h:commandButton image="images/memberButton.jpg" action="#{home.setRendered(2)}">
<f:ajax execute="@this" render=":sidebar" />
</h:commandButton>
</div>
</h:form>

<!-- The below is just a guess of what you're really trying to achieve. -->
<h:panelGroup id="sidebar" layout="block">
<h:panelGroup rendered="#{home.rendered eq 1}">
Home
</h:panelGroup>
<h:panelGroup rendered="#{home.rendered eq 2}">
Member
</h:panelGroup>
</h:panelGroup>

See also:

  • Differences between action and actionListener
  • How to invoke a managed bean action method in on* attribute of a JSF component
  • How to invoke a JSF managed bean on a HTML DOM event using native JavaScript?

Call function from JSF backing bean with javascript var or other tag value

When I change the hiddenHolder value from javascript that is not reflected in the backingBean

You're indeed not telling JSF to process the input value. The <f:ajax execute> should be used for this, which defaults to @this (the current input or command component). As the <f:ajax> is enclosed inside a command component, only the command component itself (its action) will be processed.

So, just explicitly specify the input value along with the command component:

<f:ajax execute="@this hiddenHolder" ... />

Or, if this all is within the same form, use @form:

<f:ajax execute="@form" ... />

See also:

  • How to invoke a JSF managed bean on a HTML DOM event using native JavaScript?
  • How to use jsf.ajax.request to manually send ajax request in JSF
  • Calling JSF managed bean method with arguments in jQuery

Call a JSF method via JS

you can use primefaces remoteCommand component. you can find details about remoteCommand in this blog post.

http://blogs.bytecode.com.au/glen/2013/09/25/calling-primefaces-remotecommand-with-javascript-arguments.html

Invoke JSF managed bean action on page load

JSF 1.0 / 1.1

Just put the desired logic in the constructor of the request scoped bean associated with the JSF page.

public Bean() {
// Do your stuff here.
}

JSF 1.2 / 2.x

Use @PostConstruct annotated method on a request or view scoped bean. It will be executed after construction and initialization/setting of all managed properties and injected dependencies.

@PostConstruct
public void init() {
// Do your stuff here.
}

This is strongly recommended over constructor in case you're using a bean management framework which uses proxies, such as CDI, because the constructor may not be called at the times you'd expect it.

JSF 2.0 / 2.1

Alternatively, use <f:event type="preRenderView"> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a @PostConstruct is perfectly fine too.

<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:event type="preRenderView" listener="#{bean.onload}" />
</f:metadata>
public void onload() { 
// Do your stuff here.
}

JSF 2.2+

Alternatively, use <f:viewAction> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a @PostConstruct is perfectly fine too.

<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:viewAction action="#{bean.onload}" />
</f:metadata>
public void onload() { 
// Do your stuff here.
}

Note that this can return a String navigation case if necessary. It will be interpreted as a redirect (so you do not need a ?faces-redirect=true here).

public String onload() { 
// Do your stuff here.
// ...
return "some.xhtml";
}

See also:

  • How do I process GET query string URL parameters in backing bean on page load?
  • What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
  • How to invoke a JSF managed bean on a HTML DOM event using native JavaScript? - in case you're actually interested in executing a bean action method during HTML DOM load event, not during page load.


Related Topics



Leave a reply



Submit