31
votes

Is it possible to update a PrimeFaces component from javascript so that it would be force to refresh?

I am making an ajax save call using this button in a dialog. I have attached my custom javascript on the oncomplete event.

<p:growl life="1500" id="showmessage"/>
<p:dialog id="addMemberDialog" widgetVar="addMemberDlg">
    <!-- More Code -->
    <p:commandButton value="Save"
        actionListener="#{memberManagedBean.save}"
        oncomplete="handleSaveNewMember(xhr, status, args)"
        update=":memberListForm:membersTable createupdateform "
        process="@form" />
</p:dialog>

..during save button, I am adding a message here to display it to the client using the growl component.

public void save(ActionEvent event) {
    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
            "Successfuly Add user", "Successfuly Add user");
    FacesContext.getCurrentInstance().addMessage(null, message);

}

My problem is, how can I sequence the UI such that, i should hide the dialog first before the growl component could show the meesage?

function handleSaveNewMember(xhr, status, args) {
    addMemberDlg.hide();
    //update the growl after the dialog was hidden?
}

What's happening is that the growl component is displayed alongside the dialog at the same time.

Thanks.

6
You must be showing the dialog on a button click. Did you try update of growl from that button rather than from Save button in dialog ?rags

6 Answers

57
votes

You can use PrimeFaces' <p:remoteCommand> for this.

<p:remoteCommand name="updateGrowl" update="showmessage" />

which is to be invoked as

<p:commandButton ... oncomplete="addMemberDlg.hide(); updateGrowl();" />

In this particular case there's however a simpler way. Set the autoUpdate attribute of <p:growl> to true.

<p:growl autoUpdate="true" life="1500" id="showmessage"/>

It'll auto-update itself on every ajax request. If your component actually didn't support it, then you could always wrap it in a <p:outputPanel> which also supports that attribute.

<p:outputPanel autoUpdate="true">
    ...
</p:outputPanel>
5
votes

you can always do something like this (remove the showmessage id from your save button update attribute)

<h:commandButton style="display:none" id="myBtn" >
    <f:ajax render=":showmessage"/>
</h:commandButton>

function handleSaveNewMember(xhr, status, args) {
    ...
    jQuery("#myBtn").click();
}

EDIT But anyway in your current code , isn't the dialog being closed at the same time that the grwol being updated ?

3
votes

My advice:

  1. Use <p:remoteCommand> with an actionListener attribute. This attribute invokes a backing bean method that contains FacesContext.addMessage code, this way: <p:remoteCommand actionListener="myBean.testMethod()" />
  2. Next, in your handleSaveNewMember script, invoke the remoteCommand name attribute after addMemberDlg.hide(); this way: <p:remoteCommand name="testScript" actionListener="myBean.testMethod()"/>. Then, function handleSaveNewMember(xhr, status, args) { addMemberDlg.hide(); testScript(); }
  3. Add update attribute to remoteCommand pointing growl component: <p:remoteCommand name="testScript" actionListener="myBean.testMethod()" update="showmessage" />
  4. Your commandButton is OK.

This worked for me.

Greetings.

0
votes

Why can't you put p:Dialog inside of < h:panelGroup >. like

< h:panelGroup id="addUser" rendered = "boolean value " >
    < p:dialog id="addMemberDialog" widgetVar="addMemberDlg" >
        <!-- More Code -->
        < p:commandButton value="Save" actionListener="#{memberManagedBean.createOrUpdate}"
                oncomplete="handleSaveNewMember(xhr, status, args)"
                update=":memberListForm:membersTable createupdateform :showmessage :addUser"
                process="@form" />
    < /p:dialog >
< /h:panelGroup>

boolean value which should be set in your save method. on setting this as false in your save method it wont display while updating it. So growl message alone will display. But before calling this save method this boolean value set as true.

0
votes

You can use an PrimeFaces element called p: remotecommand. This element will execute an action (to call a bean method, for example) and to execute an update after that action.

There is an example in this post http://devdublog.blogspot.com/2015/04/best-way-for-calling-method-of.html.

0
votes

PrimeFaces has an Ajax API. You can use PrimeFaces.ajax.Request.handle(cfg), or the shorter version PrimeFaces.ab(cfg) to trigger an update by using the update propery of the config object.

You probably want to set the process propery to your needs. If you don't need anything to be processed set it to @none.

Then, you are required to set the source property. You can set it to the current component using EL: #{component.clientId}.

Putting this all together you get:

PrimeFaces.ab({source:'#{component.clientId}',process:'@none',update:'clientIdToUpdate'})

I created a custom EL function to reduce this to #{my:ajaxUpdate('clientIdToUpdate')}:

public static String ajaxUpdate(final String clientIds) {
  return "PrimeFaces.ab({source:'"
                 + UIComponent.getCurrentComponent(Faces.getContext()).getClientId()
                 + "',process:'@none',update:'"
                 + clientIds
                 + "'})";
}

This reduces (for example):

<p:remoteCommand name="updateMyComponent" update="myComponent"/>
...
<p:ajax event="filter" oncomplete="updateMyComponent()"/>

to:

<p:ajax event="filter" oncomplete="#{my:ajaxUpdate('myComponent')}"/>