You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 14升级15后Material Legacy表单主题失效问题排查

升级Angular 14到15后Angular Material Legacy组件出现mat-mdc类及显示异常问题

将Angular从14升级到15后,使用Angular Material的Legacy版本模块,但出现字体与表单显示异常。检查发现HTML中出现了Legacy版本不应有的mat-mdc类,无法定位代码或配置中的具体错误,求排查原因。


Legacy模块导入代码

import { NgModule } from '@angular/core';
import { MatLegacyTabsModule as MatTabsModule } from '@angular/material/legacy-tabs';
import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button';
import { MatLegacyProgressSpinnerModule as MatProgressSpinnerModule } from '@angular/material/legacy-progress-spinner';
import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip';
import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select';
import { MatLegacySlideToggleModule as MatSlideToggleModule } from '@angular/material/legacy-slide-toggle';
import { MatLegacyInputModule as MatInputModule } from '@angular/material/legacy-input';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatLegacySnackBarModule as MatSnackBarModule} from '@angular/material/legacy-snack-bar';
import { MatLegacyRadioModule as MatRadioModule } from '@angular/material/legacy-radio';
import { MatStepperModule } from '@angular/material/stepper';
import { MatLegacyFormFieldModule as MatFormFieldModule } from '@angular/material/legacy-form-field';
import { MatLegacyMenuModule as MatMenuModule } from '@angular/material/legacy-menu';
import { MatDividerModule } from '@angular/material/divider';
import { MatGridListModule } from '@angular/material/grid-list';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatIconModule } from '@angular/material/icon';
import { MAT_LEGACY_DIALOG_DEFAULT_OPTIONS, MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog';
import { MatLegacyAutocompleteModule as MatAutocompleteModule } from '@angular/material/legacy-autocomplete';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatLegacyCardModule as MatCardModule } from '@angular/material/legacy-card';
import { FormlyMaterialModule } from '@ngx-formly/material';
import { MatLegacyTableModule as MatTableModule } from '@angular/material/legacy-table';
import { MatBadgeModule } from '@angular/material/badge';
import { MatLegacyPaginatorModule as MatPaginatorModule } from '@angular/material/legacy-paginator';
import { MatSortModule } from '@angular/material/sort';
import { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatLegacyProgressBarModule as MatProgressBarModule } from '@angular/material/legacy-progress-bar';
import { MatLegacySliderModule as MatSliderModule } from '@angular/material/legacy-slider';
import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox';
import { MomentDateAdapter } from '@angular/material-moment-adapter';
import { LegacyDateAdapter as DateAdapter, MAT_LEGACY_DATE_FORMATS, MAT_LEGACY_DATE_LOCALE } from '@angular/material/legacy-core';
import { MultipleType } from '@Shared/enums/config.enum';

const format = {
    parse: {
        dateInput: 'DD/MM/YYYY'
    },
    display: {
        dateInput: 'DD/MM/YYYY',
        monthYearLabel: 'MMMM YYYY',
        dateA11yLabel: 'MM/DD/YYYY',
        monthYearA11yLabel: 'MMMM YYYY'
    }
};

const modules = [
    MatTabsModule,
    MatSelectModule,
    MatSlideToggleModule,
    MatDatepickerModule,
    MatButtonModule,
    MatInputModule,
    MatSnackBarModule,
    MatProgressSpinnerModule,
    MatTooltipModule,
    MatRadioModule,
    MatStepperModule,
    MatFormFieldModule,
    MatMenuModule,
    MatDividerModule,
    MatGridListModule,
    MatToolbarModule,
    MatIconModule,
    MatAutocompleteModule,
    MatDialogModule,
    MatAutocompleteModule,
    MatExpansionModule,
    MatCardModule,
    FormlyMaterialModule,
    MatTableModule,
    MatPaginatorModule,
    MatBadgeModule,
    MatSortModule,
    MatChipsModule,
    MatButtonToggleModule,
    MatProgressBarModule,
    MatSliderModule,
    MatCheckboxModule
];

@NgModule({
    imports: [
        ...modules
    ],
    exports: [
        ...modules,
    ],
    providers: [
        { provide: MAT_LEGACY_DIALOG_DEFAULT_OPTIONS, useValue: {hasBackdrop: false} },
        { provide: MAT_LEGACY_DATE_LOCALE, useValue: 'fr' },
        { provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_LEGACY_DATE_LOCALE] },
        { provide: MAT_LEGACY_DATE_FORMATS, useValue: format }
    ]
})
export class MaterialModule {
    constructor(private readonly adapter: DateAdapter<MultipleType>) {}

