Run the CLI
Use the CLI to add the component to your project.
npx @ngzard/ui add emptyThe Empty component displays a placeholder when no data is available, commonly used in tables, lists, or search results.
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ZardButtonComponent } from '../../button/button.component';
import { ZardIconComponent } from '../../icon/icon.component';
import { ZardEmptyComponent } from '../empty.component';
@Component({
selector: 'z-demo-empty-default',
standalone: true,
imports: [ZardButtonComponent, ZardEmptyComponent, ZardIconComponent],
template: `
<z-empty
zIcon="folder-code"
zTitle="No Projects Yet"
zDescription="You haven't created any projects yet. Get started by creating your first project."
[zActions]="[actionPrimary, actionSecondary]"
>
<ng-template #actionPrimary>
<button z-button>Create Project</button>
</ng-template>
<ng-template #actionSecondary>
<button z-button zType="outline">Import Project</button>
</ng-template>
<button z-button zType="link" zSize="sm" class="text-muted-foreground">
Learn More
<i z-icon zType="arrow-up-right"></i>
</button>
</z-empty>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoEmptyDefaultComponent {}
Use the CLI to add the component to your project.
npx @ngzard/ui add emptypnpm dlx @ngzard/ui add emptyyarn dlx @ngzard/ui add emptybunx @ngzard/ui add emptyCreate the component directory structure and add the following files to your project.
import { ChangeDetectionStrategy, Component, computed, input, type TemplateRef, ViewEncapsulation } from '@angular/core';
import type { ClassValue } from 'clsx';
import { emptyActionsVariants, emptyDescriptionVariants, emptyHeaderVariants, emptyIconVariants, emptyImageVariants, emptyTitleVariants, emptyVariants } from './empty.variants';
import { mergeClasses } from '../../shared/utils/utils';
import { ZardStringTemplateOutletDirective } from '../core/directives/string-template-outlet/string-template-outlet.directive';
import { ZardIconComponent } from '../icon/icon.component';
import { type ZardIcon } from '../icon/icons';
@Component({
selector: 'z-empty',
exportAs: 'zEmpty',
standalone: true,
imports: [ZardIconComponent, ZardStringTemplateOutletDirective],
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
template: `
@let image = zImage();
@let icon = zIcon();
@let title = zTitle();
@let description = zDescription();
@let actions = zActions();
<div [class]="headerClasses()">
@if (image) {
<div [class]="imageClasses()">
<ng-container *zStringTemplateOutlet="image">
<img [src]="image" alt="Empty" class="mx-auto" />
</ng-container>
</div>
} @else if (icon) {
<div [class]="iconClasses()" data-testid="icon">
<z-icon [zType]="icon" zSize="xl" />
</div>
}
@if (title) {
<div [class]="titleClasses()">
<ng-container *zStringTemplateOutlet="title">{{ title }}</ng-container>
</div>
}
@if (description) {
<div [class]="descriptionClasses()">
<ng-container *zStringTemplateOutlet="description">{{ description }}</ng-container>
</div>
}
</div>
@if (actions.length) {
<div [class]="actionsClasses()">
@for (action of actions; track $index) {
<ng-container *zStringTemplateOutlet="action" />
}
</div>
}
<ng-content></ng-content>
`,
host: {
'[class]': 'classes()',
},
})
export class ZardEmptyComponent {
readonly zActions = input<TemplateRef<void>[]>([]);
readonly zIcon = input<ZardIcon>();
readonly zImage = input<string | TemplateRef<void>>();
readonly zTitle = input<string | TemplateRef<void>>();
readonly zDescription = input<string | TemplateRef<void>>();
readonly class = input<ClassValue>('');
protected readonly classes = computed(() => mergeClasses(emptyVariants(), this.class()));
protected readonly headerClasses = computed(() => emptyHeaderVariants());
protected readonly imageClasses = computed(() => emptyImageVariants());
protected readonly iconClasses = computed(() => emptyIconVariants());
protected readonly titleClasses = computed(() => emptyTitleVariants());
protected readonly descriptionClasses = computed(() => emptyDescriptionVariants());
protected readonly actionsClasses = computed(() => emptyActionsVariants());
}
import { cva } from 'class-variance-authority';
export const emptyVariants = cva('flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border-dashed p-6 text-center text-balance md:p-12', {
variants: {},
});
export const emptyHeaderVariants = cva('flex max-w-sm flex-col items-center gap-2 text-center', {
variants: {},
});
export const emptyImageVariants = cva('mb-2 flex shrink-0 items-center justify-center bg-transparent [&_svg]:pointer-events-none [&_svg]:shrink-0', {
variants: {},
});
export const emptyIconVariants = cva(
`bg-muted text-foreground mb-2 flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-6`,
{
variants: {},
},
);
export const emptyTitleVariants = cva('text-lg font-medium tracking-tight', {
variants: {},
});
export const emptyDescriptionVariants = cva('text-muted-foreground [&>a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4', {
variants: {},
});
export const emptyActionsVariants = cva('flex w-full max-w-sm min-w-0 items-center justify-center gap-2 text-sm text-balance', {
variants: {},
});
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ZardButtonComponent } from '../../button/button.component';
import { ZardIconComponent } from '../../icon/icon.component';
import { ZardEmptyComponent } from '../empty.component';
@Component({
selector: 'z-demo-empty-default',
standalone: true,
imports: [ZardButtonComponent, ZardEmptyComponent, ZardIconComponent],
template: `
<z-empty
zIcon="folder-code"
zTitle="No Projects Yet"
zDescription="You haven't created any projects yet. Get started by creating your first project."
[zActions]="[actionPrimary, actionSecondary]"
>
<ng-template #actionPrimary>
<button z-button>Create Project</button>
</ng-template>
<ng-template #actionSecondary>
<button z-button zType="outline">Import Project</button>
</ng-template>
<button z-button zType="link" zSize="sm" class="text-muted-foreground">
Learn More
<i z-icon zType="arrow-up-right"></i>
</button>
</z-empty>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoEmptyDefaultComponent {}
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ZardButtonComponent } from '../../button/button.component';
import { ZardEmptyComponent } from '../empty.component';
@Component({
selector: 'z-demo-empty-custom-image',
standalone: true,
imports: [ZardButtonComponent, ZardEmptyComponent],
template: `
<z-empty
zImage="images/avatar/imgs/avatar_image.jpg"
zTitle="User Offline"
zDescription="This user is currently offline. You can leave a message to notify them or try again later."
[zActions]="[actionPrimary]"
class="[&_img]:size-12 [&_img]:rounded-full [&_img]:grayscale"
/>
<ng-template #actionPrimary>
<button z-button>Leave Message</button>
</ng-template>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoEmptyCustomImageComponent {}




import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ZardAvatarGroupComponent } from '../../avatar/avatar-group.component';
import { ZardAvatarComponent } from '../../avatar/avatar.component';
import { ZardButtonComponent } from '../../button/button.component';
import { ZardIconComponent } from '../../icon/icon.component';
import { ZardEmptyComponent } from '../empty.component';
@Component({
selector: 'z-demo-empty-advanced-customization',
standalone: true,
imports: [ZardAvatarComponent, ZardAvatarGroupComponent, ZardButtonComponent, ZardIconComponent, ZardEmptyComponent],
template: `
<z-empty [zImage]="customImage" [zTitle]="customTitle" zDescription="Invite your team to collaborate on this project." [zActions]="[actionInvite]"> </z-empty>
<ng-template #customImage>
<z-avatar-group>
<z-avatar zSrc="https://github.com/srizzon.png" zSize="md" class="grayscale" />
<z-avatar zSrc="https://github.com/Luizgomess.png" zSize="md" class="grayscale" />
<z-avatar zSrc="https://github.com/ribeiromatheuss.png" zSize="md" class="grayscale" />
<z-avatar zSrc="https://github.com/mikij.png" zSize="md" class="grayscale" />
</z-avatar-group>
</ng-template>
<ng-template #customTitle>
<span>No Team <strong>members</strong></span>
</ng-template>
<ng-template #actionInvite>
<button z-button zSize="sm">
<i z-icon zType="plus"></i>
Invite Members
</button>
</ng-template>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoEmptyAdvancedComponent {}