Developing the AngularJS Tagcloud application - appendix for Marrying the Worlds of ADF and HTML5 image9

Developing the AngularJS Tagcloud application – appendix for Marrying the Worlds of ADF and HTML5

This blog-post accompanies the OTN Article Marrying the Worlds of ADF and HTML 5 – to provide some details about setting up the HTML5/AngularJS development environment and about the development of the AngularJS application.

Get hold of the sources

All sources associated with the article are available from GitHub: https://github.com/pavadeli/adf-html5. You can clone this GitHub repository or download the sources in a zip-file that you can subsequently extract locally. The directory structure that you will end up with looks like this:

image

 

The top folders contain the ADF application with embedded AngularJS component, the lower (html-…) directories contain the pure HTML5 & AngularJS applications.

Set up the Development Environment

Just like JDeveloper is the IDE for ADF application development – including facilities for library management, building and deploying the application and with the integrated WebLogic Server as the run time engine, we need an environment to develop the rich client, HTML5 & AngularJS application. We use a different set of tools in this environment – and while you have some choice, we suggest the following combination of tools:

–IDE: Sublime Text Editor

–Package Manager: Node.js – NPM

–Build (Ant-like): Gulp

–Dependency Management (Maven-style): Bower

–Run Time: Google Chrome browser

Install node.js (http://nodejs.org/). This will give you access to the Node.js Package Manager (NPM). With NPM you can install Gulp (build tool, super hip, does for JS what ANT does for Java) and bower (dependency management, is to JS what Maven is for Java)

Open the command line and type:

> npm install -g gulp bower

This will install both gulp and bower on your local file system.

To build the pure HTML5 sample applications in the folders html-step1, html2-step2 and html, you have change the current directory to each of these folders respectively and for each perform these steps:

> npm install

to fetch all design-time dependencies (the tools used via gulp). The file package.json tells NPM what to install:

image

Next, to fetch the run time dependencies (which means: AngularJS):

> bower install

This instructions results in the creation of the bower_components subdirectory with various JavaScript components downloaded from GitHub or some other git endpoint. The packages that Bower should install are configured in the file bower.json:

image

After running bower install you can run bower list to see the list of installed packages:

image

Note that the angular component as well as the bower-tagcanvas are known to bower (as you can check in the bower directory of components at http://bower.io/search/). Details about a [bower] package can be retrieved with bower info [package name]:

image

The next command starts the build server (Gulp):

> gulp serve

This will not take long (maybe two seconds), and will open a browser window. In the command line window, you will see an indication of the host and port at which you can access the server:

image

The actions performed by Gulp are defined in the gulpfile.js file. This file defines for example that gulp serve will publish all files in the current directory (./) and will watch for changes to all files with extension .html and inside the components directory:

image

Run the sample applications

When you started the build server with gulp serve, the run time server was started – this server provides resources to the associated run time presentation engine: the browser. Real AngularJS developers seem to only use Google Chrome, so open that browser, and point it at the URL suggested in the command line window by the Gulp Server – with /tagcloud-html.html appended (for the folder html-step1):

image

You can open the main source file for this application, in for example Sublime Text editor:

image

Add a new value for a link and save the text file. You will notice that without refreshing, the browser updates the page (thanks to a Web Socket channel to the Gulp Server):

image

Stop Gulp and change to the html-step2 directory

image

Open the tagcloud-bridge.html document in the browser window:

image

This application contains the bridge module into which the guest-tag-cloud component has been injected. Both tagclouds shown in the page are completely independent instances of the same AngularJS module.

Note: instead of checking out the html-step1 and html-step2 directories, you could also immediately go to the html directory, start the Gulp server and open the index.html document that gives access to both page:

image

The AngularJS modules – bridge and tagcloud – can be packaged into a couple of JS files that can easily be integrated into other applications, such as an ADF application. You achieve this through the command “gulp”. This will trigger the default action in the gulp.js file, which states that both integration and tagcloud should be built:

image

The result of this action should be written to directory ../adf/ViewController/public_html/scripts, which is part of the ADF application that embeds the tagcloud component.

image

Note that a typical gulp build pipeline may also contains steps for

  • Minification (reducing the size of the JS file, often with up to 70 – 80%)
  • Jslint (static code checking, similar to Sonar in Java )
  • Various preprocessing / checking tasks

Exploring the AngularJS application

Without diving too deeply into AngularJS there are some things to point out in the AngularJS applications.

A good place to start is in the file tagcloud-html.html:

image

At (1) we see a custom HTML tag, tag-cloud. We can use this tag because HTML5 allows custom tags, we engage AngularJS and in the tagcloud.js file – that is imported and defines the included tagcloud module – we have defined an AngularJS directive that instructs Angular to relate this tag to the tagcloud module.

At (2) we see an Angular data binding expression: {{log}} will result in the contents of the log variable in the Angular scope to be returned. At (7) (see below), we see how we put a function on the scope as tagClicked. This function will be invoked whenever a tag is clicked in the tagcloud. The function will create a string and put that in the scope as log. Because of Angular’s two-way databinding, the update of log in the scope by this function will immediately result in an update of the contents of the <pre> tag in the page.

At (3) we see the import of the JavaScript libraries – two were created by bower and one is our hand-crafted Angular module tagcloud, to be discussed below.  At (4) the Angular App myApp is initialized with dependencies on the tagcloud module. A controller is set up for myApp and defined with an anonymous function. This function puts a collection called tags on the scope with values that represent a simulated initialization phase. After a timeout of 2 seconds (2000 ms), a new value for tags is put on the scope (6). Again, through two way data binding (and the watch function defined for tags in the tagcloud.js file), the consumer of the tags variable will be updated on both occasions when the tags variable is set.

image

 

Let’s take a look at tagcloud.js – the file that defines the Angular tagcloud module. At (1) we see the definition of the module tagcloud, which does not have dependencies on any additional modules. At (2) is the derivation of the unique id for each instance – every occurrence of the tag-cloud custom HTML tag. At (3) the directive specifies that an HTML element of tag-cloud (which is the automatic conversion of camel case tagCloud) is to be associated with this module. At (4), the private (data) scope for this module is defined, containing the elements tags and tagClicked. This is crucial in order to be able to have multiple instances of the tagcloud in a single page that are isolated from each other. Each instance has its own tags and its own tagClicked function.

At (5) we indicate the external HTML file that provides the ‘view’ content for our tagcloud module. The tagcloud.html file is shown below.

Directives that want to modify the DOM typically use the link option, shown at (6). One very important element set up in this link() function is the watch function that we associate with the tags collection (on the scope). Whenever the value of tags changes, this function will be executed. In most situations, the result will be that the Start function on the TagCanvas object is invoked – to redraw the tagcloud [with the latest set of tag values].

image

The HTML file that is imported at (5) is actually very simple:

image

A new canvas is rendered with an id value based on the canvasId value in the Angular scope – where we have taken care to make this value unique. The ng-repeat attribute is interpreted by Angular, creating a for each loop that stamps out the <li> element for every element in the tags collection (on the scope). For each tag, an <a> element is rendered with attributes data-weight and click derived from properties of the tag element in the tags collection and the tagClicked() function that was put on the scope at (7) in tagcloud-html.html.

A visualization of the application structure is shown next:

image

Resources

What’s so great about Angular by Ben Lesh – http://www.benlesh.com/2014/04/embular-part-2-whats-great-about-angular.html

Getting Started With Gulp by Travis Maynardhttp://travismaynard.com/writing/getting-started-with-gulp

Gulp as a Development Web Server by Johannes Schicklinghttp://code.tutsplus.com/tutorials/gulp-as-a-development-web-server–cms-20903

Getting Started with Bower – blog article with introduction tutorial to Bower for managing JavaScript dependencies

AngularJS – documentation on the Directive, watches