Monday, December 19, 2016


Introduction

Content Management systems manage and deliver electronic content to a target audience.The content may be web information, marketing campaigns or social media content. Applications often call third-party http-based RESTful APIs, including social networks, cloud providers, e-commerce and news aggregators.Within larger enterprise environments, applications call multiple internal applications.

There are two ways to call third-party http-based APIs from an AEM application.The first approach is calling directly from client-side and the second approach, using AEM servlet data calls.Here, we are going to discuss the first approach which is calling directly from the client-side.AngularJS calls the third-party API, directly and all logic is on the client-side, instead of on the server-side.

Example

To make this post more interesting, I will be using the OMDb API - a free web service to obtain movie information for our movie search component. This component will be built using Bootstrap for styling and AngularJS, which will retrieve any movie information which we will enter in a search text box.

Develop Movie Search Component

After creating the basic folder structure for our app, we need to create template under /apps/angular/templates/. Then create our movie search component under /apps/angular/components/page.

So as of now, we had created the basic project structure, now we will include AngularJS in our application.

Create a folder with primaryType="cq:ClientLibraryFolder" under /apps/angular/compoents/moviesearchcomponent/ with name clientlibs and include AngularJS. As we already have Angularjs defined in libs, so we just need to add these properties to include Angularjs framework in our application.Along with this we also have to include Bootstrap css and js files to style our component.





Creating the Controller

Now, we will look at app.js which is very important for angularjs application in which we will create a controller can use it to make calls to the OMDB API.Here's a controller named MovieInfoController that will be used for data retrieval and manipulation. Once data is returned from the API the $scope is updated which will drive the user interface.
'use strict';

angular.module('myApp', [])
    .controller('MovieInfoController', function($scope, $http) {
        $scope.$watch('search', function() {
            fetch();
        });
  $scope.search = "Game of Thrones";
  function fetch() {
            $http.get("http://www.omdbapi.com/?t=" + $scope.search + "&plot=full")
                .then(function(response) {
                    $scope.records= response.data;
                });
        }
        $scope.select = function() {
            this.setSelectionRange(0, this.value.length);
        }
});
Explanation 


Here we can see how to inject dependencies like that variable $scope & $http which are passed as a parameter to the function of the controller, $scope is used for sharing values between the view and the controller.This means we are declaring dependencies on both the scope object and the http service.

The search model(search text box value) is undefined when on page loads, so we set it to some content value(Ex: "Game of thrones") and call fetch function, which will call the remote API and ensure that the view is initialized.

Now we will see the MovieInfoController, we set up monitoring of the search model and load the results when the value in the search box changes.As we used the ngModelOptions directive with a debounce value of 500, the result should only be fetched after the user has stopped typing for 500 ms.

Now comes the fetch function.We use Angular's $http.get a function to make the requests, passing query string along with API URL.

We used records model to store the responses on success. Finally, When the user clicks in the text input search button, we have a select function to ensures that the entire text is selected.

Creating the View

Lets now we look our moviesearch component view(moviesearch.html). First thing we need to include required client libs in our page by using Sightly include. Then inside body, we declare our module name as myapp by using angularjs directive ng-app and controller as ng-controller = "MovieInfoController". By using ng-model to bind the input field where user will enter the movie name to the search model(which we declared in our controller).

The main-info div will be used to display information about the searched movie. Here, we start with ng-if directive to show the message "Loading Results....". When the results were returned and assigned that response to records. So records has all required data to display in page.

Here, a complete code of movie search html.
<html>

<head>
    <title>Movie Search !!!</title>
    <sly data-sly-call="${clientLib.all @ categories='cq.widgets'}" data-sly-unwrap="" data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html"></sly>
</head>

<body>
    <div class="container-fluid outerdiv bg-info" ng-app="myApp" ng-controller="MovieInfoController">
     <div class="input-group search-bar">
        <input autofocus="" class="form-control" ng-model-options="{ debounce: 500 }" ng-model="search" onclick="select()" placeholder="Enter movie name" type="text" />
        <span class="input-group-addon bar-style"><i class="glyphicon glyphicon-search"></i></span>
     </div>
<div class="col-md-12" id="main-info">
        <div ng-if="!records">
          Loading results...
        </div>
<div ng-if="records.Response==='True'">
          <img class="img-thumbnail animated flip movie-poster" ng-src="{{ records.Poster=='N/A' ?  'http://placehold.it/150x220&text=N/A' : records.Poster }}" />
          <span class="span-outer">
             <a href="https://www.blogger.com/null">{{ records.Title }}</a>
          </span>
         <strong>Released on:</strong> {{ records.Released }} ({{ records.Runtime }}) &lt/br>
         {{ details.Plot }}
         <div class="outer-p">
             <div class="inner-p">
               <span class="label label-primary">Directors :</span> {{ records.Director }}
             </div>
<div class="inner-p">
               <span class="label label-primary">Actors :</span> {{ records.Actors }}
             </div>
<div class="inner-p">
               <span class="label label-primary">Genre :</span> {{ records.Genre }}
            </div>
</div>
<div class="outer-p-2">
              Ratings:
              <br>
              <strong<IMDb Rating</strong>: <span class="label label-success">{{ records.imdbRating }}</span>
          </div>
</div>
<div ng-if="records.Response==='False'">
          No results found.
        </div>
</div>
</div>
</body>

</html>

Create the web page and drag and drop this component to view the result.