Tuesday, 29 January 2013

AngularPrime, Integration of PrimeUI within AngularJS


Introduction

I received a lot of reactions on the first trial of my integration between PrimeUI and AngularJS (see here). Therefor I decided to try a more complete integration where all the 16 components of the 0.7 release of PrimeUI are integrated as widgets in AngularJS

Alpha release

My code can be found in GitHub at the following location.
For the moment, it isn’t yet a real widget module like AngularUI.  I created some pages where all the widgets are tested and where you can see what I added as a directive to make it work.
I concentrated myself mainly on the graphical aspects and not always on the functional side of the integration.  Therefor you can find a disabled button that is still clickable, making components dynamical disabled and enabled isn’t always foreseen, and so on.
Also the browser support is minimal.  I mainly tested with Firefox and Chrome and found out that for instance with IE9, there is a problem on all pages.

One or multiple directives

For the widgets that I started first (like panel), I could implement all the functionality with one new directive and at most 2 additional attributes that defines the extra functionality.  So I had the following tag

<div id="options" pui-panel pui-collapsed=”false” pui-closable style="margin-bottom:20px" title="Toggle and Close">

The pui-panel attribute is a real directive, the other 2, pui-collapsed and pui-closable, where just inspected in the directive code.

But soon I found out that for some widgets, like Galleria, there where too much options. Implementing them all with an attribute would made the html unreadable.

For the second group of widgets, I started to use the pui-options attribute for specifying the configuration.  That allowed me to use the object notation to define the parameters, something like

<div id="options" pui-panel pui-options="{'collapsed': false, 'closable': true}" style="margin-bottom:20px" title="Toggle and Close">

This made it more compact but had another benefit.  I could also write the name of a property within the controller to define the options.

<div id="options" pui-panel pui-options="panelOptions" style="margin-bottom:20px" title="Toggle and Close">

$scope.panelOptions = {collapsed: false, closable: true}
 
Changing the object, like setting collapsed to true, has no effect. For some options, like collapsed I think I can foresee that in one of the next versions, but for others like closable it isn’t possible. It will not be possible since the DOM structure is changed to make closable possible. On the other side, something like collapsed is just changing the visual state and can easily be done.
At the end, I also abandoned the pui-options attribute and used the directive itself. Because then there is no longer the confusion between the real directive and the attribute.

Based on PrimeUI

AngularPrime uses the widgets which are provided by Çağatay Çivici in the PrimeUI library.
I try to use the code unmodified but needed already 3 small changes. But when there will be some more complex widgets in the next releases of PrimeUI, I’m afraid that I need to modify the code to make the integration possible.
However, I hope to be able to integrate the bugfixes made for the PrimeUI components into the AngularPrime module.

Requirements

Since PrimeUI builds on JQuery and JQueryUI, AngularPrime needs those JavaScript frameworks.
This means that the people that try to create an application with only a few kiloBytes of download, will not be able to use AngularPrime. For me, that is not a concern as my main goal is to learn JavaScript and AngularJS.

Widget overview 

Accordion: Container component that displays content in stacked format.
Button: Button with theming
Checkbox: Also with theming
Dialog: Panel component that can overlay other elements on page.
Fieldset: Grouping component as an extension to html fieldset.
Galleria: Display a set of images
Growl: Based on the Mac’s growl notification widget
Inputtext: With theming
Inputtextarea: With theming, autosizeable and with counter of remaining characters
Panel: Grouping component with content toggle
Password: Has a strength indicator
Radiobutton: With theming
Rating: Star based rating system
Spinner: To provide a numerical input via increment and decrement buttons
TabView: Tabbed panel component.
This widget is the first major difference with PrimeUI. You don’t have to specify the span to have a closable version. Just setting the option closable to true, the required changes in the DOM are performed.

Next version

