Angular NgZorro Integration
Introduction
NgZorro is a comprehensive UI component library for Angular based on the Ant Design system. It offers a wide range of high-quality components that help developers build elegant, consistent, and accessible web applications with minimal effort. By integrating NgZorro with your Angular project, you gain access to a rich ecosystem of pre-built components, from basic buttons and forms to complex date pickers, tables, and more.
In this tutorial, we'll explore how to integrate NgZorro into an Angular application and utilize some of its most popular components.
Why Choose NgZorro?
- Enterprise-Grade Components: Built for business applications with complex UIs
- Angular-First: Specifically designed for Angular, not a wrapper around vanilla JavaScript libraries
- Internationalization: Supports multiple languages out of the box
- Customizable Themes: Easy theming using less variables
- Accessibility: Built with a11y in mind
- Active Maintenance: Regular updates and strong community support
Prerequisites
Before we start, make sure you have:
- Node.js (v12.x or later) and npm installed
- Angular CLI installed (
npm install -g @angular/cli
) - Basic knowledge of Angular
Step 1: Create a New Angular Project
If you don't have an existing project, let's create one:
ng new my-ngzorro-app
cd my-ngzorro-app
Step 2: Install NgZorro
Now, let's add NgZorro to our project:
ng add ng-zorro-antd
This command will:
- Install the NgZorro library and its dependencies
- Add necessary styles and scripts to
angular.json
- Import NgZorro modules to
app.module.ts
- Set up internationalization
- Add browser animations
When prompted, you can choose:
- Whether to set up custom theme
- Whether to use dark theme
- Which locale to use (e.g., en_US)
- Whether to set up automatically
Step 3: Configure NgZorro in Your Application
The ng add
command should have already updated your app.module.ts
. It should look something like this:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
// NgZorro imports
import { NZ_I18N } from 'ng-zorro-antd/i18n';
import { en_US } from 'ng-zorro-antd/i18n';
import { registerLocaleData } from '@angular/common';
import en from '@angular/common/locales/en';
registerLocaleData(en);
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
HttpClientModule,
BrowserAnimationsModule
],
providers: [{ provide: NZ_I18N, useValue: en_US }],
bootstrap: [AppComponent]
})
export class AppModule {}
Step 4: Import Specific NgZorro Modules
NgZorro uses a modular approach, allowing you to import only the components you need. Let's import a few basic components:
// app.module.ts
import { NgModule } from '@angular/core';
// ... other imports
// NgZorro component modules
import { NzButtonModule } from 'ng-zorro-antd/button';
import { NzLayoutModule } from 'ng-zorro-antd/layout';
import { NzMenuModule } from 'ng-zorro-antd/menu';
import { NzIconModule } from 'ng-zorro-antd/icon';
@NgModule({
declarations: [AppComponent],
imports: [
// ... other imports
NzButtonModule,
NzLayoutModule,
NzMenuModule,
NzIconModule
],
providers: [{ provide: NZ_I18N, useValue: en_US }],
bootstrap: [AppComponent]
})
export class AppModule {}
Step 5: Create a Basic Layout
Let's update our app.component.html
file to use NgZorro components for a basic layout:
<nz-layout>
<nz-header>
<div class="logo"></div>
<ul nz-menu nzTheme="dark" nzMode="horizontal">
<li nz-menu-item nzSelected>Home</li>
<li nz-menu-item>Products</li>
<li nz-menu-item>About</li>
<li nz-menu-item>Contact</li>
</ul>
</nz-header>
<nz-content>
<div class="inner-content">
<h1>Welcome to NgZorro!</h1>
<p>This is a basic layout example using NgZorro components.</p>
<div class="button-demo">
<button nz-button nzType="primary">Primary Button</button>
<button nz-button nzType="default">Default Button</button>
<button nz-button nzType="dashed">Dashed Button</button>
<button nz-button nzType="text">Text Button</button>
<button nz-button nzType="link">Link Button</button>
</div>
</div>
</nz-content>
<nz-footer>Angular NgZorro Demo ©2023</nz-footer>
</nz-layout>
Add some basic styling in app.component.css
:
.logo {
width: 120px;
height: 31px;
background: rgba(255, 255, 255, 0.2);
margin: 16px 28px 16px 0;
float: left;
}
nz-header {
position: fixed;
width: 100%;
z-index: 1;
}
nz-content {
padding: 0 50px;
margin-top: 64px;
}
.inner-content {
background: #fff;
padding: 24px;
min-height: 280px;
}
nz-footer {
text-align: center;
}
.button-demo {
margin-top: 20px;
}
.button-demo button {
margin-right: 8px;
margin-bottom: 12px;
}
Step 6: Run Your Application
Now let's see our NgZorro application in action:
ng serve
Visit http://localhost:4200
in your browser, and you should see your application with the NgZorro components.
Real-World Example: Creating a User Registration Form
Let's create a more practical example using NgZorro components. We'll build a user registration form with validation:
First, import the necessary modules in app.module.ts
:
import { ReactiveFormsModule } from '@angular/forms';
import { NzFormModule } from 'ng-zorro-antd/form';
import { NzInputModule } from 'ng-zorro-antd/input';
import { NzSelectModule } from 'ng-zorro-antd/select';
import { NzDatePickerModule } from 'ng-zorro-antd/date-picker';
import { NzCheckboxModule } from 'ng-zorro-antd/checkbox';
@NgModule({
// ...
imports: [
// ... other imports
ReactiveFormsModule,
NzFormModule,
NzInputModule,
NzSelectModule,
NzDatePickerModule,
NzCheckboxModule
],
})
export class AppModule { }
Now, let's update our component class in app.component.ts
:
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { NzFormTooltipIcon } from 'ng-zorro-antd/form';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
registerForm: FormGroup;
// For the select dropdown
listOfOption = [
{ label: 'Software Development', value: 'dev' },
{ label: 'Design', value: 'design' },
{ label: 'Marketing', value: 'marketing' },
{ label: 'Sales', value: 'sales' },
{ label: 'Other', value: 'other' }
];
submitForm(): void {
if (this.registerForm.valid) {
console.log('Form submitted:', this.registerForm.value);
// Here you would typically send the form to your backend
} else {
Object.values(this.registerForm.controls).forEach(control => {
if (control.invalid) {
control.markAsDirty();
control.updateValueAndValidity({ onlySelf: true });
}
});
}
}
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.registerForm = this.fb.group({
email: [null, [Validators.required, Validators.email]],
password: [null, [Validators.required, Validators.minLength(6)]],
confirmPassword: [null, [Validators.required]],
name: [null, [Validators.required]],
phoneNumber: [null, [Validators.pattern(/^\d{10}$/)]],
department: [null, [Validators.required]],
birthday: [null],
agree: [false, [Validators.requiredTrue]]
});
}
validateConfirmPassword(): void {
setTimeout(() => {
const { password, confirmPassword } = this.registerForm.controls;
if (confirmPassword.value) {
if (password.value !== confirmPassword.value) {
confirmPassword.setErrors({ passwordMismatch: true });
} else {
confirmPassword.setErrors(null);
}
}
});
}
}
Finally, update the HTML template in app.component.html
:
<nz-layout>
<nz-content>
<div class="registration-container">
<h1>User Registration</h1>
<form nz-form [formGroup]="registerForm" (ngSubmit)="submitForm()">
<!-- Email -->
<nz-form-item>
<nz-form-label [nzSpan]="6" nzRequired nzFor="email">E-mail</nz-form-label>
<nz-form-control [nzSpan]="14" nzErrorTip="Please enter a valid email!">
<input nz-input formControlName="email" id="email" />
</nz-form-control>
</nz-form-item>
<!-- Password -->
<nz-form-item>
<nz-form-label [nzSpan]="6" nzRequired nzFor="password">Password</nz-form-label>
<nz-form-control [nzSpan]="14" nzErrorTip="Please enter at least 6 characters!">
<input
nz-input
type="password"
formControlName="password"
id="password"
(ngModelChange)="validateConfirmPassword()"
/>
</nz-form-control>
</nz-form-item>
<!-- Confirm Password -->
<nz-form-item>
<nz-form-label [nzSpan]="6" nzRequired nzFor="confirmPassword">Confirm Password</nz-form-label>
<nz-form-control [nzSpan]="14" [nzErrorTip]="passwordErrorTpl">
<input
nz-input
type="password"
formControlName="confirmPassword"
id="confirmPassword"
/>
<ng-template #passwordErrorTpl let-control>
<ng-container *ngIf="control.hasError('required')">
Please confirm your password!
</ng-container>
<ng-container *ngIf="control.hasError('passwordMismatch')">
Passwords do not match!
</ng-container>
</ng-template>
</nz-form-control>
</nz-form-item>
<!-- Name -->
<nz-form-item>
<nz-form-label [nzSpan]="6" nzRequired nzFor="name">Full Name</nz-form-label>
<nz-form-control [nzSpan]="14" nzErrorTip="Please enter your name!">
<input nz-input formControlName="name" id="name" />
</nz-form-control>
</nz-form-item>
<!-- Phone Number -->
<nz-form-item>
<nz-form-label [nzSpan]="6" nzFor="phoneNumber">Phone Number</nz-form-label>
<nz-form-control [nzSpan]="14" nzErrorTip="Please enter a valid 10-digit phone number!">
<input nz-input formControlName="phoneNumber" id="phoneNumber" />
</nz-form-control>
</nz-form-item>
<!-- Department -->
<nz-form-item>
<nz-form-label [nzSpan]="6" nzRequired nzFor="department">Department</nz-form-label>
<nz-form-control [nzSpan]="14" nzErrorTip="Please select your department!">
<nz-select formControlName="department" id="department">
<nz-option
*ngFor="let option of listOfOption"
[nzLabel]="option.label"
[nzValue]="option.value">
</nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
<!-- Birthday -->
<nz-form-item>
<nz-form-label [nzSpan]="6" nzFor="birthday">Date of Birth</nz-form-label>
<nz-form-control [nzSpan]="14">
<nz-date-picker formControlName="birthday" id="birthday"></nz-date-picker>
</nz-form-control>
</nz-form-item>
<!-- Agreement -->
<nz-form-item>
<nz-form-control [nzSpan]="14" [nzOffset]="6" nzErrorTip="You must agree to the terms!">
<label nz-checkbox formControlName="agree">
I have read and agree to the <a href="#">Terms of Service</a>
</label>
</nz-form-control>
</nz-form-item>
<!-- Submit Button -->
<nz-form-item>
<nz-form-control [nzSpan]="14" [nzOffset]="6">
<button nz-button nzType="primary">Register</button>
</nz-form-control>
</nz-form-item>
</form>
</div>
</nz-content>
</nz-layout>
Add the following CSS styles to app.component.css
:
.registration-container {
max-width: 800px;
margin: 64px auto;
background: #fff;
padding: 24px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.09);
}
h1 {
text-align: center;
margin-bottom: 24px;
}
[nz-form] {
max-width: 600px;
}
button[nz-button] {
margin-right: 8px;
}
Advanced Features
NgZorro offers many advanced features and components. Here's a brief overview:
1. Theming
You can customize the theme by modifying the variables in your src/theme.less
file (created during installation):
// Override default variables
@primary-color: #1890ff;
@link-color: #1890ff;
@success-color: #52c41a;
@warning-color: #faad14;
@error-color: #f5222d;
2. Internationalization
NgZorro provides built-in support for multiple languages:
// Change to zh_CN (Chinese)
import { NZ_I18N, zh_CN } from 'ng-zorro-antd/i18n';
import { registerLocaleData } from '@angular/common';
import zh from '@angular/common/locales/zh';
registerLocaleData(zh);
@NgModule({
// ...
providers: [
{ provide: NZ_I18N, useValue: zh_CN }
]
})
3. Dynamic Components
NgZorro provides services for creating dynamic components like notifications, modals, and drawers:
import { NzModalService } from 'ng-zorro-antd/modal';
import { NzNotificationService } from 'ng-zorro-antd/notification';
constructor(
private modal: NzModalService,
private notification: NzNotificationService
) {}
showModal(): void {
this.modal.create({
nzTitle: 'Modal Title',
nzContent: 'Modal Content',
nzFooter: [
{
label: 'Cancel',
onClick: () => console.log('Cancel clicked')
},
{
label: 'OK',
type: 'primary',
onClick: () => console.log('OK clicked')
}
]
});
}
showNotification(): void {
this.notification.success(
'Success',
'Operation completed successfully!'
);
}
Summary
In this tutorial, we've covered:
- Installing and configuring NgZorro in an Angular application
- Using basic layout components to structure your application
- Creating a practical form with validation using NgZorro form components
- Exploring advanced features like theming and internationalization
NgZorro provides a rich ecosystem of components that follow the Ant Design principles. With its modular architecture, you can choose only the components you need, reducing bundle size. The library is well-documented and actively maintained, making it an excellent choice for building enterprise-grade Angular applications.
Additional Resources
Exercises
- Create a data table using the NgZorro
nz-table
component with sorting and pagination - Build a dashboard layout with a side navigation menu using
nz-layout
,nz-sider
, andnz-menu
- Implement a search form with auto-complete functionality using NgZorro components
- Create a multi-step form wizard using the
nz-steps
component - Build a responsive card gallery using
nz-card
and CSS Grid/Flexbox
By completing these exercises, you'll gain practical experience with some of NgZorro's most powerful components, setting you on the path to creating sophisticated Angular applications.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)