Headless Drupal Doubleheader at SF DUG

We encourage users to post events happening in the community to the community events group on https://www.drupal.org.
eatings's picture
Start: 
2014-08-18 18:00 - 20:00 America/Los_Angeles
Organizers: 
Event type: 
User group meeting

Josh Koenig and I are talking Headless Drupal tonight at SFDUG, at the Pantheon office (717 California, San Francisco). I'll be talking about the sitebuilding and usage implications of Headless approaches, and Josh will be demoing his work-in-progress D8+Angular experiments. We'll do our best to record this.

Admission is free, food and drinks will be provided.

Comments

Was it Recorded?

Bevan's picture

Was it Recorded?

Sadly no

joshk's picture

However, David's presentation should be generally available (and recorded at DrupalCon AMS) and I will post my code shortly. ;)

Better than slides or video - working code

joshk's picture

For anyone who is curious about this, I did a short write-up and have posted WORKING CODE for my AngularJS demo:

https://www.getpantheon.com/blog/headless-drupal-demo-working-code-and-c...

Please feel free to fork, hack, slash, and experiment away. I would love it if more people started posting examples like this.

link doesn't work. :(

mirzu's picture

link doesn't work. :(

links get truncated in

RobKoberg's picture

links get truncated in emails. You have to go to the post. These drupal groups as a communication platform kind of suck...

Shortlink

NodeLoader should be a

RobKoberg's picture

NodeLoader should be a factory (and called a service) that can be injected into other controllers.

Here is a 'wildcard' drupal page loader along with a PageData service to use as an example. Notice a few things:

  • the array for injecting services and the function. You will need this when the JS gets minimized.
  • keep controllers thin and services fat
  • the resolve property in the routes returns a promise and loads the page data before instantiating the controller

Any more explicitly defined routes (define routes in each separate module) will override the WildcardCtrl routes. For example, see the ProfileCtrl example below.

'use strict';

angular.module('app.wildcard', [

  'app.pageData'

])
  .config(['$routeProvider', function ($routeProvider) {


    var defaultTemplateUrl = 'components/wildcard/wildcard.html',
      defaultController = 'WildcardCtrl',
      defaultResolver = {
        pageData: ['PageData', function(PageData) {
          return PageData.load();
        }]
      };


    $routeProvider
      .when('/', {
        templateUrl: defaultTemplateUrl,
        controller: defaultController,
        resolve: defaultResolver
      })
      .when('/:arg0', {
        templateUrl: defaultTemplateUrl,
        controller: defaultController,
        resolve: defaultResolver
      })
      .when('/:arg0/:arg1', {
        templateUrl: defaultTemplateUrl,
        controller: defaultController,
        resolve: defaultResolver
      })
      .when('/:arg0/:arg1/:arg2', {
        templateUrl: defaultTemplateUrl,
        controller: defaultController,
        resolve: defaultResolver
      })
      .when('/:arg0/:arg1/:arg2/:arg3', {
        templateUrl: defaultTemplateUrl,
        controller: defaultController,
        resolve: defaultResolver
      })
      .when('/:arg0/:arg1/:arg2/:arg3/:arg4', {
        templateUrl: defaultTemplateUrl,
        controller: defaultController,
        resolve: defaultResolver
      })
      .otherwise({
        redirectTo: '/'
      });
  }
  ])
  .controller('WildcardCtrl', [
    '$scope', '$window', 'PageData',
    function ($scope, $window, PageData) {

      $scope.reload = function() {
        $window.location.reload(true);
      };

      $scope.data = PageData.get();

      console.log('WildcardCtrl $scope', $scope);
    }
  ])
;

'use strict';

angular.module('app.pageData', [
  'app.user',
  'app.notifications'
])
  .factory('PageData', [

    '$rootScope', '$window', '$location', '$sce', '$http', 'User', 'Notifications',

    function($rootScope, $window, $location, $sce, $http, User, Notifications) {

      var thisData = {};

      function setupData(data) {
        if (data.user) {

          User.set(data.user);
          delete data.user;
        }

        if (data.messages) {
          Notifications.set(data.messages);
          delete data.messages;
        }

        if (data.content) {
          data.content = $sce.trustAsHtml(data.content);
        }

        $window.document.title = data.pageTitle ? data.pageTitle + ' | RFMS' : 'Read for My School';

        return data;
      }


      return {
        get: function() {
          return thisData;
        },
        set: function(data) {
          return setupData(data);
        },
        load: function(path) {

          $rootScope.loading = true;

          var getPath = path || $location.path();

          return $http.get(getPath, {
//              params: $location.search()
            })
            .success(function(data) {

              $rootScope.loading = false;
              thisData = setupData(data);

            })
            .error(function(data) {

              $rootScope.loading = false;
              console.log('PageData GET ERROR data', data);
              thisData = setupData(data);
              thisData.maintenance = $rootScope.maintenance;

            });
        }
      };


    }
  ])
;

'use strict';

angular.module('app.user.profile', [
  'app.posts',
  'app.menu'
])
  .config(['$routeProvider', function ($routeProvider) {


    $routeProvider.when('/users/:name', {
      templateUrl: 'components/user/profile/profile.html',
      controller: 'ProfileCtrl',
      resolve: {
        access: ['User', function(User) {
          User.access({
            requiresUser: true
          });
        }],
        pageData: ['PageData', function (PageData) {
          return PageData.load();
        }]
      }
    });
  }
  ])
  .controller('ProfileCtrl', [
    '$scope', 'User', 'Response', 'PageData', 'Books',

    function ($scope, User, Response, PageData, Books) {

      $scope.uid = User.uid();

      $scope.isTeacher = User.isTeacher();


      $scope.bookCategories = Books.categoriesDropdown();


      var response = Response.get();
      console.log('ProfileCtrl preloaded response', response);

      $scope.data = PageData.get();

    }
  ])
;

Pull request?

link doesn't work. :(

mrthangvt's picture

link doesn't work. :(