angular-contentful

AngularJS module to access the Contentful content delivery API

Added by: Sam Deering

GitHub

Repository

jvandemo/angular-contentful

Stats

Stars: 3

Watchers: 3

Forks: 0

Module Description

AngularJS Contentful

AngularJS module to easily access the Contentful content delivery API:

Build Status

  • lightweight (< 3KB minified)
  • no external dependencies
  • automatically resolves linked content in the response for maximum convenience
  • uses the native AngularJS $http service to connect to the API
  • returns native AngularJS $q promises

Demo

There are working demo's available in the examples directory.

Usage

First install the module using bower:

$ bower install angular-contentful

and add the library to your application:

<script type="text/javascript" charset="utf-8" src="bower_components/angular-contentful/dist/angular-contentful.min.js"></script>

Then add the contentful module to the dependencies of your AngularJS application module:

angular.module('yourApp', ['contentful']);

and configure the contentful service in a config block using the provider:

angular
  .module('yourApp')
  .config(function(contentfulProvider){
    contentfulProvider.setOptions({
        space: 'yourSpace',
        accessToken: 'yourAccessToken'
    });
  });

Now you can use one of the directives to fetch Contentful data right from within your markup:

<pre contentful-entry="6KntaYXaHSyIw8M6eo26OK">
  {{ $contentfulEntry | json }}
</pre>

or you can use the contentful service anywhere in your application code:

angular
  .module('yourApp')
  .controller('SomeCtrl', function(contentful){
    
    // Get all entries
    contentful
      .entries()
      .then(
      
        // Success handler
        function(response){
          var entries = response.data;
          console.log(entries);
        },
        
        // Error handler
        function(response){
          console.log('Oops, error ' + response.status);
        }
      );
    
  });

The contentful-entry directive

Fetches a Contentful entry asynchronously in the background and makes it available in your child markup as $contentfulEntry as soon as a response from Contentful is received.

Requires a Contentful entry id to be passed.

For example, to display an entire entry with id 6KntaYXaHSyIw8M6eo26OK:

<pre contentful-entry="6KntaYXaHSyIw8M6eo26OK">
  {{ $contentfulEntry | json }}
</pre>

Or to display only one field of the entry:

<h1 contentful-entry="6KntaYXaHSyIw8M6eo26OK">
  Hi {{ $contentfulEntry.fields.name }}!
</h1>

$contentfulEntry is available in the child elements as well:

<article contentful-entry="6KntaYXaHSyIw8M6eo26OK">
  <section>
    {{ $contentfulEntry.fields.sectionOne }}
  </section>
  <section>
    {{ $contentfulEntry.fields.sectionTwo }}
  </section>
<article>

The contentful-entries directive

Fetches multiple Contentful entries asynchronously in the background and makes them available in your child markup as $contentfulEntries as soon as a response from Contentful is received.

Takes an optional query string value to pass to the Contentful content delivery API.

For example, to fetch all entries in your space:

<ul contentful-entries>
  <li ng-repeat="entry in $contentfulEntries.items">
    {{ entry.fields.name }}
  </li>
</ul>

Or specify a query string to filter the entries:

<ul contentful-entries="content_type=dog">
  <li ng-repeat="dog in $contentfulEntries.items">
    {{ dog.fields.name }}
  </li>
</ul>

The optional query string is passed to the Contentful API, so you can use all supported filters.

Links are automatically resolved too, so you can easily access linked content as embedded data like this:

<ul contentful-entries="content_type=dog">
  <li ng-repeat="dog in $contentfulEntries.items | orderBy:'dog.fields.name' ">
    <h1>{{ dog.fields.name }}</h2>
    <img ng-src="{{ dog.fields.image.fields.file.url }}" />
  </li>
</ul>

The contentful service

The contentful service can be injected anywhere in your application and exposes the following API:

contentful.asset(id)

Get an asset.

Arguments
  • id - {string} - Asset id, required
Returns

Promise.

contentful.assets(queryString)

Get assets.

Arguments
  • queryString - {string} - Query string to pass to API, optional
Returns

Promise.

contentful.contentType(id)

Get a content type.

Arguments
  • id - {string} - Content type id, required
Returns

Promise.

contentful.contentTypes(queryString)

Get content types.

Arguments
  • queryString - {string} - Query string to pass to API, optional
Returns

Promise.

contentful.entry(id)

Get an entry.

Arguments
  • id - {string} - Entry id, required
Returns

Promise.

contentful.entries(queryString)

Get entries.

Arguments
  • queryString - {string} - Query string to pass to API, optional
Returns

Promise.

contentful.space()

Get space.

Arguments

None.

Returns

Promise.

Promises

All methods return a promise.

Depending on the reponse of the API, either the success handler or the error handler is called with a destructured representation of the response with the following properties:

  • data – {object} – The response body transformed with the transform functions.
  • status – {number} – HTTP status code of the response.
  • headers – {function([headerName])} – Header getter function.
  • config – {object} – The configuration object that was used to generate the request.
  • statusText – {string} – HTTP status text of the response.

The data property contains the Contentful data. The other properties are passed for convenience in case you need them.

