Cloudinary Blog

New Angular SDK for image management - More than meets the eye

Cloudinary Angular 2 Image and Video SDK

The night was moist. Angular2 had just been released and developers all over the world were asking for an integrated image management solution.

Cloudinary heeded the call and is proud to present the new Angular2 SDK, providing directives for displaying and transforming images and video with an API.

Wait, what's Cloudinary?

Cloudinary is an end-to-end image and video management solution for your website and mobile apps. Cloudinary covers everything from media uploads and storage to transformations, optimizations, and delivery.

You can easily upload images and video to the cloud and automatically perform smart transformations without installing any complex software. You can also integrate a Facebook or Twitter profile image in a snap, in any dimension and style to match your website’s graphics requirements. All your media files are seamlessly delivered through a fast CDN, optimized and using industry best practices.

For more information visit our Features Page.

Why do I need an SDK?

Cloudinary provides RESTful APIs that can be easily integrated with any Web development framework, but the new Angular SDK makes it easier to consume Cloudinary's service in your Angular2 app.

Let’s see how this is done by transforming Angular’s logo:

Ruby:
Copy to clipboard
cl_image_tag("angular_logo", :transformation=>[
  {:effect=>"pixelate:8", :gravity=>"north", :height=>0.5, :overlay=>"angular_logo", :width=>1.0, :crop=>"crop"},
  {:flags=>"layer_apply", :gravity=>"north"},
  {:width=>180, :crop=>"fit"}
  ])
PHP v1:
Copy to clipboard
cl_image_tag("angular_logo", array("transformation"=>array(
  array("effect"=>"pixelate:8", "gravity"=>"north", "height"=>"0.5", "overlay"=>"angular_logo", "width"=>"1.0", "crop"=>"crop"),
  array("flags"=>"layer_apply", "gravity"=>"north"),
  array("width"=>180, "crop"=>"fit")
  )))
PHP v2:
Copy to clipboard
(new ImageTag('angular_logo'))
  ->overlay(
      Overlay::source(Source::image('angular_logo')
        ->transformation((new ImageTransformation())
          ->resize(Resize::crop()->width(1.0)->height(0.5)->gravity(Gravity::compass(Compass::north())))
          ->effect(Effect::pixelate()->squareSize(8))))
      ->position((new Position())
        ->gravity(Gravity::compass(Compass::north()))))
    ->resize(Resize::fit()->width(180));
Python:
Copy to clipboard
CloudinaryImage("angular_logo").image(transformation=[
  {'effect': "pixelate:8", 'gravity': "north", 'height': "0.5", 'overlay': "angular_logo", 'width': "1.0", 'crop': "crop"},
  {'flags': "layer_apply", 'gravity': "north"},
  {'width': 180, 'crop': "fit"}
  ])
