
Have you ever wondered how to create an app in Angular using a headless CMS product? After doing a lot of research on multiple CMS products like:
-Contentful
-CloudCMS
-ButterCMS
-MURA CMS
I decided to go with Contentful.
Contentful is content infrastructure. Its platform lets you create, manage, and distribute content to any platform. Unlike a CMS, it gives you total freedom to create your own content model so you can decide what content you want to manage. Contentful provides you RESTful APIs so you can deliver your content across multiple channels such as websites, mobile apps (iOS, Android, and Windows Phone) or any other platform you can imagine (from Google Glass to infinity). With an uncluttered user interface, Contentful is an efficient tool for creating and managing your content online, either alone or in a team. You can assign custom roles and permissions to team members; add validations depending on the kind of content you have to insert; and add media such as images, documents, sounds, or video.
I decided to use Contentful for an Enterprise project for one of the biggest companies in the USA.
A few things I like about Contentful:
-It allows multiple users
-It's easy for the non-technical minded
-It streamlines scheduling
-It improves site maintenance
-Design changes are simple
-It helps you manage content
-You're in control
-Try for free
-Works with multiple frontend technologies like Angular, React, Vue, etc
-They have a slack channel
-Good community support
-GraphQL friendly
Did I mention Contentful is built on top of AWS? :)
This tutorial requires some level of knowledge with Angular.
Working with Contentful
1) Create an account withContentful.
3) Enter the new space name E.g angular-cms.
4) Make sure the optionCreate an empty space is selected.
5) Click onPROCEED TO CONFIRMATION.
6) Click onCONFIRM AND CREATE SPACE.
7) After your space has been created, at the very top click on CONTENT MODEL.
8) Then click on the blue buttonAdd Content Type.
9) A modal will appear. Enter your content type name as Angular Post. Write down the content type ID (should be angularPost).
10) ClickCREATE.
11)Time to add some fields. On your right side, click on the blue buttonAdd Field.
12) Create a new field calledtitle of type TEXT.
13) Create a new field calledbody of type TEXT.
Note: Right below where you enter the name of the field, make sure you selectLong text, full-text search.
14) Create a new field calledimage of type MEDIA.
Note: Below where you enter the name of the field, make sure you selectOne file.
15) On the top right corner, click the green buttonSAVE.
16) In the top navigation bar, click onCONTENT.
17) Click the "Add Angular Post".
18) Enter the Title and Body for your new post. Create at least 2 posts.
19) Now click onCreate a new asset and link.
20) A modal will open; enter the name of your asset, description (optional), and select your image file.
21) On the right sidebar, click onPUBLISH.
22) Click the "<" arrow at the top left of the modal to go back to the creation of your post.
23) On the right sidebar, click onPUBLISH.
24) In the top navigation bar, click onSETTINGS/API Keys.
25) On the right sidebar, click onAdd API Key.
26) Copy your Space ID and your Content Delivery API Access Token, save them somewhere.
27) On the top right corner, click SAVE.
Connecting Angular with Contentful
Note: I'm not going to get into best practices with angular, I'm only showing you how to use Contentful with Angular.
1) Create a new Angular app. Select SASS as your CSS compiler, and the option to create the routes file.
ngnewangular-cms
2) Create a new service.
nggscontentful
3) Install the Contentful NPM package.
npmi--savecontentful
4) At the top of you contentful.service.ts file, add the following line:
import{createClient}from'contentful';
5) Time to use your Space Id and accessToken.
privateCONFIG={space:'ENTER YOUR SPACE ID HERE',accessToken:'ENTER YOUR ACCESS TOKEN HERE',contentTypeIds:{//The property name angularPost can be whatever//what matters in the value which is the content type Id.angularPost:'angularPost'}};
Note If you didn't save your content type ID somewhere, you can get it as followed: contentful -> content model -> click your content model name -> right sidebar look for your content type ID.
6) Create a new private variable.
privatecdaClient=createClient({space:this.CONFIG.space,accessToken:this.CONFIG.accessToken});
7) At the top of your file, importfrom from RxJs.
import{from}from'rxjs';
8) Now let's create a function to retrieve all of our posts.
getPosts(query?:object):any{returnfrom(this.cdaClient.getEntries({...Object,content_type:this.CONFIG.contentTypeIds.angularPost,query})).pipe(map(posts=>posts.items));}
9) Time to create a function to retrieve a single post.
getPost(id:string):any{returnfrom(this.cdaClient.getEntry(id));}
10) Inside of your constructor, let's initialize the our getPosts() method.
constructor(){this.getPosts();}
11) The contenful.service.ts file should look like this:
https://github.com/devpato/angular-contentful-cms/blob/master/src/app/contentful.service.ts
12) Let's create to new 2 components.
nggcposts-page
nggcpost-details
13) Now go to your posts-page component, and enter the following lines of code:
import{ContentfulService}from'../contentful.service';...posts$=this.contentfulService.getPosts();constructor(privatecontentfulService:ContentfulService){}
14) Your code should look like this:
https://github.com/devpato/angular-contentful-cms/blob/master/src/app/posts-page/posts-page.component.ts
15) Clear your post-page.component.html and paste:
<divclass="content"><divclass="posts"><ng-container*ngIf="posts$ | async as posts"><div*ngFor="let p of posts"class="post"><divclass="post-image"><imgsrc="{{ p.fields.image.fields.file.url }}"/></div><a[routerLink]="['/posts/', p.sys.id]"><divclass="post-title"> {{ p.fields.title }}</div></a></div></ng-container></div></div>
16) Copy the code from the link listed below, and paste it to your posts-page.components.scss
17) Time to go to our post-details.component.ts and add the following:
import{ContentfulService}from'../contentful.service';import{ActivatedRoute}from'@angular/router';...id=this.route.snapshot.paramMap.get('id');post$=this.contentfulService.getPost(this.id);constructor(privatecontentfulService:ContentfulService,privateroute:ActivatedRoute){}
18) Your code should look like this:
https://github.com/devpato/angular-contentful-cms/blob/master/src/app/post-details/post-details.component.ts
19) Clear your post-details.component.html and paste:
<divclass="post-details"*ngIf="post$ | async as post"><divclass="post"><divclass="post-header"><divclass="header--image"><imgsrc=" {{ post.fields.image.fields.file.url }}"/></div><divclass="header--title"> {{ post.fields.title }}</div></div><divclass="post-body"> {{ post.fields.body }}</div></div></div>
20) Copy the code from the link listed below, and paste it to your post-details.components.scss
https://github.com/devpato/angular-contentful-cms/blob/master/src/app/post-details/post-details.component.scss
21) Now let's work with the routes. Add the following routes to your app-routing.module.ts
constroutes:Routes=[{path:'',component:PostsPageComponent},{path:'posts/:id',component:PostsDetailsComponent}];
22) Now run your server. You should see something like this:
Note: the information on the posts may be different. It depends on whatever you entered when creating a new Angular post.
23) Click on one of the items, it should take you to its details page.
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse