Asking your advise about dynamic/static loading components/pages/html

Hi everybody,

I would like to ask your advise on our situation about dynamic/static loading components.

We’re developing a “multi lang teaching app” for Android/iOS. For UI texts we use ng-translate plugin (json files for each lang). For the lessons content we use seperate html files for each language. In the beginning user selects a language to learn and then sees related lessons as a list (which comes from a json file too). Clicking a lesson loads related html file and dynamically compiles directives/pipes in it (which makes it more interactive). By directives, I mean simple functions like showing a toast when user clicks a custom directive, like this: <example tooltip="explanation to show as a toast">An example sentence</example>. But maybe we can use more complex directives in the future…

Up to building the app, everything goes well in browser. But in mobile devices, AoT compiler does not support “dynamic loader components”, so we need to decide whether or not use this approach. And at that point I’m really confused :frowning: We may change our structure but I don’t know which way is better.

As far as I can see, we have 3 options (if there is more, please enlighten me):

  • Stop using html files and convert each of them into a component with html templates (using AoT compiler (–prod mode)):

    • Be able to use directives/pipes
    • Gain interactivity
    • Gain performance (that’s the main purpose of AoT, right? but what if I use hundreds of html pages/components? isn’t it a bulky solution?)
    • Use hundreds of pre-compiled html pages for grammer lessons, stories, texts…
  • Load pure html files into an innerHTML of a loader component (using AoT compiler (–prod mode)):

    • Don’t use directives/pipes
    • Loose interactivity (except being able to use simple html tags like p, strong, em, table etc. --if we count this as an interactive content)
    • Gain performance a bit (as we use AoT?)
  • Load html files dynamically as components via one dynamic template component (using JiT compiler (–dev mode)):

    • Be able to use directives/pipes
    • Use seperate html files
    • Gain interactivity
    • Loose performance
    • Do something that Angular generally does not recommend

I can’t decide what to do now, if I want more interactivity, I should drop the performance that Angular proposes… :sweat:

I just wanted to be able to handle these grammar lessons in a simple syntax (like HTML) as seperate files and not to use/declare components for each of them…

What would you recommend to us? There must be some other people facing a similar issue, I hope? :slight_smile:

I went through this with Markdown, tried a bunch of things, and here’s what I eventually settled on:

  • Store your objects however is convenient for you. In my case, that’s markdown source.
  • Define two components; we’ll call them skeleton and bone for now.
  • skeleton has an input property giving it the source. In ngOnChanges, you need to parse that source into an array of elements, each corresponding to a different type of bone.
  • skeleton’s template looks something like this:
<template ngFor let-bone [ngForOf]="bones">
  <app-bone [bone]="bone"></app-bone>
</template>
  • Make sure each bone has a discriminator indicating its type, and then the BoneComponent template is a big giant switch:
<blockquote *ngIf="bone.tag === 'blockquote'">
  <app-bone *ngFor="let child of bone.children" [bone]="child"></app-bone>
</blockquote>

<br *ngIf="bone.tag === 'br'">

... every other block-level element we support...

Note that this can work recursively if you need it to, in that the inside of the blockquote case is effectively another skeleton. I’m using HTML elements here, but the general technique works equally well for other user-defined components (as types of bones).

4 Likes

Hi @rapropos
Thank you for your explanation. It was really helpful. I decided to use your bone/skeleton solution. It was a good challenge to implement :slight_smile: Thank you again!

Hi @emre3,

I am also onto implementing something similar. Can you please enlighten me on how to code such a directive with ionic2 (ts)?

Is anyone able to provide a simple example on Github for this? Anyone willing to contribute some open-source code back to the community? @rapropos @akshukla07