Skip to content

docs(datepicker): need better guidance for use with lazy loaded modules #18970

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
lubowiecki opened this issue Apr 2, 2020 · 11 comments
Open
Labels
area: material/datepicker docs This issue is related to documentation P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent

Comments

@lubowiecki
Copy link

lubowiecki commented Apr 2, 2020

Reproduction

I created here MyIntl class and I set there only text for calendar open button.
https://angular-material-datepicker-intl.stackblitz.io
https://stackblitz.com/edit/angular-material-datepicker-intl

Steps to reproduce:

  1. If you check first calendar button it has aria-label="test" so it works. It works also for second calendar that is in first lazy loadad module
  2. But if you click link 'lazy-loaded' and check button for 'other lazy' calendar it's aria-label is default 'Open calendar'
  3. It starts to work only if I provide again my custom MyIntl class in OtherLazyModule (commented line)

Expected Behavior

I expected that if I provide my custom implementation of MatDatepickerIntl in AppModule it will work also for all lazy loaded modules.
For example MatPaginator works that way.

Actual Behavior

Custom implementation of MatDatepickerIntl is not provided in lazy loaded modules

Environment

  • Angular: 9
  • CDK/Material: 9
  • Browser(s): Chrome
  • Operating System (e.g. Windows, macOS, Ubuntu): Windows 10
@lubowiecki lubowiecki added the needs triage This issue needs to be triaged by the team label Apr 2, 2020
@trik
Copy link
Contributor

trik commented Apr 7, 2020

i guess it's not a datepicker intl bug, lazy loaded modules have their own injector, you do need to override the intl provider
https://angular.io/guide/providers#limiting-provider-scope-by-lazy-loading-modules

@lubowiecki
Copy link
Author

I updated my description with link to source on stackblitz. You can see there that I provide my MatDatepickerIntl. I think that problem is in implementation of https://github.com/angular/components/blob/master/src/material/datepicker/datepicker-module.ts
on
providers: [ MatDatepickerIntl, MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY_PROVIDER, ]
which don't let MatDatepickerIntl to be overwritten

@trik
Copy link
Contributor

trik commented Apr 7, 2020

ok i got the point, but the problem is the scope of the provider override. since lazy modules have different injectors, the override has no effect.. so you're proposing to change the MatDatepickerIntl to an injection token with a default value

@mmalerba
Copy link
Contributor

I do think the material.angular.io docs need to do a better job discussing how to use the datepicker with lazy loaded modules. I'll update the title and use this issue to track that

@mmalerba mmalerba changed the title bug([datepicker]): Custom DatepickerIntl don't work in lazy loaded modules docs(datepicker): need better guidance for use with lazy loaded modules May 29, 2020
@mmalerba mmalerba added area: material/datepicker docs This issue is related to documentation P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent and removed needs triage This issue needs to be triaged by the team labels May 29, 2020
@gtamas
Copy link

gtamas commented Aug 13, 2020

@mmalerba
@trik
Any news on this?
When will you update the docs or provide a fix? Right now, using MatDatepickerIntl with lazy loaded modules is pretty hard and requires a lot of extra work.

@mercury83
Copy link

If MatDatepickerIntl was meant to be a singleton than IMO this is a bug. It already provides itself in the root injector, I think it shouldn't be listed in MatDatepickerModule's providers.

@Totati
Copy link
Contributor

Totati commented Aug 17, 2020

If MatDatepickerIntl was meant to be a singleton than IMO this is a bug. It already provides itself in the root injector, I think it shouldn't be listed in MatDatepickerModule's providers.

This could be a solution, however Paginator, Sort and Stepper are using a different approach, and that works properly.

@marcinmajkowski
Copy link

Current implementation guarantees that lazy loaded module behaves the same, no matter in what application it is imported. I like the idea, although I do not think that there are many real world scenarios for this level of reusability. I agree this should be documented bettter and I agree this seem inconsistent with other Material components.

I see two solutions that can be used in applications:

  • create analogous factory provider to one in Paginator, Sort and Stepper on your own (the one using parent provided instance) and provide it in your lazy loaded module.
  • create your CustomDatepickerModule (re-exporting the Material one) with your custom Intl in its providers array and use it throughout your application. SharedModule / CustomMaterialModule would work just as well in this case.

@hiepxanh
Copy link

Angular 14 release with standalone component can solve the problem, I think

@hiepxanh
Copy link

hiepxanh commented May 25, 2022

hi I created deep insight about datepicker and standalone component in this post https://dev.to/hiepxanh/angular-14-standalone-component-help-reduce-bundle-size-and-the-story-behind-you-may-not-know-1f44
you can see my example, we create standalone compnent and lazy import it, it can be lazyload now:

https://gist.github.com/hiepxanh/1306f075b2478e62133473d8cfaca537

@ViewChild('datepickerTemplate', { read: ViewContainerRef }) datepickerTemplate!: ViewContainerRef;
  constructor(private fb: FormBuilder) {}

  async loadComponent() {
    const { DatepickerAtom } = await import('../../atoms/datepicker/datepicker.atom');
    const componentRef = this.datepickerTemplate.createComponent(DatepickerAtom);
    const dobControl = this.optionalForm.get('dob');
    if (dobControl) {
      componentRef.instance.dob = dobControl;
    }
  }

  ngOnInit(): void {
    this.loadComponent();
  }

@lubowiecki
Copy link
Author

In angular 15 it still doesn't work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: material/datepicker docs This issue is related to documentation P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Projects
None yet
Development

No branches or pull requests

8 participants