Nem bízol a kollégáidban? Akkor valamit rosszul csinálsz!
bizalom vezetokent
2023-05-03
Dolgok, amikről a programozók azt hiszik, hogy tudják, de tévednek
programozoi-tevhitek-falsehoods
2023-04-08
A programozóktól meg kell szabadulni
chatgpt no-code low-code
2023-01-22
Miért fontosak a személyes adatok egyáltalán?
privacyaware, privacy
2023-01-07
Egy tanmese a szerény, de tehetséges informatikusról, akit én csak Gézának hívok
privacyaware, privacy
2023-01-02
Beskatulyáznád magad egy termékkel? Gondold át még egyszer!
learning, vendorlockin, risky
2022-12-11
Rekrúterekről és állásajánlatokról
bérsáv, recruiter, relevancia
2022-10-30
"A hídon akkor kell átmenni, amikor odaérünk."​ - YAGNI
yagni, pagni
2022-10-17
"A lényeg, hogy a munka készen legyen!"
agile, estimation, becsles, scrum, home office
2022-08-20
Munka vs. hivatás, a klasszikus dilemma
hr, hobbi, munka, egyensuly, hivatas
2022-07-18
Miért nem fogok nálatok technikai interjún részt venni?
technikai interju, hr, recruit, leet code, coding challenge, take home challenge
2022-07-04
"Hogyan építsek kapcsolati tőkét, ha karriert szeretnék váltani?"
linkedin, tippek, trukkok
2022-06-10
Junior/Medior/Senior, hogyan mérjük?
junior, medior, senior, hr, grade, level, experience
2022-05-09
11 tipp frontendeseknek, hogyan tegyék hatékonyabbá a munkájukat
frondend, vscode, angular
2021-10-31
Motion zoom - mozgás alapú képrekonstrukció
#52het
2021-06-01
Gesture Launcher
#52het
2021-05-31
CellEvent, első Android alkalmazásom
#52het
2021-05-19
Notebookcheck, azaz hogyan válasszuk ki a legjobb ár-érték arányú eszközt
#52het
2021-05-18
Torrent multiplexer
#52het
2021-05-17
Process watcher, logger
#52het
2021-05-05
Lazy loading material dialog content
lazy loading, angular, material, dialog
2020-12-28
Runtime configuration loading in Angular
angular, runtime, configuration, settings, environment, production
2020-03-29
How to start an Angular project?
angular
2020-03-11
Az 52 hét projekt
#52het
2020-01-01
Akkutöltöttség-jelző
#52het
2020-01-01
NetClub - Kollégiumi internetszolgáltató
#52het
2019-12-31
DeeJayy - Lost Terminal
#52het
2019-12-31
Counter Strike monitor
#52het
2019-12-31
Kollégiumi CS bajnokság 2005
#52het
2019-12-31
Mozgásérzékelős képrögzítő, Camera Capture
#52het
2019-12-30
Többszörös host pingelő
#52het
2019-12-30
Sávszélesség mérő, tesztelő
#52het
2019-12-30
Generáljunk hamis adatokat
#52het
2019-12-30
SQL lekérdezések parancssorból, odbc-vel
#52het
2019-12-30
Nonogram generátor (aka. "Fesse feketére")
#52het
2019-12-30
Egyedi chat alkalmazás, kliens és szerver
#52het
2019-12-29
FontSelector - betűtípusválasztó / font preview
#52het
2019-12-28
Saját hálózati kommunikációs segédszoftver - sox
#52het
2019-12-28
Csoportos e-mail küldő szoftver Delphiben
#52het
2019-12-28
Universal Api caller module for Angular 7-9 With NGRX state management
Ngrx, API, Effects, HttpClient
2019-07-02
A leghosszabb projekt
#52het
2019-04-19
Legelső kioszk projektem: Stari Sör Jukebox
#52het
2019-02-28
BPM számláló
#52het
2018-11-01
Assembly féléves beadandók
#52het
2018-11-01
Chatbot before it was cool
#52het
2018-10-30
StartX - Cseréljük ki a windows tálcáját és a Start menüt
#52het
2018-10-28
What? - fájltípus azonosító
#52het
2018-10-27
Transport Tycoon DirectX
#52het
2018-10-26
Diff - fájlösszehasonlító
#52het
2018-10-26
De Facto - Szoftverfelügyelet
#52het
2018-10-25
CD és DVD katalogizáló
#52het
2018-09-24
MP3 segédeszközök
#52het
2018-09-24
Keylogger - azaz billentyűleütés-figyelő és naplózó alkalmazás
#52het
2018-08-29
Az örök projekt: személyes weboldal és blog
#52het
2018-08-14
Szógyakorló nyelvtanuláshoz
#52het
2018-08-13
Warzone 2100 mentett játék szerkesztő
#52het
2018-08-13
Rejtett Windows-beállításokat konfiguráló program: TweakMaster
#52het
2018-08-13
A DrótPostaGalamb levelezőprogram adatfájljainak dekódolása
#52het
2018-08-13
Privacy jegyzet
2018-07-30
Egy éve ilyenkor
2018-07-25
The Matrix - konzol szimuláció
#52het
2018-07-13
Kakaóreceptkönyv
kakaó
2018-06-29
Crackelés!
#52het
2018-06-22
A K.I.T.T. challenge
#52het
2018-06-18
Doom 2 botokkal
#52het
2018-06-16
Römi játék Delphiben
#52het
2018-06-09
MeetsCow & DeeJayy - Intro
#52het
2018-06-09
Direct viewer - bitmap megjelenítő
#52het
2018-06-09
bazMAG
#52het
2018-06-09
Console Vision - Konzolos ablakkezelő Delphiben
#52het
2018-05-01
Quake 2 egy floppyn
#52het
2018-04-20
Játék-kitömörítők
#52het
2018-04-12
Tetszőleges program elrejtése Windows tálcáról
#52het
2018-04-05
Személyre szabás
#52het
2018-03-28
A year with Angular 5, 6 - Angular 2018
#angular5 #angular #resources #articles
2018-03-16
Az ikon evolúciója
#52het
2018-03-14
Betűtípusok
#52het
2018-03-04
Billentyűzet-gyakorló
#52het
2018-02-28
Zenél is a DeeJayy?
#52het
2018-02-22
Térképrajzoló az Ascii 3D labirintushoz
#52het
2018-02-19
Ascii 3D labyrinth
#52het
2018-02-14
52 hét - 52 projekt, avagy #eletem
#52het
2018-02-14
Dockerezzünk virtualizált környezetben!
docker, xen, ubuntu
2017-11-12
A cloud-initramfs-copymods hatásai paravirtualizált környezetben
ubuntu, xen, copymods, docker, docker-ce, docker.io
2017-11-11
Virtualizáljunk Xen 4.6-tal Ubuntu 16-on (Xenial)
ubuntu, xen, virtualizálás, hypervisor, debootstrap
2017-11-04
Álláskeresésem története
álláskeresés, it, fejvadászok, linkedin, job
2017-10-24
FAR Manager competitors
far manager, file managers
2010-01-01
Blog
blog
2001-01-02

Lazy loading material dialog/modal content

TL;DR version

Step 1:

  public showDialog(): void {
    import('src/app/feature/my-dialog/my-dialog.module')
      .then((importedModule) => importedModule.MyDialogModule)
      .then((moduleType) => this.dialog.open(moduleType.components.MyDialogContentComponent))
  }

Step 2:

export class MyDialogModule {
  public static components = {
    MyDialogContentComponent,
  };
}

You are done, read further for explanation.

Show a material dialog in a traditional way

Let's start with an Angular project prepared with material. You can check this tutorial or just simply clone this repo, up to you.

Create a module with the dialog's content

ng g m my-dialog
cd my-dialog
ng g c my-dialog-content
<button (click)="showDialog()">
  Show me
</button>
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';

import { MyDialogContentComponent } from './feature/my-dialog/my-dialog-content/my-dialog-content.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {
  constructor(private dialog: MatDialog) {}

  public showDialog(): void {
    this.dialog.open(MyDialogContentComponent); // <- magic
  }
}

(don't forget to add MatDialogModule and MyDialogModule to the module you try to open this dialog)

This solution should work like a charm:

However, this is loaded with the main bundle which means your clients will download the code related to the dialog regardless of they open it or not.

Check the output of ng build --prod command, you can't observe your MyDialog module's chunk, so it is a part of the main chunk.
Protip: always check production build, you can skip some rounds of googling.

chunk {1} main.5ee3e8e18e48590dcb03.js (main) 5.1 kB [initial] [rendered]

Lazy loading to help

With lazy loaded modules you can achieve smaller initial bundle size and you can download the necessary code on demand. But maintain the balance: downloading a small piece of code may be more expensive depending on the circumstances (e.g. with high latency connection, one bigger bundle is usually smarter then a dozen of small ones), so watch your step.

Lazy load needs modules

You can say that components can also be downloaded lazy, but if you need services, state management, etc. then a component may not be enough: you need bundle together different purpose code into a module.

Let's make our existing My-Dialog module to load lazy.

First: you need to get rid of every reference which calls into MyDialogModule or any of it's parts.

E.g. check these:

  public showDialog(): void {
    this.dialog.open(MyDialogContentComponent);
  }

...

@NgModule({
  declarations: [AppComponent],
  imports: [
    MyDialogModule,

These references wire the components/modules into your main bundle. But if you are not using these object names*, it will tell webpack that a module can be separately created in it's own chunk (check code splitting and tree-shaking).

*you can only use as variable type, because ts->js transpiling will only consider the typedef of these objects at build time

Load the module and display the dialog lazy

Remove all imports from you code which mentions any part of MyDialogModule or it's components and change showDialog() method as follows:

  public showDialog(): void {
    import('src/app/feature/my-dialog/my-dialog.module')
      .then((importedModule) => importedModule.MyDialogModule)
      .then((moduleType) => this.dialog.open(moduleType.components.MyDialogContentComponent))
  }

All right, what's happening here?

The import() command should be familiar from lazy loading route modules. After importing the file (which will initiate a network request to the corresponding js chunk, check the network tab in browser dev tools), we need to select the module from that chunk. Then, simply open the dialog. But what is this moduleType.components? There is no such property in a module! You need to add it manually, like this:

export class MyDialogModule {
  public static components = {
    MyDialogContentComponent,
  };
}

It needs to be static because we don't instantiate the module, just use it statically. Also, the component list may be available in the module's componentFactories array in dev mode, but not in production mode, componentFactories is empty there!

Checking production build:

chunk {1} main.7ccae0763b130d21fb52.js (main) 4.78 kB [initial] [rendered]
chunk {6} 6.699c38ffd171596980b5.js () 648 bytes  [rendered]

Main bundle decreased in size, because we split out MyDialog module from it, and a new chunk appeared which holds the content of MyDialog module.

Afterword

Normally I'd say this is it, but here are some further good-to-know things about lazy loading for material dialog.

Putting this into a service

Since we didn't used any view-specific thing on the way, the whole code can be put into a service. So instead of importedModule.MyDialogModule, you can write importedModule[moduleName] and pass moduleName as an attribute of the dialog-opener method. Same with moduleType.components.MyDialogContentComponent -> moduleType.components[componentName].
What you cannot do is replacing the import()'s parameter with a variable, because webpack and typescript will parse the import command at build time and create a chunk accordingly, same time replacing the file name with the final chunk name along with the generated hash. This needs the parameter to be kept as a simple, hard-coded string.

  public showDialog(moduleName: string, componentName: string): void {
    import('src/app/feature/my-dialog/my-dialog.module')
      .then((importedModule) => importedModule[moduleName])
      .then((moduleType) => this.dialog.open(moduleType.components[componentName]))
  }

What I suggest is to create a module mapping logic inside your application, which can resolve a moduleName into an import Promise. E.g.

private resolveModule(moduleName: string): Promise<Type<{}>> {
  switch (moduleName) {
    case 'MyDialogModule':
      return import('src/app/feature/my-dialog/my-dialog.module');
  }
}

public showDialog(moduleName: string, componentName: string): void {
  // please do some checks as well, if everything exists what needs to
  this.resolveModule(moduleName)
    .then((importedModule) => importedModule[moduleName])
    .then((moduleType) => this.dialog.open(moduleType.components[componentName]))
}

... and you can call, like

showDialog('MyDialogModule', 'MyDialogContentComponent');

Complicating the module

You may want to put some service into your dialog module. In this case, you must specify the providedIn attribute of you service Injectable decorator (either 'root' or 'any' will fit). Including your service only in the module's providers[] array won't work.

Instead, you'll get something like this:

ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(AppModule)[MyServiceService -> MyServiceService -> MyServiceService]: 
  NullInjectorError: No provider for MyServiceService!
NullInjectorError: R3InjectorError(AppModule)[MyServiceService -> MyServiceService -> MyServiceService]: 
  NullInjectorError: No provider for MyServiceService!

You can say, what about creating an instance of the lazy loaded module and use the injector from it? But unfortunately, material dialog.open() won't consider that, only the root injector.