Notes on Building a Drupal 8 Module, With a Little AngularJS

Note: This post was written 3/20/2016 and refers to a block on this site that displayed links to posts on my Drupal 7 site (webmech.biz). Since that Drupal 7 site has now been taken down, the block of Drupal 7 posts discussed below is no longer available. However, the discussion of how I used processed the data from webmech.biz and used AngularJS to display it may still be of interest.

For the moment, I just want to explore some of the features that I found particularly interesting in the module I wrote to show posts from my old Drupal 7 site in a block in the left sidebar.

First, to access the JSON data that comes through the web service I set up on my Drupal 7 installation at http://webmech.biz, I used the Guzzle HTTP client library, which was added to the initial Drupal 8 release.  The Guzzle API is object-oriented and easy to use:

$client = \Drupal::service('http_client');
$result = $client->get($uri, ['Accept' => 'application/json']);
$result_json = $result->getBody();

To handle the JSON data that is returned from this request, Symfony provides a useful class called Serializer.  However, in Symfony 2.7--the version currently used in Drupal 8--Serializer::deserialize can only take an object as an argument, not an array of objects, which is what http://webmech.biz has returned to us.  In Symfony 2.8 and in Symfony 3 (which will be incorporated into Drupal 8 at some point in the future), Serializer::deserialize is able to deserialize arrays of objects.  But for our purposes here, it's easier just to use the good old PHP function json_decode() to access the JSON data.

The other interesting thing about this module is that it uses AngularJS to show and hide the blog post teasers when the titles are clicked.  No, that's not JQuery; it's Angular.  This is a pretty basic use of Angular and not at all necessary in this situation, but since it's my blog and I'm interested in getting more familiar with Angular, I figured, why not? 

Many people think that AngularJS is meant only to be used to manage the entire front end of a website, and not just to be placed in small divs within an external template.  Sure, that's how Angular is usually used, but it is designed to be used either as a framework for the entire front end or to manage front end activity in localized areas within the front end, which is what I have done here.  All that I had to do was wrap the blog post content in divs with the ng-app and ng-controller attributes in order to use the ng-click and ng-show functions, like this:

<div class="ng-scope" ng-app="webmechanicblockapp">
  <div class="ng-scope" ng-controller="WebMechanicBlockImport">
    <h3 ng-click="showBlogPost11 = !showBlogPost11">
      <a class="webmechanic-feed-block-title" href="">The Web Mechanic Has Moved to Drupal 8!</a>
    </h3>
    <div ng-show="showBlogPost11" class="webmechanic-feed-block-paragraph ng-hide">
      <p>Now that Drupal 8 has been released, <a href="http://webmechanic.org" target="_blank">webmechanic.org</a> has moved to a Drupal 8 platform.  Blog posts will not be migrated to the new site (since some involve custom modules that demonstrate issues specific to Drupal 7), but this Drupal 7 installation and all of its current blog posts will continue to be available at <a href="http://webmech.biz">webmech.biz</a>.</p>
    </div>
    <!-- more blog posts -->
  </div>
</div>

In the code above, webmechanicblockapp (the AngularJS app) and webmechanicblockapp (the AngularJS controller) are defined in an external JavaScript file. In this case, the app and controller do not contain any significant code; all they do here is define the scope of activity for AngularJS on the page.