Create Scotch-Like Image Cards in Angular 2+ with Cloudinary

Chris Nwamba

When it comes to managing media files, we rely on Cloudinary for its ease and efficiency. The Cloudinary tool enables us to adeptly handle storage, transformation, and calculated delivery, so we can focus simply on uploading and fetching images with little configurations to suit our needs.

Because we have previously written about Cloudinary’s features, we won’t go into detail about them here. Instead, we’ll focus on how we can integrate Cloudinary in Angular 2x.

Cloudinary has just released a new SDK release for this integration, so we will explore what this SDK has to offer and show how to use the SDK to deliver animated image cards as seen on Scotch.io home page.


What we will build

Setup Environment

Angular CLI is the quickest way so far to create an Angular project. It takes only two steps: Install the CLI tool (if you haven’t) and create a new project with it. The installation should be done via npm, thus:

npm install -g angular-cli

Create a new project with the tool by running the following command:

# Create new project
ng new scotch-cards
# Enter project folder
cd scotch-cards
# Run app
ng-serve

With the Angular project created, now install the Cloudinary SDK via npm:

# install Cloudinary
npm install @cloudinary/angular cloudinary-core --save

The SDK is based on Cloudinary’s JS module, cloudinary-core, and entirely decoupled, so you have to install both. Decoupling the both libraries allows you to use the SDK features that do not require the JS module without having to bear the burden of size.

Due to the limitations in Angular CLI project (not exposing resolve aliases, not having an addon system ready yet) you need to install lodash since cloudinary-core depends on it.

Let’s import and provide the SDK to our app module so we can gain access to its APIs and components:

