How to run a back bean method from a Javascript function?

Asked

Viewed 2,681 times

4

I am developing a web page with canvas in HTML 5, it will be presented dashboards in real time, for this use Managedbean to return the respective values, I have a component developed in JavaScript with its variable declared as global, and every 3 seconds its values should be updated through the pool of Primefaces, but this does not happen, the code is executed only once after rendering the page, as can be seen below in the generated code:

<script id="j_idt2:j_idt3_s" type="text/javascript">
    $(function() {
        PrimeFaces.cw("Poll", "widget_j_idt2_j_idt3", {
            id: "j_idt2:j_idt3",
            widgetVar: "widget_j_idt2_j_idt3",
            frequency: 2,
            autoStart: true,
            fn: function() {
                PrimeFaces.ab({
                    s: 'j_idt2:j_idt3',
                    f: 'j_idt2',
                    u: 'j_idt2',
                    d: 3,
                    onco: function(xhr, status, args) {
                        radial1.setValueAnimated(36.16220080628247);
                    }
                });
            }
        });
    });
</script>

How do I set the value of my object by calling a Javascript method with a Javascript time interval by calling a Managebean method?

<body onload="init()">
    <h:outputScript library="primefaces" name="jquery/jquery.js" />

    <h:form>
        <p:poll oncomplete  =   "radial1.setValueAnimated(#{mBeanTesteIsolado.teste})" listener="#{mBeanTesteIsolado.teste}" 
                autoStart   =   "true"
                delay       =   "3"
                update      =   "@form"
        />              

        <table>

            <tr>
                <td width="100%">
                    <canvas id="canvasRadial1" width="200" height="200">
                        No canvas in your browser...sorry...
                    </canvas>
                </td>
            </tr>

        </table>


    </h:form>

</body>


<script type="text/javascript">

     var radial1;

    function init()
    {
        // Define some sections
        var sections = Array(steelseries.Section(0, 25, 'rgba(0, 0, 220, 0.3)'),
                             steelseries.Section(25, 50, 'rgba(0, 220, 0, 0.3)'),
                             steelseries.Section(50, 75, 'rgba(220, 220, 0, 0.3)'));

        // Define one area
        var areas = Array(steelseries.Section(75, 100, 'rgba(220, 0, 0, 0.3)'));


        // Initialzing gauge
        radial1 = new steelseries.Radial('canvasRadial1', {
                                         gaugeType: steelseries.GaugeType.TYPE1,
                                         section: sections,
                                         area: areas,
                                         titleString: 'Title',
                                         unitString: 'Unit',
                                         threshold: 50,
                                         lcdVisible: true
                            });

        // O método abaixo deve ser executado eternamente, como sugerido usando pool, mas o fato de estar em uma função JavaScript
        // aparentemente não é possível
        gauge.setValueAnimated(#{mBeanTesteIsolado.teste});
    }
</script>
  • #{mBeanTesteIsolado.teste} would be a template that returns a string? Is it missing only the quotes around it? Check your browser console to see if there is a syntax error.

  • @bfavaretto #{mBeanTesteIsolado.teste} is an expression of Expression Language JSF, not template, runs on server-side. Eder, are you using any components library? In Primefaces you could use a remoteCommand to execute a Bean from Javascript.

  • @Wakim Ok, but then he injects something into js that runs client-side, right? That wouldn’t generate the syntax error I mentioned?

  • It injects a property or return method, ai depends on the type or type of the return of the teste.

  • Excuse my ignorance (if any), but can you call server-side methods in the client-side? As far as I know, server methods are restricted to the server and client methods are restricted to the client.

  • @g.carvalho97, the client-side can invoke server-side methods yes. In case it executes an http request (by Ajax or Submit de form), JSF interprets (in its phases) and calls the action, in the fifth stage, corresponding to backing bean.

  • Gentlemen, thank you for your answers. The return type of the test method is Integer, yes @Wakim, I am using primefaces, I need to set from time to graphic time in JavaScript, the Steelseries library, I had already thought of using the RemoteCommand, But how would that behave? Since the requests must be made every five seconds more or less, and the return of the method must be assigned to a JS function that arrow the value of the charts that are in Canvas

  • You can use a p:poll to make calls at intervals. Or p:remoteCommand using the serInterval javascript.

  • @Wakim, I will test here, put the return later. Thank you!

  • @Wakim, identified another possible problem, my object is declared within tags <script type="text/javascript">

  • You need to create a javascript in facelets to call what’s inside the script, perhaps by changing it.

  • You can put in your question even, only format with 4 spaces.

  • In that case you would have to use the oncomplete of p:poll to update this object gauge. And still would have access to it in another function, maybe putting as global help.

  • @Wakim, thank you for your commitment to answer me, I’m almost giving up, thinking of creating a Rest service to upgrade with Ajax, as well as in the Example http://www.desert-home.com/2013/06/how-to-use-steelseries-gauges-with.html, I did what you mentioned, I reformulated the whole question practically, take a look please.

Show 10 more comments

1 answer

3


The solution was:

  1. Use the p:poll of the first faces or a p:remoteCommand to invoke a action backing bean.

    <p:poll autoStart="true" listener="#{mBeanTesteIsolado.teste}"
            oncomplete="handleComplete(xhr, status, args)" interval="3" />
    

    Or with the p:remoteCommand:

    <p:remoteCommand name="atualizarUI" actionListener="#{mBeanTesteIsolado.teste}" oncomplete="handleComplete(xhr, status, args)" />
    

    In the case of p:remoteCommand, using a setInterval to call at regular intervals:

    setInterval(function() { atualizarUI(); }, 3000);
    

    With a focus on the role assigned to oncomplete, in relation to its signature, which must accept 3 arguments (xhr, status, args)

  2. In the Backing Bean, use the RequestContext.addCallbackParam to return data the Javascript function used in oncomplete, so much of p:poll how much of p:remoteCommand.

    Setting the Backing Bean return to the Javascript function:

    Managed Bean

    public void teste() {
        // Processamento necessário
    
        RequestContext context = RequestContext.getInstance();
    
        // Adiciona as variáveis para o JS (variável args da assinatura)
        context.addCallbackParam("nomeDoAtributo", "valor");
    }
    

    Treating the return in Javascript:

    JS

    function handleComplete(xhr, status, args) {
        var nomeDoAtributo = args.nomeDoAtributo;
    
        // Atualizar UI
        gauge.setValueAnimated(nomeDoAtributo);
    }
    

Browser other questions tagged

You are not signed in. Login or sign up in order to post.