Kendo UI for Angular 通过 ngIf 加载模块时,日期选择器本地化不起作用
Kendo UI for Angular Datepicker Localization doesn't work when module is loaded via ngIf
此问题与 Angular 6 应用程序有关,该应用程序使用 Kendo UI for Angular。
我最近一直在努力使 Kendo 的 DatePicker 和 TimePicker 组件的动态 globalization/localization 正常工作。在网站右上角的 header 中,有一个语言下拉菜单,用户可以动态更改网站的 language/locale。我想实现一种动态更新 Kendo 的日期选择器和时间选择器组件的方法,以根据用户从下拉列表中选择的语言环境自动翻译文本并更新 Kendo 组件的日期时间格式。
所以我采用了 Kendo 的 DatePicker 和 TimePicker 组件并将它们包装在它们自己的名为 "DatepickerWrapperModule" 的模块中。只要这个模块被急切地加载,一切都可以正常工作(即模块和相应的组件不会动态注入到页面中)。
但是,如果通过 *ngIf 指令将模块和相应的组件动态加载到页面中,则会破坏我设置的动态本地化。
我假设这是由于模块被延迟加载并因此创建了它所依赖的服务的新实例???但是在研究并尝试了许多不同的方法来让它工作之后,到目前为止我一直没有成功。有没有办法让这种类型的 Kendo UI DatePicker 动态本地化与通过 *ngIf 动态加载的 modules/components 一起工作???
通常情况下,我会提供所有相关的代码示例,但它们太大太复杂,无法在本题中简明扼要地展示。一般来说,有:
- AppModule
- 一个SharedModule
- 和DatepickerWrapperModule
AppModule 使用 forRoot() 方法在 imports[] 数组中导入 SharedModule。
然后SharedModule在imports[]数组中导入DatepickerWrapperModule,同样在exports[]数组中导出。在 imports[] 数组中,DatepickerWrapperModule 使用了 forRoot() 方法。
DatepickerWrapperModule 然后实现 DatePickerWrapper 组件,其中包含对 Kendo DatePicker 组件的实际引用。
此外,在 DatepickerWrapperModule 的构造函数中,我使用 @Optional() 和 @SkipSelf() 构造函数参数装饰器来查看 DatepickerWrapperModule 是否被加载了两次,并通过一些简单的 console.log 语句,我确认它确实被初始化并加载了两次(一次是在整个 app/site 的初始加载期间,另一次是在特定页面和正在考虑的特定组件上满足 *ngIf 条件时。
我想弄清楚如何获取通过 *ngIf 条件加载的 module/component 以使用已作为整个应用程序的一部分加载的 DatepickerWrapperModule 实例,而不是创建新实例当满足 *ngIf 条件时将组件动态添加到 DOM。
提前致谢!
现在我终于解决了我的问题,我想提供我自己为我解决的问题的答案,以防其他人将来遇到同样的问题。
作为参考,请在此处查看最终解决我的问题的推荐方法:
https://github.com/telerik/kendo-angular/issues/1455#issuecomment-405247258
基本上,我的问题与延迟加载模块在通过路由加载时的工作方式有关,例如:
{
path: 'logistics',
canActivate: [AuthGuardService],
appData: 'APPDATA_LOGISTICS',
loadChildren: './logistics/+logistics/logistics.module#LogisticsModule'
}
在我的 AppModule 的 providers[] 数组中,我指定了 LOCALE_ID、CldrIntlService 和 国际服务如下:
providers: [
CldrIntlService,
{
provide: IntlService,
useExisting: CldrIntlService
},
{
provide: LOCALE_ID,
useValue: 'en-US'
}
]
这将为在 AppModule 或 AppModule 的某些子项中导入的预加载模块提供这些服务,但对于不是由 AppModule 导入的延迟加载模块或 AppModule 的直接子项,它将创建这些的新实例服务。
因此,根据上面的 link,一旦我在延迟加载的 LogisticsModule 中指定了适当的提供程序,Kendo DatePicker 和 TimePicker 组件的动态本地化又开始按预期工作。
这是解决我的问题的 LogisticsModule 中 providers[] 数组的相关部分:
providers: [
.
.
.
{
provide: IntlService,
useExisting: CldrIntlService
}
.
.
.
]
这告诉 LogisticsModule 使用已经在 AppModule 中创建(提供)的服务实例(而不是在延迟加载模块时创建新的服务实例)。
此问题与 Angular 6 应用程序有关,该应用程序使用 Kendo UI for Angular。
我最近一直在努力使 Kendo 的 DatePicker 和 TimePicker 组件的动态 globalization/localization 正常工作。在网站右上角的 header 中,有一个语言下拉菜单,用户可以动态更改网站的 language/locale。我想实现一种动态更新 Kendo 的日期选择器和时间选择器组件的方法,以根据用户从下拉列表中选择的语言环境自动翻译文本并更新 Kendo 组件的日期时间格式。
所以我采用了 Kendo 的 DatePicker 和 TimePicker 组件并将它们包装在它们自己的名为 "DatepickerWrapperModule" 的模块中。只要这个模块被急切地加载,一切都可以正常工作(即模块和相应的组件不会动态注入到页面中)。
但是,如果通过 *ngIf 指令将模块和相应的组件动态加载到页面中,则会破坏我设置的动态本地化。
我假设这是由于模块被延迟加载并因此创建了它所依赖的服务的新实例???但是在研究并尝试了许多不同的方法来让它工作之后,到目前为止我一直没有成功。有没有办法让这种类型的 Kendo UI DatePicker 动态本地化与通过 *ngIf 动态加载的 modules/components 一起工作???
通常情况下,我会提供所有相关的代码示例,但它们太大太复杂,无法在本题中简明扼要地展示。一般来说,有:
- AppModule
- 一个SharedModule
- 和DatepickerWrapperModule
AppModule 使用 forRoot() 方法在 imports[] 数组中导入 SharedModule。
然后SharedModule在imports[]数组中导入DatepickerWrapperModule,同样在exports[]数组中导出。在 imports[] 数组中,DatepickerWrapperModule 使用了 forRoot() 方法。
DatepickerWrapperModule 然后实现 DatePickerWrapper 组件,其中包含对 Kendo DatePicker 组件的实际引用。
此外,在 DatepickerWrapperModule 的构造函数中,我使用 @Optional() 和 @SkipSelf() 构造函数参数装饰器来查看 DatepickerWrapperModule 是否被加载了两次,并通过一些简单的 console.log 语句,我确认它确实被初始化并加载了两次(一次是在整个 app/site 的初始加载期间,另一次是在特定页面和正在考虑的特定组件上满足 *ngIf 条件时。
我想弄清楚如何获取通过 *ngIf 条件加载的 module/component 以使用已作为整个应用程序的一部分加载的 DatepickerWrapperModule 实例,而不是创建新实例当满足 *ngIf 条件时将组件动态添加到 DOM。
提前致谢!
现在我终于解决了我的问题,我想提供我自己为我解决的问题的答案,以防其他人将来遇到同样的问题。
作为参考,请在此处查看最终解决我的问题的推荐方法: https://github.com/telerik/kendo-angular/issues/1455#issuecomment-405247258
基本上,我的问题与延迟加载模块在通过路由加载时的工作方式有关,例如:
{
path: 'logistics',
canActivate: [AuthGuardService],
appData: 'APPDATA_LOGISTICS',
loadChildren: './logistics/+logistics/logistics.module#LogisticsModule'
}
在我的 AppModule 的 providers[] 数组中,我指定了 LOCALE_ID、CldrIntlService 和 国际服务如下:
providers: [
CldrIntlService,
{
provide: IntlService,
useExisting: CldrIntlService
},
{
provide: LOCALE_ID,
useValue: 'en-US'
}
]
这将为在 AppModule 或 AppModule 的某些子项中导入的预加载模块提供这些服务,但对于不是由 AppModule 导入的延迟加载模块或 AppModule 的直接子项,它将创建这些的新实例服务。
因此,根据上面的 link,一旦我在延迟加载的 LogisticsModule 中指定了适当的提供程序,Kendo DatePicker 和 TimePicker 组件的动态本地化又开始按预期工作。
这是解决我的问题的 LogisticsModule 中 providers[] 数组的相关部分:
providers: [
.
.
.
{
provide: IntlService,
useExisting: CldrIntlService
}
.
.
.
]
这告诉 LogisticsModule 使用已经在 AppModule 中创建(提供)的服务实例(而不是在延迟加载模块时创建新的服务实例)。