I’m already planning version 0.2 since creating this alpha version was a pleasure. So what can you expect:
- Define AngularPrime as a real AngularJS module. So adding the javaScript files and putting a dependency will be enough.
- Integrate the new widgets in versions 0.8 and later of the PrimeUI library
- Fix the todos mentioned on the example pages. Most of them are related to the dynamic disabling and enabling of widgets.
- Provide minified and regular JavaScript and CSS code of AngularPrime

Conclusion

With this first version I just tried to have the graphical aspects more or less correct. Now I need to make the directive more uniform, provide more functionality and make it a real AngularJS module. Stay tuned.

Monday, 21 January 2013

Comparison between AngularJS and JSF

Introduction

Although AngularJS and JSF are completely different frameworks at first sight, they have a lot of similarities.
When I was looking for a framework a couple of months ago, to do some web development with JavaScript, I stumbled by accident on AngularJS.
And immediately when I looked at the home page of the framework, it felt very familiar with JSF which I'm already doing for more then 5 years now.
And although my knowledge of JavaScript is very minimal, I was able to create a very simple application which uses a controller, a services, a partial html file etc...
Because the concepts are almost identical and for the JavaScript syntax, I had a peep in some other example applications.
By now, I realize that there are a lot of JavaScript frameworks that are doing more or less the same as AngularJS but for me, having a JSF background, AngularJS is the most natural choice.
I recreated the example I made for my previous blog entry in JSF so that you can see the similarities even better. Code can be found on GitHub.

Comparing view

The first similarity is the way how the view is defined.  Both are (x)html files where you define with html tags the structure of your page. And with some markers/tags you add information to include the dynamic data or parts.
Below the examples
<h:form id="name-form">
        <p:panel id="panelTitle" header="Names list">
            first name <p:inputText id="firstName" value="#{personView.person.firstName}"/>
            <br/>
            last name <p:inputText id="lastName" value="#{personView.person.lastName}"/>
            <br/>
            <p:commandButton id="saveBtn" actionListener="#{personView.save}" value="Save" ajax="false" />
        </p:panel>
        <ui:fragment rendered="#{not empty personView.list}">
            <ul id="names-list">
                <ui:repeat value="#{personView.list}" var="person">
                    <li>
                        <div class="view">
                            <label><h:outputText value="#{person.firstName} #{person.lastName}"/></label>
                            <p:commandButton styleClass="destroy" actionListener="#{personView.deleteById(person.id)}"
               ajax="false" id="removeBtn" value="?"/>
                        </div>
                    </li>
                </ui:repeat>
            </ul>
        </ui:fragment>
    </h:form>
    <p:growl showDetail="true"/>


and for AngularJS
<section id="namesapp" ng-cloak>
  <header id="header">
    <form id="name-form">
      <div ng-controller="NamesCtrl" id="">
        <div id="panelTitle" pui-panel title="Names list">
          first name <input id="firstName" ng-model="firstName" type="text"/>
          <br/>
          last name <input id="lastName" ng-model="lastName" type="text"/>
          <br/>
          <button ng-click="addPerson()" type="button">Save</button>
          <ul id="names-list">
            <li ng-repeat="person in data">
              <div class="view">
                <label>{{person.firstName}} {{person.lastName}}</label>
                <button class="destroy" ng-click="removeName(person)"></button>
              </div>
            </li>
          </ul>
        </div>
      </div>
    </form>
    <div id="growl"></div>
  </header>
</section>



At first glance, the AngularJS version looks more like regular HTML then the JSF version.  The JSF version uses quit a lot of tags from the PrimeFaces component library.  This means that you see the specific tags of it like <p:commandButton>.
With the AngularJS version, you see only the custom directive pui-panel on the div tag.  Custom directives can also be defined as using elements in the page.  So I can define the PrimeUI panel as <pui-panel ..> which results in almost identical tags as with JSF.
And in a later version of the integration between PrimeUI and AngularJS I have also the custom directives pui-input, pui-button and so on.
So for me, defining the view in AngularJS and JSF is identical.

Comparing expressions