    french() {
        this.adapter.setLocale('fr');
    }

}

style.scss代码

@use '@angular/material' as mat;

@include mat.legacy-core();

$md-test-blue: (50 : #e8eafe, 100 : #c5cbfe, 200 : #9fa9fd, 300 : #7987fc, 400 : #5c6dfb, 500 : #3f53fa, 600 : #394cf9, 700 : #3142f9, 800 : #2939f8, 900 : #1b29f6, A100 : #ffffff, A200 : #f6f7ff, A400 : #c3c7ff, A700 : #aaaeff,
    contrast: (50 : #000000, 100 : #000000, 200 : #000000, 300 : #000000, 400 : #ffffff, 500 : #ffffff, 600 : #ffffff, 700 : #ffffff, 800 : #ffffff, 900 : #ffffff, A100 : #000000, A200 : #000000, A400 : #000000, A700 : #000000)
);
$md-test-red: (50 : #fde5e9, 100 : #fbbdc8, 200 : #f891a4, 300 : #f56580, 400 : #f34464, 500 : #f12349, 600 : #ef1f42, 700 : #ed1a39, 800 : #eb1531, 900 : #e70c21, A100 : #ffffff, A200 : #ffdee0, A400 : #ffabb1, A700 : #ff9199,
contrast: (50 : #000000, 100 : #000000, 200 : #000000, 300 : #000000, 400 : #ffffff, 500 : #ffffff, 600 : #ffffff, 700 : #ffffff, 800 : #ffffff, 900 : #ffffff, A100 : #000000, A200 : #000000, A400 : #000000, A700 : #000000)
);
@import "./mixins.scss";

html, body {
  height: 100%;
  width: 100%;
}
body {
  margin: 0;
}
html {
  font-size: 14px;
}

:root {
  --primary-color: #F12349;
  --accent-color: #3F53FA;
  --nav-color1: rgba(0,0,0,.87);
  --nav-color2: rgba(0,0,0,0.5);
  --white-background: #ffffff;
  --input-border-style: solid;
  --input-border-width: 1px;
  --input-border-untouched-color: #868898;
  --input-border-touched-color: #5264FA;
  --input-border-invalid-color: red;
  --input-border-radius: 4px;
  --input-box-shadow: 0 2px 3px 0 rgba(73,86,92,0.12), 0 0 4px 0 rgba(73,86,92,0.1);

}


$test-font-family: "'sofia-pro', sans-serif";
$typography-levels: mat.define-legacy-typography-config(
  $font-family: "'sofia-pro', sans-serif"
);
$typography: mat.define-legacy-typography-config($test-font-family);

$test-primary: mat.define-palette($md-test-blue);
$test-accent: mat.define-palette($md-test-red);

$theme: mat.define-light-theme((
    color: (
        primary: $rexmat-primary,
        accent: $rexmat-accent
    ),
    typography: mat.define-legacy-typography-config( $font-family: "'sofia-pro', sans-serif"),
));

@include mat.all-legacy-component-themes($theme);

@import './test-theme.scss';

/* You can add global styles to this file, and also import other style files */

angular.json样式配置

"styles": [ "./node_modules/@angular/material/legacy-prebuilt-themes/legacy-indigo-pink.css", "src/styles.scss" ],

排查关键点

  1. 非Legacy模块混入:
    代码中MatDatepickerModule、MatStepperModule、MatDividerModule等多个模块未使用Legacy版本,Angular 15中这些模块默认是MDC实现,会生成mat-mdc类,和Legacy组件样式冲突。需替换为对应Legacy模块,比如MatLegacyDatepickerModule、MatLegacyStepperModule。

  2. Formly模块依赖冲突:
    使用的FormlyMaterialModule默认依赖MDC版本组件,会输出mat-mdc类。需替换为@ngx-formly/material-legacy模块,确保Formly适配Legacy组件。

  3. 主题配置错误:

    • $theme定义中使用了未声明的$rexmat-primary和$rexmat-accent,应改为$test-primary和$test-accent,否则主题配置无效导致样式异常。
    • 同时引入预构建Legacy主题和自定义主题,存在优先级冲突,建议移除legacy-indigo-pink.css的引用,仅保留自定义主题。
  4. 清理构建缓存:
    升级后可能残留旧缓存,执行ng clean后重新构建项目,确保加载最新模块和样式。

内容的提问来源于stack exchange,提问作者testyahoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 10:54:59