Skip to main content
This guide provides detailed migration instructions for upgrading Angular Material across major versions.
Always migrate one major version at a time for the smoothest upgrade experience.

Migrating to v21

1

Prerequisites

Ensure you’re on the latest v20 release:
ng update @angular/core@20 @angular/cli@20
ng update @angular/material@20
Verify your application works correctly before proceeding.
2

Update Angular and Material

Run the Angular update command:
ng update @angular/core@21 @angular/cli@21 @angular/material@21
This command will:
  • Update package versions
  • Run automated migrations
  • Update import statements
  • Fix deprecated API usage
3

Update Portal Directives

Replace old portal directive names:TypeScript:
// Before
import { TemplatePortalDirective, PortalHostDirective } from '@angular/cdk/portal';

// After
import { CdkPortal, CdkPortalOutlet } from '@angular/cdk/portal';
Templates:
<!-- Before -->
<ng-template portal>Content</ng-template>
<ng-template portalHost></ng-template>

<!-- After -->
<ng-template cdkPortal>Content</ng-template>
<ng-template cdkPortalOutlet></ng-template>
4

Update SCSS Variables

Update z-index and overlay variables:
// Before
@use '@angular/material' as mat;

.custom-overlay {
  z-index: mat.$z-index-overlay;
}

.backdrop {
  background: mat.$dark-backdrop-background;
}

// After
.custom-overlay {
  z-index: mat.$overlay-z-index;
}

.backdrop {
  background: mat.$overlay-backdrop-color;
}
5

Remove Animation Imports

Remove imports of animation constants:
// Remove these imports
import { matDialogAnimations } from '@angular/material/dialog';
import { matMenuAnimations } from '@angular/material/menu';
// etc.

// Use CSS/SCSS for animation customization instead
If you were using these for custom animations:
.mat-mdc-dialog-container {
  animation-duration: 300ms;
  animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1);
}
6

Remove MatCommonModule

Remove MatCommonModule from imports:
// Before
import { MatCommonModule } from '@angular/material/core';

@NgModule({
  imports: [MatCommonModule, MatButtonModule]
})

// After - just import specific modules
@NgModule({
  imports: [MatButtonModule]
})
7

Test your application

Run your test suite and manually test critical paths:
ng test
ng e2e
ng serve

Migrating to v20

1

Update from v19

ng update @angular/core@20 @angular/cli@20
ng update @angular/material@20
2

Update TypeScript

Ensure you’re using TypeScript 5.4 or later:
// package.json
{
  "devDependencies": {
    "typescript": "~5.4.0"
  }
}
3

Standalone Components

Consider migrating to standalone components:
// Before
@NgModule({
  declarations: [MyComponent],
  imports: [MatButtonModule]
})
export class MyModule {}

// After
@Component({
  standalone: true,
  imports: [MatButtonModule],
  // ...
})
export class MyComponent {}

Migrating to v19 (Material Design 3)

Version 19 introduced Material Design 3, which includes visual changes to all components.
1

Update packages

ng update @angular/core@19 @angular/cli@19
ng update @angular/material@19
2

Update theme configuration

Replace M2 theme API with M3:
@use '@angular/material' as mat;

// Before (M2)
$theme: mat.m2-define-light-theme((
  color: (
    primary: mat.m2-define-palette(mat.$indigo-palette),
    accent: mat.m2-define-palette(mat.$pink-palette),
  )
));

// After (M3)
$theme: mat.define-theme((
  color: (
    theme-type: light,
    primary: mat.$violet-palette,
  ),
));

html {
  @include mat.all-component-themes($theme);
}
3

Update density

M3 uses a simpler density API:
$theme: mat.define-theme((
  density: (
    scale: -1  // More compact
  )
));
4

Test visual changes

All components will look different. Test thoroughly:
  • Component spacing and sizing
  • Colors in light and dark modes
  • Custom overrides

Migrating from AngularJS Material

Migrating from AngularJS Material to Angular Material requires a complete rewrite.
1

Set up Angular

Create a new Angular application:
ng new my-app
cd my-app
ng add @angular/material
2

Map components

Most AngularJS Material components have Angular equivalents:
AngularJSAngular
<md-button><button mat-button>
<md-input-container><mat-form-field>
<md-select><mat-select>
<md-dialog>MatDialog service
<md-sidenav><mat-sidenav>
3

Update directive syntax

<!-- AngularJS -->
<md-button ng-click="ctrl.submit()">
  Submit
</md-button>

<!-- Angular -->
<button mat-button (click)="submit()">
  Submit
</button>
4

Migrate services

Services work differently in Angular:
// AngularJS
angular.module('app').controller('MyCtrl', function($mdDialog) {
  $mdDialog.show({
    template: '<div>Hello</div>'
  });
});

// Angular
import { MatDialog } from '@angular/material/dialog';

@Component({...})
export class MyComponent {
  constructor(private dialog: MatDialog) {}

  openDialog() {
    this.dialog.open(MyDialogComponent);
  }
}
5

Migrate incrementally

Consider using ngUpgrade to run both frameworks side-by-side during migration.

Common Migration Patterns

Updating Module Imports

import { MatLegacyButtonModule } from '@angular/material/legacy-button';

@NgModule({
  imports: [MatLegacyButtonModule]
})

Updating Component Selectors

<mat-form-field appearance="legacy">
  <input matInput>
</mat-form-field>

Updating Theme Mixins

@import '~@angular/material/theming';

@include mat-core();
$primary: mat-palette($mat-indigo);

Troubleshooting

Clear cache and reinstall:
rm -rf node_modules package-lock.json
npm install
Clear Angular cache:
ng cache clean
Check @use syntax:
// Correct
@use '@angular/material' as mat;

// Incorrect
@import '@angular/material/theming';
Update test imports:
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatButtonHarness } from '@angular/material/button/testing';
Use harnesses instead of internals:
// Instead of
const button = fixture.nativeElement.querySelector('.mat-button');

// Use
const button = await loader.getHarness(MatButtonHarness);
Update TypeScript version:
npm install -D typescript@latest
Enable strict mode gradually:
// tsconfig.json
{
  "compilerOptions": {
    "strict": false,  // Enable gradually
    "strictNullChecks": true
  }
}

Automated Migrations

Angular CLI provides automated migrations:
# See available migrations
ng update @angular/material --migrate-only

# Run specific migration
ng update @angular/material --migrate-only --from=19 --to=20
Automated migrations handle most common cases but always review changes.

Resources

Breaking Changes

Complete list of breaking changes

Angular Update Guide

Interactive update guide

GitHub Releases

Release notes and changelogs

Community Forum

Ask migration questions

Build docs developers (and LLMs) love