【发布时间】:2017-05-27 15:38:51
【问题描述】:
我的 AngularJS 有一个问题,我似乎无法解决,因为我不知道自己做错了什么。
版本
AngularJS:1.6.1
角材料:1.1.1
问题
我正在使用 AngularJS 组件和过滤器构建一个日期时间选择器。
当我单击显示的日期(通过{{ $ctrl.model | date:'dd-MM-yyyy HH:mm' }}u 格式化)时,会打开一个带有自定义日期时间选择器的 Angular-material 弹出窗口,并显示一些更改日期的选项。用户单击“确认”后,日期将传递给我的组件(打开对话框的组件)并将新日期分配给模型this.model = newDate.getMomentDate();。在此之后,我希望查看日期也将被更新和格式化。然而它只是更新而不是格式化。
预期结果: 28-02-2016 00:00u
结果: 2016 年 2 月 28 日星期日 00:00:57 GMT+0100u
使用过的组件
为了实现这个功能,我使用了一些角度组件:
- 我的应用代码中的一个组件 (time.component.ts)
- 显示内容的 HTMl 文件 (time.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)
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
选择器回调
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-way-binding 或 ng-model 无关(我不希望有该控制器中可能导致问题的任何内容)。
我试过了
我尝试使用$scope.$apply(),因为我预计 Angular 没有看到变化。但是使用$scope.$apply() 我得到错误'Digest is already running'。
我还尝试用单向绑定 ("<") 替换组件的双向绑定 ("="),并使用函数将日期返回到 time.component.ts。然后,在time.component.ts 中,我将使用新日期更新ng-model。然而,这给了我同样的结果。
我找到了一个可行的解决方法,但这违背了 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 对哪些过滤器有效。 (每个更改都可能对页面产生影响,因此需要重新评估每个过滤器,每个周期)。
谁能帮帮我?
【问题讨论】:
-
虽然很多人未能提供足够详细的信息来获得他们需要的帮助,但您已经走到了另一个极端。您提供了太多信息,我没有时间阅读或使用所有信息。创建一个 plunker 并链接到它。
-
我同意你的观点,我应该使用 plunker。但问题是我使用的是 TypeScript 并且无法运行。我需要使用 javascript,但这是已编译且非常不可读的。关于我应该如何创建它的任何建议?
-
Plunker 支持 1.5x + TS
标签: javascript angularjs typescript angular-material