Paul.F-G Paul.F-G - 1 year ago 69
Ajax Question

How to set JS effects on progress bar managed by a backing bean?

I have

<h:form id="form">
<p:progressBar id="pbAjax" value="#{backingBean.value}" labelTemplate="{value} %"/>
<p:poll listener="#{backingBean.updateValue()}" update="pbAjax"/>
</h:form>


And

@ManagedBean
public class BackingBean implements Serializable {
private Integer value;

@PostConstruct
public void init(){
this.value = (int)Math.round(Math.random()*10);
}

public Integer getValue(){
this.value = (int)Math.round(Math.random()*10);
return value;
}

public void setValue(Integer value){
this.value = value;
}

public void updateValue(){
this.value = (int)Math.round(Math.random()*5);
}
}


The progress bar is working fine.

Now I would like to implement a "ease-in" effect.
Since the values change with Ajax requests on a backing bean and not a Javascript function, how can I put a javascript effect on the progress bar, or "intercept" the XHR response to apply a "ease-in" effect in Javascript before it updates the component?

If it can help, I see this kind of Ajax response :

<?xml version='1.0' encoding='UTF-8'?>
<partial-response id="j_id1">
<changes>
<update id="form:j_idt40:18:pbAjax">
<![CDATA[
<div id="form:j_idt40:18:pbAjax" class="ui-progressbar ui-widget ui-widget-content ui-corner-all">
<div class="ui-progressbar-value ui-widget-header ui-corner-all" style="display:block;width:9%">
</div>
<div class="ui-progressbar-label" style="display:block">
9 %
</div>
</div>
<script id="form:j_idt40:18:pbAjax_s" type="text/javascript">
$(function() PrimeFaces.cw(
"ProgressBar",
"widget_form_j_idt40_18_pbAjax",
{
id:"form:j_idt40:18:pbAjax",
initialValue:6,
ajax:false,
labelTemplate:"{value} %"
}
);
});
</script>
]]>
</update>
<update id="j_id1:javax.faces.ViewState:0">
<![CDATA[-1946172786751610988:-1619424769397867671]]>
</update>
</changes>
</partial-response>


Thanks for any help.

Answer Source

With the setup shown above, the following solution works.

  1. I've set the "update" method to static in my Managed Bean.

    public static Integer updateValue(){
        return (int)Math.round(Math.random()*5);
    }
    
  2. Created a servlet with the content of my static method in the response body.

    @WebServlet(name = "ProgressBarServlet", urlPatterns = ("/ProgressBarServlet"})
    public class ProgressBarServlet extends HttpServlet {
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("ProgressBarUpdate", "no-cache");
        PrintWriter out = response.getWriter();
        out.print(BackingBean.updateValue()+"");
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        processRequest(request, response);
    }
    
  3. Created a cyclic XHR request on the servlet url.

     <script type="text/javascript">
            setInterval(function () {
                    testAjax("ProgressBarServlet");
            }, 5000);
    
            function testAjax(servletURL) {
                    var xmlhttp;
                    if (window.XMLHttpRequest) {
                        xmlhttp = new XMLHttpRequest();
                    }
                    else {
                        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
                    }
                    xmlhttp.open("GET", servletURL, true);
                    xmlhttp.onreadystatechange = function() {
                        if (xmlhttp.readyState === 4) { 
                            if (xmlhttp.status === 200) {
                                PF('pbAjax').setValue(xmlhttp.responseText);
                            }    
                            else {
                                PF('pbAjax').setValue("Error");
                            }
                        }
                    };
                    xmlhttp.send(null);
             }
    </script>
    

So the value of the progress bar is set with PrimeFaces Javascript and has the ease-in effect.

Albeit it might not be the most efficient way to update components, this solution can be useful for one or few components.

It is not relevant in my case, because I have a p:dataTable with a progress bar in each row and cannot link generated ids to Javascript.