How to Integrate Contentful with Angular: A Quick Guide on Using It Within Your Angular App

How to Integrate Contentful with Angular: A Guide on Using It Within Your Angular App

Decided to tap into the unmatched flexibility that Contentful places in your developer hands? And to “inject” it into your Angular project? Just imagine: an API-first content platform that you get to use as a backend for your Angular app, but which doesn't grow “dependent” on its presentation layer. Meaning that you get to easily “create once, publish everywhere”, from the very same cloud content repository... Well then, here's how you integrate Contentful with Angular:

If back in the 90's static websites used to “rule” and next it was the traditional CMSs that stole the spotlight, now it's about time you stepped into the “future present” of the programmable content with Contentful!

The API-driven content management platform revolutionizing the way we:

  • manage content, since it enables us, developers, to handle it independently from the front-end 
  • distribute content: with Contentful CMS it gets easily published across your whole ecosystem of platforms, from the a single content source 

Now let's dive right in:
 

1. Contentful or The Power of the Platform-Agnostic Approach 

I promise not to bore you with an exhaustive definition of Contentful. So here's a short, yet comprehensive one:

Contentful is the API-driven content management platform that enables you to:

  1. structure and manage your content right in the cloud
  2. have it published across multiple platforms nice and easy 

By “nice and easy” meaning unlike with the traditional content management systems, where once you published your content on one specific platform, you could no longer publish it elsewhere. There were simply too many discouraging factors to adjust your content to:

  • multiple image formats
  • how to provide content via API
  • how to segment your content block to fit on all the other platforms, as well 

“But how does Contentful work, more precisely?” you might wonder.

Well, it simply breaks down your content into multiple programmable chunks (title, tags array, author, featured image). And since they'll all get stored in the very same source (or “space), you'll get to easily distribute them across your website, mobile apps, desktop apps, smart devices etc.

In short: Contentful steps away from the conventional HTML-based architecture of the traditional CMSs.

So, you get to integrate Contentful with Angular, but... not exclusively. It enables you to publish the very same content on all the other platforms in your “ecosystem”.
 

2. Contentful as a Backend for Your Angular App

Yet, even if the presentation layer could be any front-end technology of your choice — since Contentful is platform-agnostic — it's using Contentful within an Angular app that we'll be focusing on in this post.

Therefore, I'll be walking you through all the steps required for:

  • creating a “space” for your Angular project on Contentful
  • defining your content types and then entering the real content and setting up your Angular app
  • making it (your app) “communicate” with the content stored in your Contentful backend

Ready to dig in?
 

3. Create a New Space, Define Your Content Types and Enter Your Content 
 

3.1. Create a New Space for Your Angular Project in the Contentful Backend

Once you've registered into a free Contentful account, it's time to “make some space” in there for your Angular project.

Take it as a place in the backend where you'll keep all the content relevant for a certain project safely stored and organized. 

Note: you might want to go for separate spaces on Contentful for, let's say, your e-commerce products and your blog posts.

And here's how you do it, how you create your space there:

  • “unfold” the left side menu
  • click on the “Add space” link there
  • then it's the window in the screenshot here below that will pop up

Integrate Contentful with Angular: Create a New Space in the Backend

  • just enter a name for your project's new space
  • hit the “Create space” button to generate a new space on Contentful 
     

3.2. Define Your Content Types (Tweet, Blog Post, Author Profile, Advertisement etc.)

Now that you've “made room for your project” in your Contentful backend, it's time to define a content type for the newly created space.

Take it as some sort of “backbone structure” for the content that you're planning to use in your Angular app (whether it's a blog post or maybe a tweet etc.).

Add all the needed fields to it (body, title, image, author, tag list, you name it), the validation rules and the appearance settings.

Then, time to jump to the next step as you integrate Contentful with Angular:
 

3.3. Fill in Your Content Type Fields with “Real” Content 

Switch to “Content View” and enter unique content in each one of your content blueprint's fields.

