One the most annoying and tedious tasks of JSF programming is having to deal with labels and messages. AngularFaces takes the scare out of that.
Mind you, how often have you written something like this?
<prime:panel header="Who are you?">
<prime:panelGrid columns="3">
<prime:outputLabel value="last name" for="lastNameID" />
<prime:inputText id="lastNameID" value="#{customer.lastName}" label="last name"/>
<prime:message for="lastNameID" />
<prime:outputLabel value="first name" for="firstNameID" />
<prime:inputText id="firstNameID" value="#{customer.firstName}" label="first name"/>
<prime:message for="firstNameID" />
</prime:panelGrid>
</prime:panel>
To make the tabular layout visible, the examples on this page deliberately draw lines around the grid cells.
That's two input fields, but six JSF components. Before the invention of @next and @previous, you also had to add ids to assign the label and the message to the input field. In fact, you still have to do so unless you're using PrimeFaces. Among other things, the ids make copying and pasting input fields a pain.
AngularFaces automatically adds the label and the error message to input fields. The label attribute of the input field is taken as the label caption:
<prime:panel header="Who are you?">
<prime:panelGrid columns="3">
<prime:inputText value="#{customer.lastName}" label="last name"/>
<prime:inputText value="#{customer.firstName}" label="first name"/>
</prime:panelGrid>
</prime:panel>
In many cases, the label can be derived automatically from the bean attribute name. If you omit the label attribute of the input field, AngularFaces assumes the bean attribute name is a camel case version of the label. That's a useful feature for rapid prototyping - and even beyond if you see to it to chose expressive variable names. For example, the next example is as simple as can be:
<prime:panel header="Who are you?">
<prime:panelGrid columns="3">
<prime:inputText value="#{customer.lastName}"/>
<prime:inputText value="#{customer.firstName}"/>
</prime:panelGrid>
</prime:panel>
As of AngularFaces 2.0, automatic addition of labels and messages requires a little preparation:
<h:body style="width:1000px" ng-controller="LabelDemoController" ng-app="AngularFacesExamples">
<h:form id="angular">
<prime:commandButton value="save" update="angular" action="..." />]]>
angular.module("AngularFacesExamples", [ "angularfaces" ]);
<f:view xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:prime="http://primefaces.org/ui">
<h:head>
<title>car dealer - customer contact information</title>
</h:head>
<h:body style="width:1000px" ng-controller="LabelDemoController"
ng-app="AngularFacesExamples">
<h:form id="angular">
<prime:panel header="Contact information">
<prime:panelGrid columns="3">
<prime:inputText value="#{customer.lastName}" />
<prime:inputText value="#{customer.firstName}" />
<prime:inputText value="#{customer.dateOfBirth}" />
<prime:inputText value="#{customer.emailAddress}" />
<prime:inputText value="#{customer.iAgreeToTheTermsAndConditions}" />
</prime:panelGrid>
<prime:commandButton value="save" update="angular" action="#{customer.save}" />
</prime:panel>
</h:form>
</h:body>
</f:view>
AngularFaces 2.0 takes a simplistic approach: labels always precede their input field, and messages always follow the input field. That's why the example uses a PrimeFaces panel grid with columns="3": The input field is accompanied by two components that are added automatically to the JSF view.
In a future version, AngularFaces is going to have more flexibility (such as putting labels above and messages below the input field).
There are three ways to influence the creation of labels and messages:
First, you can switch off the automatical creation of labels and messages by adding an attribute to <h:body> (or <h:body> if you prefer the relaxed syntax of AngularFaces).
Second, you can add the generation of labels and messages for each individual field:
The third possibility is to simply provide a label to the field. AngularFaces doesn't add a label if it recognizes there's already a label. So all you have to do is to add an outputLabel manually, and to set the for attribute. The same applies to the message attribute.
As of AngularFaces 2.0, this feature does not work with @next and @previous.
Suppressing message generation also disables the client side bean validation. You can fix it by adding a <puimessage /> tag to the <h:message /> tag. <puimessage /> is a client side widget implemented as an AngularJS directive. It examines the css class of the associated input field and displays an error message if needed. If there's no error message to display, it defaults to the optional "servermessage" attribute. For instance, the HTML code generated by AngularFaces 2.0 to display the label "number 2", a numeric input field and the error message looks like so:
<tr>
<td><label for="myForm:j_idt7">number 2</label></td>
<td><input name="myForm:j_idt7" value="65" max="100" type="number" required=""
min="10" ng-model="calculatorBean.number2" /></td>
<td><puimessage af-for="myForm:j_idt7"></puimessage></td>
</tr>
To display the error message using the PrimeFaces look and feel, add the attribute primefaces="true":
<tr> <puimessage primefaces="true" af-for="myForm:j_idt7"></puimessage> </tr>
Suppressing the automatic generation of labels doesn't break client side bean validation, but it also has a side effect. AngularFaces doesn't generate standard JSF or PrimeFaces labels, but <puilabel> that are partially created on the client side. They mimick the look and field of the host JSF framework, but they are also colored red if AngularJS considers the input field invalid. Standard JSF or PrimeFaces labels change their color only after an AJAX request (unless you activate the Client Side Validation feature of PrimeFaces 4+).