// ./src/app/app.module.ts
import { HttpModule } from '@angular/http';
import { CloudinaryModule } from '@cloudinary/angular';
import * as Cloudinary from 'cloudinary-core'

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    HttpModule,
    CloudinaryModule.forRoot(Cloudinary, { cloud_name: 'cloud_name'}),
  ],
  providers: [
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Importing the module gives you access to the SDK’s directives and components. The import is configured using the static forRoot method, passing in Cloudinary’s JS core and the config object.

The config object contains a cloud_name property, which is received upon creating a free Cloudinary account. The cloud_name is available on the dashboard.

Another important thing to include is the typings.d.ts to shut TypeScript from screaming that the module, cloudinary-core is not defined. You need to declare the cloudinary-core in this file:

// ./src/typings.ts
declare module 'cloudinary-core';

Cloudinary Components and Directives

To start delivering images from your Cloudinary cloud using this SDK, you need to become comfortable with the components and directives made available by the SDK. Let’s explore them:

Components

cl-image is used to deliver images to the browser. It requires public-id, which is a reference to the image hosted on the cloud. So if we have something like:

<cl-image secure="true" public-id="cat" class="cat_image" format="jpg">
cl-image>

We get:


<img class="cat_image"
  public_id="cat"
 src="https://res.cloudinary.com/sample/image/upload/cat.jpg">

By default, Cloudinary delivers media files using non-secure URLs. However, the secure attribute, when applied, instructs Cloudinary to deliver media files using a secure URL (HTTPS).

cl-video just like cl-image is used to deliver videos. Most important property is still the public-id of the video to be delivered:

<cl-video public-id="dog" class="dog_video" controls="true" preload="none">
cl-video>

Output:

<video secure="true" _ngcontent_ymq_2="" class="dog_video" controls="true" preload="none" public_id="dog" ng_reflect_public_id="dog" poster="https://res.cloudinary.com/sample/video/upload/dog.jpg">
  <source src="https://res.cloudinary.com/sample/video/upload/dog.webm" type="video/webm">
  <source src="https://res.cloudinary.com/sample/video/upload/dog.mp4" type="video/mp4">
  <source src="https://res.cloudinary.com/sample/video/upload/dog.ogv" type="video/ogg">
video>

Cloudinary will automatically convert your videos to HTML5 and mobile-friendly formats for optimized viewing on all web browsers and mobile devices.

cl-transformation is used to apply transformations to both images and videos. You can read more about Cloudinary transformation here.

Transformations can be applied multiple times to either of the delivery components:

<cl-image secure="true" public-id="angular_logo" class="logo" angle="20" format="jpg">

    
    <cl-transformation height="150" width="150" crop="fill" effect="sepia">cl-transformation>

        
    <cl-transformation overlay="text:arial_20:Angular" color="#EECCAA" gravity="south" y="20">cl-transformation>

cl-image>

Multiple transformation are chained, therefore, the transformation are applied in order of listing and you can apply as many as needed to ensure your media appears correctly. Chaining transformations enables you to edit a media files based on the previous transformation. For example, it makes more sense to apply a border radius to an image after it has been cropped. Therefore, the cropping transformation will come first and then the border radius transformation will be chained to it, and so on.

The above example will generate the following HTML:

<img class="logo" _ngcontent_ovt_3=""
  public_id="angular_logo" 
  ng_reflect_public_id="angular_logo" 
  src="https://res.cloudinary.com/demo/image/upload/c_fill,e_sepia,h_150,w_150/co_rgb:EECCAA,g_south,l_text:arial_20:Angular,y_20/a_20/angular_logo.jpg">

The transformation is applied to the URL and each chained transformation is separated with /.

Attribute Directives

clSrc: You might not want Cloudinary generating the image tag for you. Sometimes what you need is just the URL. The clSrc attribute directive does just that:

<img clSrc="cat" alt="Cat Image" />

clHref just like clSrc is used to generate the image URL for an anchor tag, not an image tag.

<a clHref="cat">
 . . .
a>

Another awesome feature of the clHref attribute directive is that you can apply transformation as attributes on the anchor tag for the linked image:

<a clHref="cat" width="150" gravity="auto" crop="thumb">
...
a>

It is worth noting that the transformation directive, cl-transformation, also can be added to anchor tags bearing the attribute directives:

<a clHref="cat" width="150" gravity="auto" crop="thumb">
     <cl-transformation height="150" width="150" crop="fill" effect="sepia">cl-transformation>
a>

Fetch Images from Cloudinary

In our example, we do not plan on displaying a single image. Instead, we want to fetch a list, iterate over the list and display each item in the list as a card.

We can fetch these images by making an HTTP request to Cloudinary once our component is initialized with the ngOnInit lifecycle method:

export class AppComponent implements OnInit{
  title = 'app works!';
  cards = [];

  constructor(
   // Inject HTTP service
    private http: Http
  ){}

  ngOnInit() {

// Fetch images tagged 'scotch' and set the images to 'cards'                                                                                                            

this.http.get('http://res.cloudinary.com/christekh/image/list/scotch.json')
      .map(data => data.json().resources)
      .subscribe(resources => { this.cards = resources });
  }
}

For security reasons, Cloudinary will not allow you to make requests like this from the client. The best method is to use the admin API via a backend SDK and then send the resource list to the client.

However, to enable access to list resources from client, you need to enable client resource listing. This is not recommended in production environment but is fine for demo purposes.

With the fetch logic out of the way, we now iterate over the cards property in the template to render them:

<div class="gallery">
  <a class="gallery__item" clHref={{card.public_id}} *ngFor="let card of cards">
    <div class="gallery__item-image">
      <cl-image public-id="{{card.public_id}}" class="img" format="jpg">

      cl-image>
    div>
    <div class="gallery__item-content">{{card.created_at}} div>
  a>
div>

Auto Cropping and Format Techniques

Currently, the image is fetched and displayed without any transformation. There is a cost to this, because what is fetched is the actual large image and the size is reduced with just CSS. While this fine for demo purposes, it is important to note that it will be a very expensive act for production apps.

With Cloudinary’s auto cropping features, you can transform the images before they are delivered to your browser. Cloudinary does the heavy lifting and you are served with image that maintain the same quality but with less weight.

<div class="gallery">
  <a class="gallery__item" clHref={{card.public_id}} *ngFor="let card of cards">
    <div class="gallery__item-image">
      <cl-image public-id="{{card.public_id}}" class="img" format="jpg">
        
         <cl-transformation  width="150" quality="auto" crop="fill">cl-transformation>
      cl-image>
    div>
    <div class="gallery__item-content">{{card.created_at}} div>
  a>
div>

Some image formats are overkill for various delivery situations. It would not make sense to display a simple banner with no need for transparency using the png format. Cloudinary is smart enough to deliver the right format for your needs, even when you upload an unnecessary format. Just as we set quality to auto, we can set fetch_format to auto as well for auto format technique:

<div class="gallery">
  <a class="gallery__item" clHref={{card.public_id}} *ngFor="let card of cards">
    <div class="gallery__item-image">
      <cl-image public-id="{{card.public_id}}" class="img" format="jpg">
        
         <cl-transformation  width="150" quality="auto" crop="fill" fetch_format="auto">cl-transformation>
      cl-image>
    div>
    <div class="gallery__item-content">{{card.created_at}} div>
  a>
div>

Demo

Conclusion

Now that you have seen how to craft Scotch-like image cards in Angular 2x with Cloudinary, there are a few important things to keep in mind. For example, you will want to use the Angular 2 SDK to deliver images, rather than talking to the Cloudinary client API directly. In addition, the cl-image and cl-video are used to deliver images and videos respectively, and the cl-transformation can be used to apply transformations to both types of files. And finally, the attribute directives, clSrc and clHref, are used to request the absolute URL of a media file based on the public ID provided.

To try this for yourself, sign up with Cloudinary for free and get started.

This content is sponsored via Syndicate Ads

Chris Nwamba

48 posts

JavaScript Preacher. Building the web with the JS community.