AngularJS and JSF have both a kind of expression language to mark the places where the dynamic content must be inserted. Within JSF you have #{} where as AngularJS looks for {{}}.  Besides the notation who is very alike, there are some differences.
Within AngularJS, you define the controller seperately, with the ng-controller directive.  With JSF, you specify the managed bean within the expression itself.  This means that you have greater flexibility with JSF and your managed beans are more fine grained then the AngularJS controller.
I find also the usage of the expression markers, the {{}} and #{}, is more consistent within JSF.  When using the directives ng-model, ng-repeat, etc ... the {{}} marker isn't needed because AngularJS evaluates the string.  But this makes it less readable for a novice as me. You need to know that the string placed in directives are some variables defined in a controller which is defined in some of the parent tags.

Controller versus Managed bean.

The AngularJS controller and the JSF managed bean are very similar.  Of course, they are written in another language but both have the same architectural role. They are both referenced from the expression language, they buffer the values for the screen and they contain the methods referenced from the on-click of the buttons.
The actual work is in both occasions delegated to some services injected into the controllers.

AJAX

The partial page updates is one of the major differences between the frameworks. With JSF, by default the page is completely rebuilded after each post to the server.  With the versions 2.x there is support for partially updating the page.  But you have to specify it on every place where you like to use it. This is in contrast with AngularJS where the values of the expression language is updated after every 'event'.
So for example, when you start typing in an input field with the ng-model directive, all the expressions in the page, the watches, are checked to see if they need to be updated.  Of course, this gives the user maximal responsive applications but can lead to a performance issue when you have a lot of those expressions/watches in your page.  But according to the documentation, 1000 should be no problem what is sufficient for normal applications.

AngularJS application generation

Due to the analogy between the 2 frameworks, I started playing with the idea that I could take a JSF application and 'compile' it to the AngularJS version.
I knew that it wouldn't be easy but started in a good spirit and defined some new JSF tags that where needed.  My page looked something like this:
<r:app>
  <h:form id="name-form">
   <r:controller library="person" url="personList" handler="#{personService.loadAllPersons}" alias="persons"
        <ui:fragment rendered="#{not empty persons}">
            <ul id="names-list">
                <ui:repeat value="#{persons}" var="person">
                    <li>
                        <div class="view">
                            <label><h:outputText value="#{person.firstName} #{person.lastName}"/></label>
                            <p:commandButton styleClass="destroy" actionListener="#{personService.deleteById(person.id)}"
               ajax="false" id="removeBtn" value="?"/>
                        </div>
                    </li>
                </ui:repeat>
            </ul>
        </ui:fragment>
    </r:controller>    
  </h:form>
  <p:growl showDetail="true"/>
</r:app>
With the controller tag, you would be able to define the URL on which the JAX-RS rest would be configured (here /person/personList), the method of the CDI bean which should provide the data and the alias under which this list is available for the expression language.
Besides the generation of the AngularJS HTML file, it is also the intention to generate the JAX-RS classes that handles the communication with JSON data.
Now that I'm a few months further, I realize that my target was set too high. A lot of things are already working like
  • A custom ELResolver to support the alias created in the controller app
  • A JSF preview, so that you can run the JSF application which contains the app and controller tags.
  • The generation of the AngularJS HTML page and javascript files.
  • Basics of the JAX-RS classes generation
  • A maven plugin with a 'compiler' that takes a JSF maven app and creates a AngularJS maven app.
But a lot more work need to be done before it is useable.  And since I don't have that much spare time, I decided to postpone this idea and focus on other topics of the StatelessPrime idea.

In one of the next blog posts, I can present you a way to integrate JSF and AngularJS application in a single web page. And with integrate, I mean that JSF calls AngularJS controller methods and AngularJS code calls JSF backing bean methods.

Conclusion

Of course, JSF which is mainly a server side framework is different from AngularJS, a JavaScript framework for the browser.  And they target also different kind of web applications.  Both they are surprisingly alike in defining the html output and the concepts.

So someone who is familiar with JSF can learn very quickly AngularJS and vice versa.