Image Cells
Display images in grid cells using Angular's NgOptimizedImage. Control fit, shape, size, and fallback per column — with zero-markup declarative config or full cellTemplate control.
Declarative (column.image)
Set image on any column definition and the grid renders <gc-image> automatically — no template required. The last column points to a broken URL; the grid swaps in each row's individual fallback image instead of showing a broken icon.












cellTemplate with <gc-image>
Use cellTemplate when you need full control over every gc-image input — for example, to combine an image with text, apply conditional bindings, or use inputs that aren't exposed through column.image.
Two ways to show images in a cell
Use column.image for the zero-markup path — set it on any column definition and the
grid renders <gc-image> automatically. Use cellTemplate with
<gc-image> directly when you need full Angular template power: conditional
bindings, combining an image with text, or anything the declarative config doesn't cover.
column.image — declarative config
The src field is a function that receives the row and returns the image URL.
If you omit it, the grid falls back to the column's resolved cell value via prop
or valueGetter.
{
key: 'avatar', name: 'Avatar', width: 80,
image: {
src: r => r.avatarUrl,
shape: 'circle',
fill: false,
width: 48,
height: 48,
alt: r => r.name,
},
}
fill vs fixed size
fill: true (default) makes the image behave like a background — it stretches to
cover the full cell area. Good for landscape photos and cover-style columns. Set
fill: false with explicit width and height when you need
a fixed-size image that doesn't scale with the row, like a 48×48 avatar.
Fit modes
fit maps directly to CSS object-fit. The two you'll reach for most often:
'cover'(default) — fills the cell and crops edges to maintain ratio.'contain'— shrinks to fit the full image inside the cell with letterboxing.'fill'— stretches to fill exactly, ignoring aspect ratio.'none'— natural image size, no scaling.'scale-down'— likecontainbut never scales up.
Shape
shape: 'circle' clips to a circle — standard for user avatars.
'rounded' adds a subtle border-radius suitable for thumbnails.
Default is 'square' (no clip).
Fallback on load error
fallback accepts either a static string or a per-row function. When the
primary image fails, the grid swaps it out immediately with no broken-image icon.
// static — same fallback for every row
image: { src: r => r.photo, fallback: '/assets/placeholder.png' }
// per-row — each row supplies a different fallback
image: { src: r => r.photo, fallback: r => r.fallbackUrl }
If no fallback is provided and the image fails, the cell renders a muted grey placeholder.
Loading behaviour
Images load eagerly by default. Only set priority: true when the image is the
page's Largest Contentful Paint (LCP) candidate — a hero image above the fold, not a grid
column. Angular's NgOptimizedImage caps LCP-priority images at 5 per page;
marking an entire column as priority triggers a console warning and defeats the purpose.
Use loading="lazy" on <gc-image> only when placing it outside
a virtualised grid where images are genuinely off-screen on load.
CDN loaders
For images served from Cloudinary, Imgix, ImageKit or similar, register the matching Angular
image loader in your app config. The grid doesn't bundle any loader — it defers to whatever
NgOptimizedImage finds at the app level, so optimised srcset
attributes are generated automatically once the loader is in place.
// app.config.ts
import { provideImgixLoader } from '@angular/common';
providers: [provideImgixLoader('https://your-subdomain.imgix.net')]
Don't set priority: true on a grid column — Angular caps LCP-priority images at
5 per page and warns in the console. Priority is for a single above-the-fold hero image,
never a virtualised column.
column.image options
| Property | Type | Default | Description |
|---|---|---|---|
| column.image | GcImageConfig | — | Zero-markup path — the grid renders <gc-image> automatically for the column. |
| image.src | (row) => string | cell value | URL resolver; falls back to the column’s resolved value via prop/valueGetter. |
| image.fit | 'cover' | 'contain' | 'fill' | 'none' | 'scale-down' | 'cover' | Maps to CSS object-fit. |
| image.fill | boolean | true | true stretches to cover the cell; false + width/height gives a fixed-size image. |
| image.shape | 'square' | 'rounded' | 'circle' | 'square' | Clip shape — circle for avatars, rounded for thumbnails. |
| image.fallback | string | (row) => string | grey placeholder | Swapped in immediately when the primary image fails — no broken-image icon. |
| image.alt | (row) => string | — | Accessible alt text per row. |