After 9 days since the last PrimeFaces Extensions release we have done a maintenance release 0.5.1. It's built on top of PrimeFaces 3.3.1.
Please see releases notes.
We fixed a couple of critical issues, especially in components AjaxExceptionHandler, KeyFilter and ImageAreaSelect.
MasterDetail component got a new features - support of f:ajax / p:ajax and ability for disabled breadcrumb items.
On the other hand, error-prone and slow-down features were removed. These are implicitly adding of MasterDetail Id to "process" attribute and implicitly navigation without pe:selectDetailLevel. Another update to be considered for migration is renaming of ResetEditableValues - pe:resetEditableValues was renamed to a short variant pe:resetInput.
The showcase shows new / updated components for both last releases 0.5.0 and 0.5.1. A lot of descriptions - showcase documentation - were also improved and corrected. This release is available in the Maven central repo as usually.
The work on the next release has been already started with two major re-implementations. Timeline and Layout components will be re-implemented from scratch!
Wednesday, June 20, 2012
PrimeFaces Extensions 0.5.1 released
Wednesday, June 13, 2012
Dynamic forms, JSF world was long waiting for
The new PrimeFaces Extensions release 0.5.0 brought a new DynaForm component. Normally, we can build a form quite straightforward by h:panelGrid oder p:panelGrid if the count of rows / columns, positions of elements, etc. are known. That's true for static forms. But it's not possible to use h:panelGrid oder p:panelGrid if a form is described dynamically, at runtime. E.g. if the entire form's definition is placed in a database or a XML file.
DynaForm makes possible to build a dynamic form with labels, inputs, selects and any other elements by model. There aren't limitations. Explore all its features in the showcase.
Let's show how to build a simple dynamic form.
Main steps:
Create model instance: DynaFormModel model = new DynaFormModel();
Add row to regular grid: DynaFormRow row = model.createRegularRow();
Add label: DynaFormLabel label = row.addLabel(value, colspan, rowspan);
Add editable control: DynaFormControl control = row.addControl(data, type, colspan, rowspan);
Set relationship between label and control (optional): label.setForControl(control);
Repeat four last steps as many times as needed. What is could look like from UI point of view? A screenshot after a failed form validation:
The main tag is pe:dynaForm. Child tag pe:dynaFormControl matches created in Java controls by "type" attribute. This is usually a "one to many" relation. XHTML / Java (controller bean and model) code to the dynamic form above is listed below.
Explore the corresponding code in the use case Yet another forms.
Main steps:
Create model instance: DynaFormModel model = new DynaFormModel();
Add row to regular grid: DynaFormRow row = model.createRegularRow();
Add label: DynaFormLabel label = row.addLabel(value, colspan, rowspan);
Add editable control: DynaFormControl control = row.addControl(data, type, colspan, rowspan);
Set relationship between label and control (optional): label.setForControl(control);
Repeat four last steps as many times as needed. What is could look like from UI point of view? A screenshot after a failed form validation:
The main tag is pe:dynaForm. Child tag pe:dynaFormControl matches created in Java controls by "type" attribute. This is usually a "one to many" relation. XHTML / Java (controller bean and model) code to the dynamic form above is listed below.
<h:panelGroup id="dynaFormGroup">
<p:messages id="messages" showSummary="true"/>
<pe:dynaForm id="dynaForm" value="#{dynaFormController.model}" var="data">
<pe:dynaFormControl type="input" for="txt">
<p:inputText id="txt" value="#{data.value}" required="#{data.required}"/>
</pe:dynaFormControl>
<pe:dynaFormControl type="calendar" for="cal" styleClass="calendar">
<p:calendar id="cal" value="#{data.value}" required="#{data.required}" showOn="button"/>
</pe:dynaFormControl>
<pe:dynaFormControl type="select" for="sel" styleClass="select">
<p:selectOneMenu id="sel" value="#{data.value}" required="#{data.required}">
<f:selectItems value="#{dynaFormController.languages}"/>
</p:selectOneMenu>
</pe:dynaFormControl>
<pe:dynaFormControl type="textarea" for="tarea">
<p:inputTextarea id="tarea" value="#{data.value}" required="#{data.required}" autoResize="false"/>
</pe:dynaFormControl>
<pe:dynaFormControl type="rating" for="rat">
<p:rating id="rat" value="#{data.value}" required="#{data.required}"/>
</pe:dynaFormControl>
<f:facet name="buttonBar">
<p:commandButton value="Submit" action="#{dynaFormController.submitForm}"
process="dynaForm" update="_mainForm_dynaFormGroup"/>
<p:commandButton type="reset" value="Reset" style="margin-left: 5px;"/>
</f:facet>
</pe:dynaForm>
</h:panelGroup>
@ManagedBean
@ViewScoped
public class DynaFormController implements Serializable {
private DynaFormModel model;
private static List<SelectItem> LANGUAGES = new ArrayList<SelectItem>();
public DynaFormController() {
model = new DynaFormModel();
// add rows, labels and editable controls
// set relationship between label and editable controls to support outputLabel with "for" attribute
// 1. row
DynaFormRow row = model.createRegularRow();
DynaFormLabel label11 = row.addLabel("Author", 1, 1);
DynaFormControl control12 = row.addControl(new BookProperty("Author", true), "input", 1, 1);
label11.setForControl(control12);
DynaFormLabel label13 = row.addLabel("ISBN", 1, 1);
DynaFormControl control14 = row.addControl(new BookProperty("ISBN", true), "input", 1, 1);
label13.setForControl(control14);
// 2. row
row = model.createRegularRow();
DynaFormLabel label21 = row.addLabel("Title", 1, 1);
DynaFormControl control22 = row.addControl(new BookProperty("Title", false), "input", 3, 1);
label21.setForControl(control22);
// 3. row
row = model.createRegularRow();
DynaFormLabel label31 = row.addLabel("Publisher", 1, 1);
DynaFormControl control32 = row.addControl(new BookProperty("Publisher", false), "input", 1, 1);
label31.setForControl(control32);
DynaFormLabel label33 = row.addLabel("Published on", 1, 1);
DynaFormControl control34 = row.addControl(new BookProperty("Published on", false), "calendar", 1, 1);
label33.setForControl(control34);
// 4. row
row = model.createRegularRow();
DynaFormLabel label41 = row.addLabel("Language", 1, 1);
DynaFormControl control42 = row.addControl(new BookProperty("Language", false), "select", 1, 1);
label41.setForControl(control42);
DynaFormLabel label43 = row.addLabel("Description", 1, 2);
DynaFormControl control44 = row.addControl(new BookProperty("Description", false), "textarea", 1, 2);
label43.setForControl(control44);
// 5. row
row = model.createRegularRow();
DynaFormLabel label51 = row.addLabel("Rating", 1, 1);
DynaFormControl control52 = row.addControl(new BookProperty("Rating", 3, true), "rating", 1, 1);
label51.setForControl(control52);
}
public DynaFormModel getModel() {
return model;
}
public String submitForm() {
... // do something
}
public List<SelectItem> getLanguages() {
if (LANGUAGES.isEmpty()) {
LANGUAGES.add(new SelectItem("en", "English"));
LANGUAGES.add(new SelectItem("de", "German"));
LANGUAGES.add(new SelectItem("ru", "Russian"));
LANGUAGES.add(new SelectItem("tr", "Turkish"));
}
return LANGUAGES;
}
}
public class BookProperty implements Serializable {
private String name;
private Object value;
private boolean required;
public BookProperty(String name, boolean required) {
this.name = name;
this.required = required;
}
public BookProperty(String name, Object value, boolean required) {
this.name = name;
this.value = value;
this.required = required;
}
// getter // setter
}
You see that one of important features is a buil-in support for labels. DynaForm renders labels automatically - no need to write p:outputLabel. Another feature is autoSubmit flag. It allows pass form parameters in URL, build a form on page load and submit it automatically. More highlights: expandable extended view area (grid), open / close state saving, widget's client-side API, various facets.
Next screenshots demonstrate how to build dynamic forms with lables above fields and various elements like PrimeFaces separator. Two forms in this example are switched by clicking on the "Switch model" link. Note, XHTML code with pe:dynaForm stays the same, only Java model gets changed.Explore the corresponding code in the use case Yet another forms.
Monday, June 11, 2012
PrimeFaces Extensions 0.5.0 released
I'm pleased to announce the new release of PrimeFaces Extensions. It's fully compatible with the last PrimeFaces 3.3 release.
Please see releases notes and the showcase for new / updated components and use cases. This release is available in the Maven central repo as usually. See also recently updated Getting Started for more details.
We plan to deploy next releases in the cloud only. The showcase was already tested and successfully deployed on OpenShift. OpenShift provides a free JBoss 7 instance with JSF Mojarra implementation. It's not possible to change JSF impl. in the current JBoss version, so that we will stick first with Mojarra. Internal tests are running against MyFaces too (there are actually a lot of differences in both JSF impl.).
Another news: in the next 4-5 months I will do less than ever activities in the PrimeFaces Extensions. I would like to concentrate fully on the upcoming PrimeFaces Cookbook. Packt publisher has very tight deadlines for chapter's delivery dates. However, I hope we can offer interesting features in the next release iteration.
Please see releases notes and the showcase for new / updated components and use cases. This release is available in the Maven central repo as usually. See also recently updated Getting Started for more details.
We plan to deploy next releases in the cloud only. The showcase was already tested and successfully deployed on OpenShift. OpenShift provides a free JBoss 7 instance with JSF Mojarra implementation. It's not possible to change JSF impl. in the current JBoss version, so that we will stick first with Mojarra. Internal tests are running against MyFaces too (there are actually a lot of differences in both JSF impl.).
Another news: in the next 4-5 months I will do less than ever activities in the PrimeFaces Extensions. I would like to concentrate fully on the upcoming PrimeFaces Cookbook. Packt publisher has very tight deadlines for chapter's delivery dates. However, I hope we can offer interesting features in the next release iteration.
Wednesday, June 6, 2012
PrimeFaces Extensions is getting solid. Trailer.
PrimeFaces Extensions project is going to be released on 9. June (Saturday). Here is a video trailer to the upcoming version. The official, detailed announcement will be published after the 0.5.0 release.
Stay tuned.
Stay tuned.
Monday, April 23, 2012
DWR in JSF? Easy, with PrimeFaces Extensions.
Everybody knows DWR (Direct Web Remoting). DWR enables Java on the server and JavaScript in a browser to interact and call each other. It has several modules for Spring, Struts, Guice, etc. integration. There is also an JSF integration, but it's not fit enough to be used in JSF 2. It requires an expensive XML configuration or a configuration via annotations (@RemoteProxy, @RemoteMethod). The configuration describes a mapping between Java methods and JavaScript functions. JSF 2 standard lacks the ability to call arbitrary methods on JSF managed beans as well. There are some attempts to push up this intention and intergrate this technique in JSF 2, but nothing happend until now. PrimeFaces component library has a component RemoteCommand. Unfortunately, but it doesn't allow to call any Java method with any parameters. Passing parameters is not comfortable with this implementation. They have to be passed as
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.
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.
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()");
// 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()");
Labels:
Ajax,
JavaScript,
JSF,
PrimeFaces Extensions,
Web
Subscribe to:
Posts (Atom)



