当ng-model发生变化时,不会触发角度日期过滤器

时间:2017-01-12 13:41:00

标签: javascript angularjs typescript angular-material

我对AngularJS有一个问题,我似乎无法修复,因为我不知道我做错了什么。

版本

AngularJS:1.6.1

角度材料:1.1.1

问题

我正在使用AngularJS组件和过滤器构建datetimepicker。 当我点击显示的日期(通过{{ $ctrl.model | date:'dd-MM-yyyy HH:mm' }}u格式化)时,会打开一个带有自定义日期时间戳的角度材质弹出窗口,并显示一些更改日期的选项。用户单击“确认”后,日期将传递给我的组件(打开对话框的日期),并将新日期分配给模型this.model = newDate.getMomentDate();。在此之后,我希望视图日期也会更新和格式化。但它只是更新而不是格式化。

预期结果: 28-02-2016 00:00u

结果: 2016年2月28日星期日00:00:57 GMT + 0100u

二手组件

为了实现这个功能,我使用了一些角度组件:

  • 我的应用代码中的一个组件(time.component.ts)
  • 显示内容(time.html)的HTMl文件
  • 将时间({{ $ctrl.model | date:'dd-MM-yyyy HH:mm' }}u)转换为time.html并管理对话框(datetimepicker.ts)的组件
  • 带有模型的HTML文件 - 转换为time.html(datetimepicker.html)
  • 管理对话框的控制器(datetimepickerdialog.controller.ts)
  • 带有对话框的html文件(datetimedialog.html)
  • 保存对话框信息的模型(DateTimePickerModel.ts)

A model that describes the connections between the classes

为time.html

<date-time-picker title="pick your time"
                  model="$ctrl.time.meeting">
</date-time-picker>

datetimepicker.component.ts

绑定

bindings: {
    model: "=",  //Angular ng-model is automatically updated this way
    title: "@?"
},
transclude: true,
controller: DateTimePickerController

Picker回调

showPicker(): void {
     this.$mdDialog.show(this.datePickerDialog).then((newDate: DateTimePickerModel) => {
         this.model =  newDate.getMomentDate();
     }, function () {
         //Cancel
      });
}

datepicker.html

<md-button ng-click="$ctrl.showPicker()" aria-label="open dialog">
    {{ $ctrl.model | date:'dd-MM-yyyy HH:mm' }}u
</md-button>

DateTimePickerModel.ts

export class DateTimePickerModel {
    constructor(public day: string,
                public month: string,
                public year: string,
                public hour: string,
                public minute: string,
                public second: string) {
        }

     /**
      * Returns the number of days of the month
      * @return number
      */
      getDaysInMonth(): number {
         return moment(this.year + '-' + this.month).daysInMonth();
      }

     /**
      * Formats the property values to a moment date
      * @return {Moment}
      */
     getMomentDate(): Moment {
        return moment(
            this.year + "-" + this.month + "-" + this.day + "T" +
            this.hour + ":" + this.minute + ":" + this.second,
            moment.ISO_8601);
      }
}

我遗漏了datetimepickerdialog.controller.ts,因为DateTimePickerModel的一个实例被传递给控制器​​,它与2路绑定或ng模型无关(我不期望有控制器中可能导致问题的任何事情。)

我试过

我尝试使用$scope.$apply() bercause我期望Angular没有看到变化。但是使用$scope.$apply()我收到错误'Digest is already running'

我还尝试用单向绑定("=")替换组件("<")的双向绑定,并将日期返回到time.component.ts中功能。在time.component.ts中,我会使用新日期更新ng-model。然而,这给了我相同的结果。

我找到了一个有效的workarround,但这违背了Angular过滤器的全部目的。为此,我通过get方法操作控制器内的模型。这也适用于发现更改时的更新。但是我通过视图操作来污染我的控制器。 (我不建议这样做!)

datetimepicker.component.ts

/**
 * Formats the model and return the formatted version.
 * - An Angular filter didn't work. It was somehow only called once, if the model changed it didn't format it -
 * @return {string}
 */
get formattedModel(): string {
    return moment(this.model).format('DD-MM-YYYY HH:mm');
}

datetimepicker.html

<md-button ng-click="$ctrl.showPicker()" aria-label="open dialog">
    {{ $ctrl.formattedModel }}u
</md-button>

我想不出任何其他选项,因为Angular会在每个$digest周期运行页面上的每个过滤器,因为它不知道ng-model对哪些过滤器有效。 (每次更改都可能对页面产生影响,因此每个周期都需要重新评估每个过滤器。)

任何可以帮助我的人?​​

1 个答案:

答案 0 :(得分:0)

这很一般,因为你的问题非常详细。

首先,Angular 1.6尚未与Material 1.1.1兼容,因此我首先尝试使用Angular 1.5,并查看这是否无法解决您的问题。 https://github.com/angular/material/issues/10111

其次,如果您正在制作使用模型的组件,请考虑直接遵循实际使用ng-model的模式,如下所述:https://docs.angularjs.org/api/ng/type/ngModel.NgModelController

第三,为什么不将特定问题与测试隔离开来,然后你就会知道它是组件中的某些东西还是你使用模态的方式。例如,用材料日期时间选择器替换时间选择器组件。如果这样可行,那么您就知道问题出在组件中并且与模态无关。