Note: each field type calls for a specific form input; for instance, the long text gets written in markdown format, that you'll need to, later on, convert to HTML (once you start putting together your Angular app)
 

4. Build Your Angular App

Ready to set up your app now so that you can make use of the content that you've just entered?

Go ahead and install its dependencies (in this example here it's “marked” and “Contentful JavaScript SDK” that we'll be installing):

ng new lessonApp
npm install contentful
npm install marked


4.1. API Keys 

Next, add the space ID and API token, thus ensuring that it's the Content Delivery API token that your Angular app will be using:

export const environment = {
  production: false,
  contentful: {
    spaceId: 'YOUR_SPACE',
    token: 'YOUR_TOKEN'
  }
};


5. Integrate Contentful with Angular: Create the Data-Retrieving Service

Now that you've set up your Angular app and you've also “populated” your Contentful space with content, it's time you... helped them communicate.

For this, you'll need to add a service containing specifically the needed logic for retrieving content from your new Contentful space.
 

5.1. Contentful.service.ts

The contentful service will call for the Contentful NPM client and generate the methods needed for requesting data from the API.

ng g service contentful --module app

This will add the contentful.service.ts including a default implementation of an Angular service class.

import { Injectable } from '@angular/core';
import * as contentful from 'contentful';
import { environment } from '../environments/environment';
import { Observable } from 'rxjs/Observable';
import * as marked from 'marked';
@Injectable()
export class ContentfulService {
  private client = contentful.createClient({
    space: environment.contentful.spaceId,
    accessToken: environment.contentful.token
  })
  constructor() { }
  // console logs a response for debugging
  logContent(contentId) {
     this.client.getEntry(contentId)
      .then(entry => console.log(entry) )
  }
  // retrieves content mapped to its data fields
  getContent(contentId) {
    const promise = this.client.getEntry(contentId)
    return Observable.fromPromise(promise).map(entry => entry.fields)
  }
  // convert markdown string to 
  markdownToHtml(md: string) {
    return marked(md)
  }
}


5.2. App.components 

The app component will add on the service, then request the backend Contentful content as an Observable:

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { ContentfulService } from './contentful.service';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.sass']
})
export class AppComponent implements OnInit {
  lesson$: Observable<any>;
  constructor(private contentful: ContentfulService) { }
  ngOnInit() {
    // this.contentful.logContent('some_id') // to console log the content for debugging
    this.lesson$ = this.contentful.getContent('some_id')
  }
}


Note: you could unwrap the Observable with the async pipe and display its fields as such in the HTML:

<div *ngIf="lesson$ | async as lesson">
  <h1>{{ lesson.title }}</h1>
  <time>Published on {{ lesson.createdAt | date: 'fullDate'  }}</time>
  <hr>
  <h3>Tags</h3>
  <span *ngFor="let tag of lesson.tags">
    {{ tag }}
  </span>
  
  <!-- markdown string -->
  {{ lesson.body }}
  
</div>


6. Convert the Markdown Format to HTML 

When you integrate Contentful with Angular expect the former to return your body text in markdown format.

And Angular doesn't read markdown!

What do you do then? You create a pipe and convert the Markdown string to HTML!

npm install marked --save
ng g pipe mdToHtml


6.1. MD-to-html.pipe.ts

What this pipe here does is it calls the markdownToHtml method from the service:

import { Pipe, PipeTransform } from '@angular/core';
import { ContentfulService } from './contentful.service';
@Pipe({
  name: 'mdToHtml'
})
export class MdToHtmlPipe implements PipeTransform {
  constructor(private contentful: ContentfulService ) {}
  transform(value: string): any {
    return this.contentful.markdownToHtml(value);
  }
}

Next, go ahead and update the app component so that it uses the HTML output:

<div [innerHTML]="lesson.body | mdToHtml">

The END! This is how you integrate Contentful with Angular and "exploit" all the benefits that come along with a cross-platform backend!