DEV Community

Cover image for Angular + Sanity CMS: Mastering Images with the Sanity Image Directive

Angular + Sanity CMS: Mastering Images with the Sanity Image Directive

Hey there, Angular enthusiasts! Welcome back to our Angular + Sanity CMS adventure. In our previous posts, we dove into rendering Portable Text and setting up a Sanity project. Now, it's time to tackle something equally exciting: handling images like a pro!

Today, we're going to explore the Sanity Image Directive and Sanity Image Loader from our trusty @limitless-angular/sanity library. These tools are about to become your new best friends when it comes to working with images in your Angular + Sanity projects. Ready to level up your image game? Let's dive in!

What's so important about using Sanity Images?

Before we start coding, let's talk about why Sanity's approach to images is so cool. Sanity stores image assets separately from your content, allowing you to transform and optimize images on the fly. This means you can have one source image and display it in various sizes, crops, and formats across your site. Pretty neat, right?

The Dynamic Duo: Sanity Image Directive and Loader

Our @limitless-angular/sanity library provides two key players for handling Sanity images:

  1. Sanity Image Directive: This is an Angular directive that makes it super easy to display Sanity images in your templates.
  2. Sanity Image Loader: This is the behind-the-scenes hero that handles the actual loading and transformation of images.

Together, they make working with Sanity images in Angular a breeze!

Step 1: Update Your Sanity Schema

First things first, let's make sure our Sanity schema can handle images. Open up your schemaTypes/post.ts file and update the content field like this:

defineField({
  name: 'content',
  title: 'Content',
  type: 'array',
  of: [{type: 'block'}, {type: 'image'}],
}),
Enter fullscreen mode Exit fullscreen mode

This change allows you to add images directly into your content array, right alongside your text blocks.

Step 2: Create Your Image Component

Now, let's create a new component to handle our images. Create a new file called image.component.ts in the same directory as your portable-text-display.component.ts file. This is typically in your src/app folder or a subdirectory thereof. Paste in this code:

import { ChangeDetectionStrategy, Component } from '@angular/core';
import {
  provideSanityLoader,
  SanityImage,
} from '@limitless-angular/sanity/image-loader';
import { PortableTextTypeComponent } from '@limitless-angular/sanity/portabletext';

@Component({
  selector: 'app-image',
  standalone: true,
  imports: [SanityImage],
  template: `
    <img
      class="mx-auto"
      alt="Sanity Image"
      [width]="400"
      [height]="400"
      [sanityImage]="value()"
    />
  `,
  styles: `
    :host {
      @apply block;
    }
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [
    provideSanityLoader({ projectId: 'your-project-id', dataset: 'production' }),
  ],
})
export class ImageComponent extends PortableTextTypeComponent {}
Enter fullscreen mode Exit fullscreen mode

Let's break this down:

  • We're using the SanityImage directive on our img tag. This is the magic that connects our image to Sanity.
  • The [sanityImage]="value()" attribute is where we pass our Sanity image object.
  • We're setting a fixed width and height here, but you could make these dynamic based on your needs.
  • The provideSanityLoader in the providers array sets up our image loader with your Sanity project details.
  • Importantly, the SanityImage directive inherits from NgOptimizedImage. This means we're automatically getting all the optimizations that NgOptimizedImage provides, without needing to set the ngSrc property separately.

Don't forget to replace 'your-project-id' with your actual Sanity project ID!

Step 3: Update Your Portable Text Component

Now that we have our new ImageComponent, let's use it in our Portable Text setup. Update your portable-text-display.component.ts file:

import { Component, inject } from '@angular/core';
import { PortableTextComponent, PortableTextComponents } from '@limitless-angular/sanity/portabletext';
import { ContentService } from '../content.service';
import { toSignal } from '@angular/core/rxjs-interop';
import { LinkComponent } from './link.component';
import { ImageComponent } from './image.component';

@Component({
  selector: 'app-portable-text-display',
  standalone: true,
  imports: [PortableTextComponent],
  template: `
    @if (portableTextContent(); as content) {
      <div portable-text [value]="content" [components]="customComponents"></div>
    } @else {
      <p>Hold on, content's loading...</p>
    }
  `,
})
export class PortableTextDisplayComponent {
  private contentService = inject(ContentService);

  portableTextContent = toSignal(
    this.contentService.getPortableTextContent('my-first-blog-post')
  );

  customComponents: PortableTextComponents = {
    types: {
      image: ImageComponent,
    },
    marks: {
      link: LinkComponent,
    },
  };
}
Enter fullscreen mode Exit fullscreen mode

The key change here is adding ImageComponent to our customComponents object under the types key. This tells our Portable Text renderer to use our custom ImageComponent whenever it encounters an image in the content.

Step 4: Marvel at Your Handiwork

That's it! Now, when you run your Angular app and load some content from Sanity that includes images, they should render beautifully using your new ImageComponent.

Here's what's happening behind the scenes:

  1. The Portable Text renderer encounters an image in your content.
  2. It uses your ImageComponent to render that image.
  3. The SanityImage directive in your ImageComponent works with the Sanity Image Loader to fetch and optimize the image.
  4. Because SanityImage inherits from NgOptimizedImage, you're automatically getting all the built-in Angular image optimizations.
  5. The result? A beautifully rendered, fully optimized image in your Angular app!

Bonus Tips and Tricks

Want to take your Sanity image game to the next level? Here are a few extra tips:

  1. Responsive Images: The SanityImage directive already provides responsive image handling through its inheritance from NgOptimizedImage. You can further customize this by adjusting the sizes attribute if needed.

  2. Image Transformations: Sanity's image API allows for on-the-fly transformations. You can adjust things like width, height, crop, and even apply filters directly in your image URL.

  3. Lazy Loading: Good news! The SanityImage directive automatically includes lazy loading functionality from NgOptimizedImage, so your images will lazy load by default.

Wrapping Up

And there you have it! You've just leveled up your Angular + Sanity CMS skills by mastering image handling. With the Sanity Image Directive and Loader, you now have the power to effortlessly display and optimize images in your Angular applications.

Remember, great images can make a big difference in a user's experience, so use these tools wisely. Keep experimenting, keep learning, and most importantly, keep enjoying your work with Angular and Sanity!

If you want to dive deeper, check out these resources:

Happy coding, and may your images always be crisp, your load times swift, and your users delighted!

Top comments (0)