Node.js:
Copy to clipboard
cloudinary.image("angular_logo", {transformation: [
  {effect: "pixelate:8", gravity: "north", height: "0.5", overlay: "angular_logo", width: "1.0", crop: "crop"},
  {flags: "layer_apply", gravity: "north"},
  {width: 180, crop: "fit"}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .effect("pixelate:8").gravity("north").height(0.5).overlay(new Layer().publicId("angular_logo")).width(1.0).crop("crop").chain()
  .flags("layer_apply").gravity("north").chain()
  .width(180).crop("fit")).imageTag("angular_logo");
JS:
Copy to clipboard
cloudinary.imageTag('angular_logo', {transformation: [
  {effect: "pixelate:8", gravity: "north", height: "0.5", overlay: new cloudinary.Layer().publicId("angular_logo"), width: "1.0", crop: "crop"},
  {flags: "layer_apply", gravity: "north"},
  {width: 180, crop: "fit"}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("angular_logo", {transformation: [
  {effect: "pixelate:8", gravity: "north", height: "0.5", overlay: new cloudinary.Layer().publicId("angular_logo"), width: "1.0", crop: "crop"},
  {flags: "layer_apply", gravity: "north"},
  {width: 180, crop: "fit"}
  ]})
React:
Copy to clipboard
<Image publicId="angular_logo" >
  <Transformation effect="pixelate:8" gravity="north" height="0.5" overlay="angular_logo" width="1.0" crop="crop" />
  <Transformation flags="layer_apply" gravity="north" />
  <Transformation width="180" crop="fit" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="angular_logo" >
  <cld-transformation effect="pixelate:8" gravity="north" height="0.5" :overlay="angular_logo" width="1.0" crop="crop" />
  <cld-transformation flags="layer_apply" gravity="north" />
  <cld-transformation width="180" crop="fit" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="angular_logo" >
  <cl-transformation effect="pixelate:8" gravity="north" height="0.5" overlay="angular_logo" width="1.0" crop="crop">
  </cl-transformation>
  <cl-transformation flags="layer_apply" gravity="north">
  </cl-transformation>
  <cl-transformation width="180" crop="fit">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Effect("pixelate:8").Gravity("north").Height(0.5).Overlay(new Layer().PublicId("angular_logo")).Width(1.0).Crop("crop").Chain()
  .Flags("layer_apply").Gravity("north").Chain()
  .Width(180).Crop("fit")).BuildImageTag("angular_logo")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .effect("pixelate:8").gravity("north").height(0.5).overlay(new Layer().publicId("angular_logo")).width(1.0).crop("crop").chain()
  .flags("layer_apply").gravity("north").chain()
  .width(180).crop("fit")).generate("angular_logo");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setEffect("pixelate:8").setGravity("north").setHeight(0.5).setOverlay("angular_logo").setWidth(1.0).setCrop("crop").chain()
  .setFlags("layer_apply").setGravity("north").chain()
  .setWidth(180).setCrop("fit")).generate("angular_logo")!, cloudinary: cloudinary)
Angular logo transformation

(Angular logo is released under CC BY 4.0)

The above image was generated by overlaying the Angular logo onto itself, cropping the overlay and pixelating its top, then cropping the result to be 180px wide.

The same transformation can be achieved in your Angular2 app using the following directives:

Copy to clipboard
    <cl-image secure="true" public-id="angular_logo" width="180" crop="fit">
        <cl-transformation overlay="angular_logo" width="1.0" height="0.5" crop="crop" effect="pixelate:8" gravity="north"></cl-transformation>
        <cl-transformation flags="layer_apply" gravity="north"></cl-transformation>
    </cl-image>

Additional transformation examples can be found in the jQuery image manipulation guide and the complete image transformation reference

The same applies to videos:

The link to this video is

Copy to clipboard
https://res.cloudinary.com/cloudinary/video/upload/g_north,l_text:arial_30:Cloudinary%20features,y_8,co_red/w_1000/manipulation_video.mp4

This can be achieved using the Angular SDK with the following directives:

Copy to clipboard
<cl-video public-id="manipulation_video"
cloud-name="cloudinary" controls="true" 
preload="none" autoplay="true"
width="1000" secure="true"
class="manipulation-video">
   <cl-transformation overlay="text:arial_30:Cloudinary%20features" 
        color="red" gravity="north" y="8">
   </cl-transformation>
</cl-video>

How do I start using the SDK?

Installation

The SDK can be installed via Node Package Manager by executing the following command in your application's root folder

npm install @cloudinary/angular --save

Or if you’re using yarn:

yarn add @cloudinary/angular

Cloudinary module configuration

The SDK is based on Cloudinary's Javascript module, however the two are decoupled. The Cloudinary module is a configurable service to which you provide your choice of our JS module.

See below for an example Cloudinary configuration in the application module definition:

Copy to clipboard
import { NgModule } from '@angular/core';
...
import { CloudinaryModule, CloudinaryConfiguration, provideCloudinary } from '@cloudinary/angular';

@NgModule({
    imports: [
        CloudinaryModule
    ],
    providers: [
        provideCloudinary(require('cloudinary-core'), { cloud_name: 'your_cloud_name' } as CloudinaryConfiguration)
    ],
    bootstrap: [...]
})
export class AppModule { }

If you are using Angular AOT you need to configure Cloudinary a bit differently:

Copy to clipboard
import { NgModule } from '@angular/core';
...
import { CloudinaryModule } from '@cloudinary/angular';
import { Cloudinary } from 'cloudinary-core/cloudinary-core-shrinkwrap';

const cloudinaryLib = {
  Cloudinary: Cloudinary
}

@NgModule({
    imports: [
    CloudinaryModule.forRoot(cloudinaryLib, {
      cloud_name: 'your_cloud_name'
    })
    ],
    bootstrap: [...]
})
export class AppModule { }

Cloudinary directives

The Cloudinary module provides a component and several directives for:

  • Creating new image and video tags and controlling the underlying chained transformations
  • Enhancing native HTML elements with Cloudinary image management capabilities
Creating image tags with cl-image & cl-transformation

The cl-image component generates an image tag with the requested transformation, type, and format. The image tag can contain optional cl-transformation elements that will be used for chained transformations.

The following example demonstrates a chained transformation with several components applied to a single image

Ruby:
Copy to clipboard
cl_image_tag("angular_logo.jpg", :transformation=>[
  {:effect=>"sepia", :height=>150, :width=>150, :crop=>"fill"},
  {:color=>"#EECCAA", :gravity=>"south", :overlay=>{:font_family=>"arial", :font_size=>20, :text=>"Angular"}, :y=>20},
  {:angle=>20}
  ])
PHP v1:
Copy to clipboard
cl_image_tag("angular_logo.jpg", array("transformation"=>array(
  array("effect"=>"sepia", "height"=>150, "width"=>150, "crop"=>"fill"),
  array("color"=>"#EECCAA", "gravity"=>"south", "overlay"=>array("font_family"=>"arial", "font_size"=>20, "text"=>"Angular"), "y"=>20),
  array("angle"=>20)
  )))
PHP v2:
Copy to clipboard
(new ImageTag('angular_logo.jpg'))
  ->resize(Resize::fill()->width(150)->height(150))
  ->effect(Effect::sepia())
  ->overlay(
      Overlay::source(Source::text('Angular', (new TextStyle('arial', 20)))
        ->textColor(Color::rgb('EECCAA')))
      ->position((new Position())
        ->gravity(Gravity::compass(Compass::south()))
        ->offsetY(20)))
    ->rotate(Rotate::byAngle(20));
Python:
Copy to clipboard
CloudinaryImage("angular_logo.jpg").image(transformation=[
  {'effect': "sepia", 'height': 150, 'width': 150, 'crop': "fill"},
  {'color': "#EECCAA", 'gravity': "south", 'overlay': {'font_family': "arial", 'font_size': 20, 'text': "Angular"}, 'y': 20},
  {'angle': 20}
  ])
Node.js:
Copy to clipboard
cloudinary.image("angular_logo.jpg", {transformation: [
  {effect: "sepia", height: 150, width: 150, crop: "fill"},
  {color: "#EECCAA", gravity: "south", overlay: {font_family: "arial", font_size: 20, text: "Angular"}, y: 20},
  {angle: 20}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .effect("sepia").height(150).width(150).crop("fill").chain()
  .color("#EECCAA").gravity("south").overlay(new TextLayer().fontFamily("arial").fontSize(20).text("Angular")).y(20).chain()
  .angle(20)).imageTag("angular_logo.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('angular_logo.jpg', {transformation: [
  {effect: "sepia", height: 150, width: 150, crop: "fill"},
  {color: "#EECCAA", gravity: "south", overlay: new cloudinary.TextLayer().fontFamily("arial").fontSize(20).text("Angular"), y: 20},
  {angle: 20}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("angular_logo.jpg", {transformation: [
  {effect: "sepia", height: 150, width: 150, crop: "fill"},
  {color: "#EECCAA", gravity: "south", overlay: new cloudinary.TextLayer().fontFamily("arial").fontSize(20).text("Angular"), y: 20},
  {angle: 20}
  ]})
React:
Copy to clipboard
<Image publicId="angular_logo.jpg" >
  <Transformation effect="sepia" height="150" width="150" crop="fill" />
  <Transformation color="#EECCAA" gravity="south" overlay={{fontFamily: "arial", fontSize: 20, text: "Angular"}} y="20" />
  <Transformation angle="20" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="angular_logo.jpg" >
  <cld-transformation effect="sepia" height="150" width="150" crop="fill" />
  <cld-transformation color="#EECCAA" gravity="south" :overlay="{fontFamily: 'arial', fontSize: 20, text: 'Angular'}" y="20" />
  <cld-transformation angle="20" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="angular_logo.jpg" >
  <cl-transformation effect="sepia" height="150" width="150" crop="fill">
  </cl-transformation>
  <cl-transformation color="#EECCAA" gravity="south" overlay="text:arial_20:Angular" y="20">
  </cl-transformation>
  <cl-transformation angle="20">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Effect("sepia").Height(150).Width(150).Crop("fill").Chain()
  .Color("#EECCAA").Gravity("south").Overlay(new TextLayer().FontFamily("arial").FontSize(20).Text("Angular")).Y(20).Chain()
  .Angle(20)).BuildImageTag("angular_logo.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .effect("sepia").height(150).width(150).crop("fill").chain()
  .color("#EECCAA").gravity("south").overlay(new TextLayer().fontFamily("arial").fontSize(20).text("Angular")).y(20).chain()
  .angle(20)).generate("angular_logo.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setEffect("sepia").setHeight(150).setWidth(150).setCrop("fill").chain()
  .setColor("#EECCAA").setGravity("south").setOverlay("text:arial_20:Angular").setY(20).chain()
  .setAngle(20)).generate("angular_logo.jpg")!, cloudinary: cloudinary)
Angular logo chained transformations

It starts by cropping the image to 150x150 pixels and adds a sepia effect. Then it adds a text overlay with the word Angular with a specific font type, font size and color, and positions the text at the bottom. Finally, it rotates the result by 20 degrees:

Copy to clipboard
<cl-image 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>

This will be compiled by Angular to:

Copy to clipboard
<img class="logo" _ngcontent_ovt_3=""
  public_id="angular_logo" 
  ng_reflect_public_id="angular_logo" 
  src="https://res.cloudinary.com/eitanpeer/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">
Creating video tags with cl-video and cl-transformation

The cl-video component generates a <video> tag with the requested transformation, type, and format. The component automatically generates video <source> URLs for all formats supported by web browsers (webm, mp4 and ogv) as a fallback in case the user's browser doesn't support one of them.

The video tag can contain optional cl-transformation elements that will be used for chained transformations.

The following example demonstrates creating a video tag with a single transformation.

Copy to clipboard
<cl-video public-id="manipulation_video" cloud_name="cloudinary" 
   controls="true" preload="none" width="925" crop="scale" 
   autoplay="true"  class="manipulation-video"
   fallback-content="Your browser does not support HTML5 video tags">
<cl-transformation overlay="text:arial_20:Cloudinary%20features" 
   color="red" gravity="north" y="12"></cl-transformation>
</cl-video>

The component automatically adds the source elements and a poster. The example above is compiled by Angular to:

Copy to clipboard
<video _ngcontent-odx-3="" autoplay="true" class="manipulation-video" 
   controls="true" preload="none" publicid="manipulation_video" 
   ng-reflect-public-id="manipulation_video" width="925"
   poster="https://res.cloudinary.com/cloudinary/video/upload/co_red,g_north,l_text:arial_20:Cloudinary%20features,y_12/c_scale,w_925/manipulation_video.jpg">
<source src="https://res.cloudinary.com/cloudinary/video/upload/co_red,g_north,l_text:arial_20:Cloudinary%20features,y_12/c_scale,w_925/manipulation_video.webm" 
   type="video/webm">
<source src="https://res.cloudinary.com/cloudinary/video/upload/co_red,g_north,l_text:arial_20:Cloudinary%20features,y_12/c_scale,w_925/manipulation_video.mp4" 
   type="video/mp4">
<source src="https://res.cloudinary.com/cloudinary/video/upload/co_red,g_north,l_text:arial_20:Cloudinary%20features,y_12/c_scale,w_925/manipulation_video.ogv" 
   type="video/ogg">
Your browser does not support HTML5 video tags
</video>
Attribute directives for enhancing HTML elements - clSrc, clHref, clSrcset

The clSrc, clHref, and clSrcset directives use the element attributes to generate image URLs in Cloudinary.

The following example demonstrates an image thumbnail that displays the full size image when clicked, displaying the full size image optimized with auto quality as a transformation:

Copy to clipboard
<a clHref={{photo.public_id}} format="jpg" target="_blank">
<cl-transformation quality="auto" fetch-format="auto"></cl-transformation>
<cl-image publicId={{photo.public_id}} class="thumbnail inline" width="150" 
   height="150" crop="fit" quality="80" format="jpg">
</cl-image>
</a>

Is this an upgrade of the previous Cloudinary AngularJS SDK?

No. Since Angular itself is a rewrite of AngularJS, the new Angluar SDK is not backwards compatible with Cloudinary’s AngularJS (A.K.A Angular 1) SDK.

However, we are happy to share some tips regarding the migration path for upgrading your previous AngularJS app using Cloudinary’s SDK to the new one.

Migration path

We’ve tried to keep the APIs as close as possible to the original names. We’ve made some changes to conform to Angular’s new style guide.

Angular 1 SDK:

Copy to clipboard
 <a cl-href="{{photo.public_id}}" format="jpg" target="_blank">

Angular 2 SDK:

Copy to clipboard
<a clHref="{{photo.public_id}}" format="jpg" target="_blank">

Can you share tips and tricks from the upgrade ?

In addition to the process of upgrading your Cloudinary SDK code, you may want to consider the following as you migrate your own Angular 1 app to the new version:

  • Use the Angular 1 to 2 quick reference for updating your application's Angular syntax. Following it will get most of your application ready for Angular2.
  • Pay special attention to the new binding syntax. Read it carefully, understand the new mental model and take note of the different binding syntaxes for the different data directions, i.e.
    • One-way from data source to view target. There are 3 different styles for this type of binding:
      • {{expression}} (known as "Interpolation")
      • [target] = "expression" (known as "Property attribute")
      • bind-target = "expression"
    • One-way from view target to data source. There are 2 different styles for this type of binding:
      • (target) = "statement"
      • on-target = "statement"
    • Two-way. There are 2 different styles for this type of binding:
      • [(target)] = "expression"
      • bindon-target = "expression"
  • A lot of content has already been created for the Angular release candidates. Some do not apply to the final released version. Pay attention to the Angular versions in question and dates in the blog posts and StackOverflow answers you read.
  • Check out this curated list of awesome Angular 2 resources by @AngularClass. It has a lot of references for deep diving into Angular’s new architecture and implementation.

Anything else?

Yes. I'm glad you asked.

We’ve created sample projects for the SDK, demonstrating different capabilities and options. In addition, we’ve created a plunker so you can get up and running in no time, without any setup!

The sample projects have the same functionality - a photo list displaying a list of images that respond to a predefined tag, and file upload page for adding images to the list.

The projects differ in their bundling solutions and image upload mechanisms:

Photo Album

This project uses:

  • ng2-file-upload for uploading files using an open source file uploader
  • Webpack for bundling and serving the application

Photo Album with jQuery

This project uses:

Photo Album AOT application

This project demonstrates how the Cloudinary SDK could be used in an Angular application created by Angular’s Ahead of Time compiler. It uses:

  • Angular’s template compiler for ahead-of-time compilation of the application
  • Rollup for bundling the application
  • lite-server as the web server serving the application

Plunker

The plunker code sample is configured to use Cloudinary’s demo cloud, and demonstrates usage of <cl-image> tags. Feel free to fork it and experiment with your own cloud credentials.

Summary

Whether the night was moist, humid, or sultry the main thing here is that you can easily integrate Cloudinary into your Angular application with the new SDK.

These are the basics:

  • Use cl-image and cl-transformation for expressively serving images from your Cloudinary account.

  • Use cl-video and cl-transformation for expressively serving videos from your Cloudinary account, setting up multiple sources for different browsers automatically.

  • Use clSrc, clHref or clSrcset for enhancing native HTML elements to serve images from your Cloudinary account.

For more detail on all available Cloudinary Angular directives and components, see the SDK documentation

Recent Blog Posts

Our $2B Valuation

By
Blackstone Growth Invests in Cloudinary

When we started our journey in 2012, we were looking to improve our lives as developers by making it easier for us to handle the arduous tasks of handling images and videos in our code. That initial line of developer code has evolved into a full suite of media experience solutions driven by a mission that gradually revealed itself over the course of the past 10 years: help companies unleash the full potential of their media to create the most engaging visual experiences.

Read more
Direct-to-Consumer E-Commerce Requires Compelling Visual Experiences

When brands like you adopt a direct–to-consumer (DTC) e-commerce approach with no involvement of retailers or marketplaces, you gain direct and timely insight into evolving shopping behaviors. Accordingly, you can accommodate shoppers’ preferences by continually adjusting your product offering and interspersing the shopping journey with moments of excitement and intrigue. Opportunities abound for you to cultivate engaging customer relationships.

Read more
Automatically Translating Videos for an International Audience

No matter your business focus—public service, B2B integration, recruitment—multimedia, in particular video, is remarkably effective in communicating with the audience. Before, making video accessible to diverse viewers involved tasks galore, such as eliciting the service of production studios to manually dub, transcribe, and add subtitles. Those operations were costly and slow, especially for globally destined content.

Read more
Cloudinary Helps Minted Manage Its Image-Generation Pipeline at Scale

Shoppers return time and again to Minted’s global online community of independent artists and designers because they know they can count on unique, statement-making products of the highest quality there. Concurrently, the visual imagery on Minted.com must do justice to the designs into which the creators have poured their hearts and souls. For Minted’s VP of Engineering David Lien, “Because we are a premium brand, we need to ensure that every single one of our product images matches the selected configuration exactly. For example, if you pick an 18x24 art print on blue canvas, we will show that exact combination on the hero images in the PDF.”

Read more
Highlights on ImageCon 2021 and a Preview of ImageCon 2022

New year, same trend! Visual media will continue to play a monumental role in driving online conversions. To keep up with visual-experience trends and best practices, Cloudinary holds an annual conference called ImageCon, a one-of-a-kind event that helps attendees create the most engaging visual experiences possible.

Read more