contentful
  .entries()
  .then(
  
    // Success handler
    function(response){
      var entries = response.data;
      console.log(entries);
    },
    
    // Error handler
    function(response){
      console.log('Oops, error ' + response.status);
    }
  );

Automatically resolved linked content

Angular-contentful automatically resolves linked content for you.

If the Contentful API response includes linked content such as linked entries or linked assets, they are automatically attached to their parent content for maximum convenience.

Suppose you have a collection of dogs that have an image linked to them, you can now access the image as a direct property instead of having to resolve the image manually:

<ul contentful-entries="content_type=dog">
  <li ng-repeat="dog in $contentfulEntries.items | orderBy:'dog.fields.name' ">
    <h1>{{ dog.fields.name }}</h2>
    <img ng-src="{{ dog.fields.image.fields.file.url }}" />
  </li>
</ul>

Notice

Resolving links hierarchically can cause circular links.

Although this isn't harmful, it may hamper you from outputting the entire response e.g. using {{ $contentfulEntries | json }}.

Example raw Contentful responses

These raw response examples give you an idea of what original Contentful responses look like.

If you are interested in the details, please visit the Contentful delivery API documentation.

Example Contentful response for successful request

{
  "data": {
    "sys": {
      "type": "Space",
      "id": "cfexampleapi"
    },
    "name": "Contentful Example API",
    "locales": [
      {
        "code": "en-US",
        "default": true,
        "name": "English"
      },
      {
        "code": "tlh",
        "default": false,
        "name": "Klingon"
      }
    ]
  },
  "status": 200,
  "config": {
    "method": "GET",
    "transformRequest": [
      null
    ],
    "transformResponse": [
      null
    ],
    "headers": {
      "Accept": "application/json, text/plain, */*"
    },
    "params": {
      "access_token": "b4c0n73n7fu1"
    },
    "url": "https://cdn.contentful.com:443/spaces/cfexampleapi"
  },
  "statusText": "OK"
}

Example response for error

{
  "data": {
    "sys": {
      "type": "Error",
      "id": "NotFound"
    },
    "message": "The resource could not be found.",
    "details": {
      "sys": {
        "type": "Space"
      }
    },
    "requestId": "71a-1131131513"
  },
  "status": 404,
  "config": {
    "method": "GET",
    "transformRequest": [
      null
    ],
    "transformResponse": [
      null
    ],
    "headers": {
      "Accept": "application/json, text/plain, */*"
    },
    "params": {
      "access_token": "b4c0n73n7fu1"
    },
    "url": "https://cdn.contentful.com:443/spaces/cfexampleapiii"
  },
  "statusText": "Not Found"
}

Why not use the official contentful.js?

The official Contentful to way is to include 2 libraries in your application:

<script type="text/javascript" charset="utf-8" src="bower_components/contentful/dist/contentful.min.js"></script>
<script type="text/javascript" charset="utf-8" src="bower_components/ng-contentful/ng-contentful.js"></script>

The problem

contentful.js is the main Contentful JavaScript library that relies on different external libraries such as:

  • questor to perform HTTP requests
  • bluebird for promises

and then bundles everything together in contentful.js using Browserify, resulting in a file that packs over 100KB minified.

ng-contenful.js then forms a wrapper around contentful.js that takes care of converting the bluebird promises back to AngularJS promises.

This makes sense if you are in a non-AngularJS environment such as node.js, but AngularJS already has built-in services to perform HTTP requests and provide promises.

The solution

This AngularJS module uses native AngularJS services to provide a similar API using:

  • $http to perform HTTP requests
  • $q for promises

which results in:

  • NOT having to include contentful.js and ng-contentful.js, saving you an expensive 100KB+ client side download when your application loads
  • less CPU cycles in the client by not having to convert promises

Contribute

To update the build in the dist directory:

$ gulp

To run the unit tests using the src files:

$ gulp test-src

To run the unit tests using the unminified library:

$ gulp test-dist-concatenated

To run the unit tests using the minified library:

$ gulp test-dist-minified

Change log

v1.0.0

  • Simplified service API so it always resolves links by default
  • Simplified contentful-entries directive API to make data available more intuitively using $contentfulEntries instead of $contentfulEntries.entries
  • Simplified contentful-entry directive API to make data available more intuitively using $contentfulEntry instead of $contentfulEntry.entry
  • Removed support for success and error shorthand methods in favor of more consistent API with then.
  • Updated documentation

v0.5.1

  • Update contentful-entries directive so it return response identical to contentful service method

v0.5.0

  • Added support to automatically resolve links when multiple entries are returned
  • Updated documentation

v0.4.0

  • Added contentfulEntries directive
  • Added additional unit tests
  • Updated documentation

v0.3.0

  • Added contentfulEntry directive
  • Added additional unit tests
  • Updated documentation

v0.2.0

  • Added demo application
  • Added shorthand support for success and error handlers
  • Added documentation

v0.1.0

  • Added contentful service
  • Added unit tests
  • Added initial documentation

Module stats last updated: 2015-04-22 02:21:24

Disclaimer: Some data on this page may have been gathered from the authors GitHub respository. If you see any mistakes or outdated information please let us know. Thanks!