// call a JavaScript function bound to RemoteCommand with parameters myFunction({param1: 'value1', param2: 'value2'});and extracted from the current request on the server side. No JSF converters, validators can be applied, etc. Fortunately we have PrimeFaces Extensions project :-) which brings an own implementation of RemoteCommand. It covers two important use cases.
1) Assign JavaScript parameters to a property in a bean. It can be done in a convenient way with pe:remoteCommand and pe:assignableParam. AssignableParam specifies a name of the parameter and an EL expression for a corresponding Java method (setter) the parameter will be applied to. It allows to attach converters as well. The code below shows how it works.
<p:growl id="growl" showDetail="true" /> <pe:remoteCommand id="applyDataCommand" name="applyData" process="@this" update="subject date circle growl" actionListener="#{remoteCommandController.parametersAssigned}"> <pe:assignableParam name="subject" assignTo="#{remoteCommandController.subject}"/> <pe:assignableParam name="date" assignTo="#{remoteCommandController.date}"> <f:convertDateTime type="both" dateStyle="short" locale="en"/> </pe:assignableParam> <pe:assignableParam name="circle" assignTo="#{remoteCommandController.circle}"> <pe:convertJson /> </pe:assignableParam> </pe:remoteCommand> <script type="text/javascript"> circle = { radius: 50, backgroundColor: "#FF0000", borderColor: "#DDDDDD", scaleFactor: 1.2 }; circle2 = { ... }; </script> <h:outputLabel for="subject" value="Subject: " /> <h:outputText id="subject" value="#{remoteCommandController.subject}" /> <h:outputLabel for="date" value="Date: " /> <h:outputText id="date" value="#{remoteCommandController.date}" /> <h:outputLabel for="circle" value="Circle: " /> <h:outputText id="circle" value="#{remoteCommandController.circle.radius} - #{remoteCommandController.circle.backgroundColor} - #{remoteCommandController.circle.borderColor} - #{remoteCommandController.circle.scaleFactor}" /> <p:commandButton value="Apply Data" type="button" onclick="applyData('hello world', '5/14/07 12:55:42 PM', JSON.stringify(circle))" /> <p:commandButton value="Apply Second Data" type="button" onclick="applyData('hello user', '7/11/01 11:55:42 PM', JSON.stringify(circle2))" />You see that three parameters are passed to the JavaScript function applyData which is bound to the pe:remoteCommand via name attribute. Every pe:assignableParam takes a parameter and assign to the corresponding bean property via assignTo attribute. You can also see that an attached date converter converts date string to a date object (java.util.Date) and an JSON converter (from the PF Extensions project) converts a JavaScript object (circle) to a model Java class (Circle.java). The bean (controller class) and the Circle.java (model class) look simple:
@ManagedBean @RequestScoped public class RemoteCommandController { private String subject; private Date date; private Circle circle; // getter, setter public void parametersAssigned() { FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "ActionListener called", "Parameters assigned"); FacesContext.getCurrentInstance().addMessage(null, msg); } } public class Circle implements Serializable { private int radius; private String backgroundColor; private String borderColor; private double scaleFactor; // getter, setter }Picture:
2) Call a remote Java method with any parameters from JavaScript. It can be done with pe:remoteCommand and pe:methodParam, pe:methodSignature. This is a DWR like approach with zero configuration. MethodParam specifies a name of the parameter and MethodSignature specifies a comma or space separated list with full qualified class names. Class names should match passed parameters in the same order as they were defined. The code below shows how it works.
<p:growl id="growl" showDetail="true" /> <pe:remoteCommand id="applyDataCommand" name="applyData" process="@this" update="growl" actionListener="#{remoteCommandController.printMethodParams}"> <pe:methodSignature parameters="java.lang.String, java.util.Date, org.primefaces.extensions.showcase.model.Circle" /> <pe:methodParam name="subject"/> <pe:methodParam name="date"> <f:convertDateTime type="both" dateStyle="short" locale="en"/> </pe:methodParam> <pe:methodParam name="circle"> <pe:convertJson /> </pe:methodParam> </pe:remoteCommand> <script type="text/javascript"> circle = { radius: 50, backgroundColor: "#FF0000", borderColor: "#DDDDDD", scaleFactor: 1.2 }; circle2 = { ... }; </script> <p:commandButton value="Apply Data" type="button" onclick="applyData('hello world', '5/14/07 12:55:42 PM', JSON.stringify(circle))" /> <p:commandButton value="Apply Second Data" type="button" onclick="applyData('hello user', '7/11/01 11:55:42 PM', JSON.stringify(circle2))" />The bean method printMethodParams (defined as actionListener) will be called when user pushes one of the both command button. The method generates a message which is shown as growl popup.
@ManagedBean @RequestScoped public class RemoteCommandController { public void printMethodParams(String subject, Date date, Circle circle) { FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "ActionListener called", "Subject: " + subject + ", Date: " + date + ", Circle - backgroundColor: " + circle.getBackgroundColor()); FacesContext.getCurrentInstance().addMessage(null, msg); } }Converters are used as well. They can be also defined as usual in JSF by converter attribute in pe:assignableParam / pe:methodParam.
Described features are available in the PF Extensions 0.5-SNAPSHOT.
Edit: DWR allows a reverse call from Java to JavaScript as well. It works bidirectional. Well, it's possible with Atmosphere integration or PrimeFaces Push too. Furthermore, PrimeFaces provides a server side way to execute JavaScript when the ajax request completes. Example: RequestContext.getCurrentInstance().execute("dialog.hide()");