> ## Documentation Index
> Fetch the complete documentation index at: https://cloudinary.com/documentation/llms.txt
> Use this file to discover all available pages before exploring further.

# Angular migration guide


## Introduction

Cloudinary's [Angular SDK](angular_integration) is designed to provide a simpler and more enhanced developer experience. This guide explains how to migrate your Angular code from the legacy [cloudinary_angular](https://github.com/cloudinary/cloudinary_angular) (legacy Angular library) to the latest Angular SDK, which includes `@cloudinary/ng` from the [frontend-frameworks](https://github.com/cloudinary/frontend-frameworks/tree/master/packages/angular) library together with `@cloudinary/url-gen` from the [js-url-gen](https://github.com/cloudinary/js-url-gen) library.

Key improvements in the Angular SDK:

* A new action-based syntax, designed to make building delivery URLs and transformations more logical and discoverable.
    * When compiled to the final delivery URL, each action (including any action [qualifiers](image_transformations#parameter_types)) represents a different component (separated by a '/'), for example: `/c_scale,w_400/f_auto/q_auto/`, rather than `/c_scale,f_auto,q_auto,w_400/`.
* Newly added autocomplete to list options and parameters and ensure only those that are supported can be used together.
* A smaller bundle size - you only need to import what you want to use.

> **INFO**:
>
> :title=Things to know before migrating to @cloudinary/ng + @cloudinary/url-gen 
> The action-based syntax used in the `js-url-gen` library (`@cloudinary/url-gen`) may cause URLs to be formed differently from those generated by the `cloudinary_angular` library. 
> For example: 

> * **URL generated with the cloudinary_angular library:**`https://res.cloudinary.com/demo/image/upload/c_scale,f_auto,q_auto,w_400/sample.jpg`

> * **URL generated with the js-url-gen library:** `https://res.cloudinary.com/demo/image/upload/c_scale,w_400/f_auto/q_auto/sample.jpg`
> Even if the delivered media file looks and behaves identically, changes to URLs can have the following implications:

> * You may see a one-time increase in [transformation counts](transformation_counts)

> * You may see a one-time increase in storage usage for the new derived assets

> * You may see a one-time increase in add-on usage when add-on transformation parameters are used in the URL

> * CDN caches may need to be warmed with the new derived assets

> * If [strict transformations](control_access_to_media#strict_transformations) are enabled for your product environment (in the Security page of your Console Settings), you need to allow the new transformations

> * If you require transformations to be generated [eagerly](eager_and_incoming_transformations#eager_transformations), for example long videos, you need to regenerate these via the latest SDK, using the `eager` parameter of the [explicit](image_upload_api_reference#explicit_method) method.
> To reduce the impact of all of the above, we recommend using the [createCloudinaryLegacyURL](#migrating_delivery_urls) method for your existing transformation URLs, especially if your existing app delivers a large number of transformed assets. This maintains the formations of the transformations, so the URLs remain the same.
> The `createCloudinaryLegacyURL` function supports only transformation and configuration parameters. It does not help to migrate HTML tags, responsive, placeholder, transparent video or jQuery functionality.
> For all new transformation URLs that you add to your application, we recommend using the new action-based SDK syntax offered by the latest version of the SDK.

For full documentation on using the `@cloudinary/ng` + `@cloudinary/url-gen` packages in your Angular app, see the [Angular SDK guide](angular_integration).

## Key considerations

Cloudinary's Angular package (`@cloudinary/ng` from the `frontend-frameworks` library) must be used in conjunction with the [Cloudinary JavaScript SDK](javascript_integration) (`@cloudinary/url-gen`) to provide all of Cloudinary's transformation and optimization functionality. As such, the latest Angular SDK is very different from the `cloudinary_angular` library in its architecture and usage, so migration paths depend on your current usage of the Angular library.

You can use the `cloudinary-core`, `cloudinary/angular-5.x` (or other version), `@cloudinary/ng` and `@cloudinary/url-gen` packages in your application concurrently, so although not recommended for the long term due to the increased bundle size, you could start by integrating `@cloudinary/ng` and `@cloudinary/url-gen` into your application and slowly migrate your functionality piece by piece, until you are able to remove all `cloudinary_angular` functionality.

## Installation

Install the required packages using the NPM package manager:

```
npm i @cloudinary/url-gen @cloudinary/ng
```

## Migrating Cloudinary instance configuration

Using the legacy Angular SDK, you configure your cloud name and other configuration parameters in a `CloudinaryModule`. This is similar to configuring these parameters in a `Cloudinary` instance, provided by the `@cloudinary/url-gen` library, in that the configuration is set once, rather than for each image or video.

For example, setting `cloudName` and `secure` in a `CloudinaryModule` element:

```angular
// Legacy SDK
import { CloudinaryModule } from '@cloudinary/angular-5.x';
import * as Cloudinary from 'cloudinary-core';

imports: [
   ...,
    CloudinaryModule.forRoot(Cloudinary, { cloud_name: 'demo', secure: true })
  ],
```

is similar to setting `cloudName` and `secure` in a `Cloudinary` instance:

```angular
// Latest SDK - app.component.ts: 
import {CloudinaryModule} from '@cloudinary/ng';
import {Cloudinary} from '@cloudinary/url-gen';

imports: [
  ...,
  CloudinaryModule
],

var cl = new Cloudinary({cloud: {cloudName: 'demo'}, url: {secure: true}});
```

> **NOTE**: Using `@cloudinary/url-gen` you can also set configuration parameters on a per asset instance:

```angular
// Latest SDK - app.component.ts: 
import {CloudinaryModule} from '@cloudinary/ng';
import {CloudinaryImage} from '@cloudinary/url-gen';

imports: [
  ...,
  CloudinaryModule
],

myImage: CloudinaryImage

this.myImage = new CloudinaryImage('sample', {cloudName: 'demo'});
```

However, if you use the Cloudinary instance configuration, you don't need to add configuration parameters to your asset instances:

```angular
this.myImage = cl.image('sample'); 
```

## Migrating delivery URLs

The `cl-image` component in the legacy Angular SDK has been replaced by the `advanced-image` component in `@cloudinary/ng`. 

Whereas in the legacy Angular SDK you specify transformation parameters in the `cl-image` component, in the latest SDK they are specified in `@cloudinary/url-gen` in a `CloudinaryImage` object that you then pass to the `advanced-image` component.

Here is an example of a `cl-image` component with transformation parameters included: 

```html
<!-- Legacy SDK -->
<cl-image public-id='actor.jpg' >
  <cl-transformation effect='cartoonify'>
  </cl-transformation>
  <cl-transformation radius='max'>
  </cl-transformation>
  <cl-transformation effect='outline:100' color='lightblue'>
  </cl-transformation>
  <cl-transformation background='lightblue'>
  </cl-transformation>
  <cl-transformation height='300' crop='scale'>
  </cl-transformation>
</cl-image>
```

There is no easy migration path from a `cl-image` component to an `advanced-image` component, but you can use the following process as an intermediate step, to create a URL that you can use as the source for a regular image tag:

1. Convert the `cl-image` component to JSON. An XML to JSON converter can help with this transition, or you may want to use a script if you have a large number of URLs to convert. The previous example would become: 

    ```angularon
    {
        transformation: [
            {effect: "cartoonify"},
            {radius: "max"},
            {effect: "outline:100", color: "lightblue"},
            {background: "lightblue"},
            {height: 300, crop: "scale"}
        ]
    }
    ```
2. Pass this JSON to the `createCloudinaryLegacyURL` function, included in the `@cloudinary/url-gen` library, to return a delivery URL that includes the transformations. Configuration parameters, such as `cloud_name`, should be included in the function call as this is simply a helper function to build the delivery URL:

    ```angular
    // Latest SDK
    import {createCloudinaryLegacyURL} from '@cloudinary/url-gen';

    const migrateUrl = createCloudinaryLegacyURL('actor', {
        cloud_name: 'demo',
        transformation: [
        {effect: 'cartoonify'},
        {radius: 'max'},
        {effect: 'outline:100', color: 'lightblue'},
        {background: 'lightblue'},
        {height: 300, crop: 'scale'}
        ]
    });
    ```
3. Use this URL as the source for a regular image tag. 

    ```angular
    // Latest SDK
    const imgElement = document.createElement('img');
    imgElement.src = migrateUrl;
    // Append the image element to the DOM, for example:
    document.getElementById('div1').appendChild(imgElement);
    ```

    ```html
    <!--Where div1 is the ID of a div element in your HTML file-->
    <div id="div1"></div>
    ```

If you have a large number of assets, we recommend you migrate using the `createCloudinaryLegacyURL` method. If you replace your existing transformations using the new SDK transformation syntax, you may find your URLs are generated in a slightly different way. See [Things to know before migrating to @cloudinary/ng + @cloudinary/url-gen](#sdk_migration_considerations), for the implications of these changes to transformation URLs.

For all new Cloudinary delivery URLs, you should start to use `@cloudinary/url-gen` to create a `CloudinaryImage` that you can use in the `advanced-image` Angular component:

```angular
// In your app.component.ts use `@cloudinary/url-gen` to generate your transformations.

import {CloudinaryModule} from '@cloudinary/ng';
import {Component, OnInit} from '@angular/core';
import {CloudinaryImage} from '@cloudinary/url-gen';
import {scale} from '@cloudinary/url-gen/actions/resize';
import {outline, cartoonify} from '@cloudinary/url-gen/actions/effect';
import {max} from '@cloudinary/url-gen/actions/roundCorners';
import {outer} from '@cloudinary/url-gen/qualifiers/outlineMode';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet, CloudinaryModule],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})

export class AppComponent implements OnInit{
  myImage: CloudinaryImage

  ngOnInit() {
    
    // Use the image with public ID, 'actor'.
    this.myImage = new CloudinaryImage('actor', {cloudName: 'demo'});
  
    // Apply the transformation.
    this.myImage
    .effect(cartoonify())
    .roundCorners(max())
    .effect(outline().mode(outer()).width(100).color('lightblue'))
    .backgroundColor('lightblue')
    .resize(scale().height(300));
  }
}
```

```html
<!-- In your view add the advanced-image component and pass your Cloudinary image. -->
<advanced-image [cldImg]="myImage"></advanced-image>
```
> **NOTE**:
>
> If you're not using standalone components, then you'll need to import the `CloudinaryModule` in **app.module.ts** instead.
The resulting URL is:

![Transformed actor](https://res.cloudinary.com/demo/image/upload/e_cartoonify/r_max/co_lightblue,e_outline:100/b_lightblue/c_scale,h_300/actor "with_code: false")

## Migrating advanced image components and responsive functionality

The advanced image components ([lazy loading](angular1_image_manipulation#lazy_loading), [image placeholders](angular1_image_manipulation#image_placeholders) and [image accessibility](angular1_image_manipulation#image_accessibility)) and [responsive image settings](angular1_image_manipulation#responsive_image_settings) offered by the legacy Angular SDK, are offered as [plugins](angular_image_transformations#plugins) in the latest Angular SDK.

When you have migrated your delivery URLs to use the `advanced-image` component, you can use any of the plugins as follows:

> **NOTE**: This example shows all four plugins being used, but you can use only one, or any combination, by importing and specifying only those you need.

// In your app.component.ts use `@cloudinary/url-gen` to generate your transformations.
import {CloudinaryModule} from '@cloudinary/ng';
import {Component, OnInit} from '@angular/core';
import {CloudinaryImage} from '@cloudinary/url-gen';

// Import the plugins.
import {accessibility, responsive, lazyload, placeholder} from '@cloudinary/ng';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet, CloudinaryModule],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})

export class AppComponent implements OnInit{
  myImage: CloudinaryImage;

   // Use all the plugins.
  plugins = [lazyload(), responsive(), accessibility(), placeholder()]

  ngOnInit() {

    this.myImage = new CloudinaryImage('sample', {cloudName: 'demo'});

  }
}

// In your view add the advanced-image component and pass your Cloudinary image and plugins.

```
> **NOTE**:
>
> If you're not using standalone components, then you'll need to import the `CloudinaryModule` in **app.module.ts** instead.
> **READING**:
>
> * Take a look at the full [Angular SDK guide](angular_integration).    

> * See examples of powerful [image](angular_image_transformations) and [video](angular_video_transformations) transformations using `@cloudinary/url-gen`.

> * See our [image transformations](image_transformations) and [video transformations](video_manipulation_and_delivery) guides. 

> * Stay tuned for updates by following the [Release Notes](programmable_media_release_notes) and the [Cloudinary Blog](https://cloudinary.com/blog).
