Paul.F-G Paul.F-G - 1 month ago 15
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

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.