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

如何调整代码适配Angular 10?Angular7升级后组件报错修复

修复Angular 10下DateTimeComponent的兼容性问题

我来帮你解决升级到Angular 10后组件失效的问题,咱们针对报错逐一修复:

一、解决"Your minutes - X doesn't match your minutesGap - Y"错误

这个报错是因为新版ngx-material-timepicker新增了分钟值与minutesGap的严格校验,同时你的原代码存在两个问题:

  • 直接修改了传入的date对象,可能导致外部数据被意外篡改
  • 分钟调整逻辑没有处理超过59的情况(比如minutesGap=5,当前分钟58时,计算后会得到60,超出分钟最大值)

修改ngModel setter逻辑

替换原有的set ngModel方法,改为操作日期副本并确保分钟值合法:

set ngModel(date: Moment) {
  if (!date) {
    // 处理空值,避免组件崩溃
    const defaultDate = moment();
    this._ngModel = defaultDate;
    this.timePart = defaultDate.clone();
    this.datePart = defaultDate.clone();
    this.ngModelChange.emit(defaultDate);
    return;
  }

  // 创建日期副本,不修改外部传入的对象
  const clonedDate = date.clone();
  let adjustedMinutes = clonedDate.minutes();
  
  // 计算符合minutesGap的分钟数,确保值在0-59之间
  adjustedMinutes = Math.floor((adjustedMinutes + this.minutesGap - 1) / this.minutesGap) * this.minutesGap;
  if (adjustedMinutes >= 60) {
    adjustedMinutes -= 60;
    clonedDate.add(1, 'hour');
  }
  clonedDate.minutes(adjustedMinutes);

  this.timePart = clonedDate.clone();
  this.datePart = clonedDate.clone();
  this._ngModel = clonedDate;
  this.ngModelChange.emit(clonedDate);
}

二、解决"Cannot read property 'nativeElement' of undefined"错误

这个错误是因为timePart初始值设为空字符串,新版ngx-material-timepicker初始化时需要绑定有效的Moment对象或合规时间字符串,空值会导致组件无法正确获取DOM元素。

修改变量初始值

把timePart和datePart的初始值改为与_ngModel一致的Moment对象:

// 替换原有的空字符串初始值
timePart: Moment = moment();
datePart: Moment = moment();

// 同时在ngOnInit里同步初始值
ngOnInit(): void {
  this.timePart = this._ngModel.clone();
  this.datePart = this._ngModel.clone();
}

三、补充依赖版本适配

Angular 10对依赖库版本有严格要求,你需要确保以下依赖版本匹配:

  1. 升级ngx-material-timepicker到支持Angular 10的版本:
npm install ngx-material-timepicker@5.5.1 --save
  1. 确保@angular/material版本为10.x.x:
npm install @angular/material@10.2.7 --save
  1. 确保moment版本为2.29.x以上:
npm install moment@2.29.4 --save

完整修改后的组件代码

component.ts

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import * as moment from 'moment';
import { Moment } from 'moment';

@Component({
  selector: 'app-date-time',
  templateUrl: './date-time.component.html'
})
export class DateTimeComponent implements OnInit {
  private _ngModel: Moment = moment();
  @Input() datePlaceHolder: string = "Date";
  @Input() timePlaceHolder: string = "Time";
  @Input() timeFormat: number = 24;
  @Input() minutesGap: number = 1;
  timePart: Moment = moment();
  datePart: Moment = moment();

  constructor() { }

  ngOnInit(): void {
    this.timePart = this._ngModel.clone();
    this.datePart = this._ngModel.clone();
  }

  @Input() get ngModel(): Moment {
    return this._ngModel;
  }

  @Output() ngModelChange = new EventEmitter<Moment>();

  set ngModel(date: Moment) {
    if (!date) {
      const defaultDate = moment();
      this._ngModel = defaultDate;
      this.timePart = defaultDate.clone();
      this.datePart = defaultDate.clone();
      this.ngModelChange.emit(defaultDate);
      return;
    }

    const clonedDate = date.clone();
    let adjustedMinutes = clonedDate.minutes();
    
    adjustedMinutes = Math.floor((adjustedMinutes + this.minutesGap - 1) / this.minutesGap) * this.minutesGap;
    if (adjustedMinutes >= 60) {
      adjustedMinutes -= 60;
      clonedDate.add(1, 'hour');
    }
    clonedDate.minutes(adjustedMinutes);

    this.timePart = clonedDate.clone();
    this.datePart = clonedDate.clone();
    this._ngModel = clonedDate;
    this.ngModelChange.emit(clonedDate);
  }

  timePartChange(ev: any) {
    const d = this._ngModel.clone();
    const m = moment(ev, "LT");
    d.hours(m.hours()).minutes(m.minutes());
    this.ngModel = d;
  }

  datePartChange(ev: Moment) {
    const d = this._ngModel.clone();
    ev.hours(d.hours()).minutes(d.minutes());
    this.ngModel = ev;
  }
}

.html(优化绑定语法)

<mat-form-field>
  <input matInput 
         [placeholder]="datePlaceHolder" 
         [matDatepicker]="picker" 
         [(ngModel)]="datePart" 
         (ngModelChange)="datePartChange($event)"/>
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
</mat-form-field><br/>
<mat-form-field>
  <input matInput 
         [placeholder]="timePlaceHolder" 
         [format]="timeFormat" 
         readonly 
         [(ngModel)]="timePart" 
         (ngModelChange)="timePartChange($event)" 
         [ngxTimepicker]="timepicker"/>
  <ngx-material-timepicker-toggle matSuffix [for]="timepicker"></ngx-material-timepicker-toggle>
  <ngx-material-timepicker [minutesGap]="minutesGap" #timepicker></ngx-material-timepicker>
</mat-form-field>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 21:32:59