How to properly dynamically load Components into Pages

Hi there,

I’ve found that when loading components dynamically into pages the style breaks. What could I be doing wrong?

Consider this code extension from the tutorial:

test.page.js:

import {DynamicComponentLoader, Component} from 'angular2/core';

import {Page} from 'ionic-angular';

@Component({
    template: '<ion-list><ion-item>item 1</ion-item><ion-item>item 2</ion-item></ion-list>'
})
export class TestComponent{
    constructor() {}
}

@Page({
    templateUrl: 'build/pages/test/test-page.template.html'
})
export class TestPage {
    static get parameters() {
        return [[DynamicComponentLoader]];
    }

    constructor(dcl) {
        dcl.loadAsRoot(TestComponent, 'test');
    }
}

test-page.template.html

<ion-navbar *navbar>
  <button menuToggle>
    <ion-icon name="menu"></ion-icon>
  </button>
  <ion-title>Test Page</ion-title>
</ion-navbar>


<ion-content padding>
    <test></test>
</ion-content>

Then I’ve modify hello-ionic.html button:

<button primary (click)="loadTestPage()">Toggle Menu</button>

and hello-ionic.js for invocation:

// hello-ionic.js code
import {TestPage} from '../test/test.page';
// more hello-ionic.js code here
    loadTestPage() {
        this.nav.push(TestPage);
    }

The result is a non styled item list:

How should I properly load components into pages in order to maintain ionic 2 styles?

Best,

Hi,

The answer was in this FAQ.

An Ionic component is not working inside my custom Angular 2 component!

To include an Ionic component in your custom Angular 2 component you must import IONIC_DIRECTIVES and inject those into your component by placing them in the directives array. You will then be able to include Ionic components in your Angular 2 component.

@Component({
  selector: 'custom-component',
  template: `
    <h1>My awesome custom component</h1>
    <ion-list>
      <ion-item>
        I am an awesome ionic component.
      </ion-item>
    </ion-list>
  `,
  directives: [IONIC_DIRECTIVES]
})
class MyComponent {
}

heh… I never reach that because I suspected that the problem was because I was dynamically loading the component. Every search I did was with DynamicComponentLoader :frowning2:

Try with IONIC_DIRECTIVES and tell me if it’s ok :slight_smile:

Yes, it was. Believe me, I did an intensive search in the topic. Also found that loadAsRoot() does not wire change detection so I finally use loadIntoLocation().

2 Likes

Any update on this with the new RC? I got it working in the webpage (using ionic serve) but as soon as I build it for the simulator (ios) it breaks the page when I try to dynamically load the component.

More info on this. So since Ionic uses AoT compilation, the Runtime Compiler is not available in production mode, throwing an error. Does anyone know how to solve this?

2 Likes

Hi Alex, did you solve your problem?

Yeah, don’t do it. I’m sad to say but dynamically adding and changing the templates for components is not supported in ionic 2. This is due to the use of AoT compilation (Which improves speed, among other things) since compiles all templates beforehand, and not during runtime. For this reason the compiler is not available during runtime when using AoT, and therefore it just is not possible to do what I wanted to do. I’m afraid you’ll have to try and find another way around it, unless of course you are willing to live with the drawbacks of running on a debug build in production.

You can do this because the latest (RC4) allows you to build with the “–prod” flag which builds the app with AoT. Omitting that flag gives you a debug build, not utilizing AoT, which therefore should leave the runtime compiler available for your app. Again, this is NOT in any way recommended, but it CAN be done.

1 Like

We’re developing a multi lang app that loads dynamically multiple .html pages for grammar lessons. I wonder if I have to create hundreds of component/pages for each lesson…

What we do without AoT is loading these pages via a “dynamic loader component” and use some simple directives inside them (like showing a toast when user clicks a custom directive, like this: <example tooltip="explanation to show with toast">An example sentence</example>). If we only use innerHTML method, we can not use these directives/attribute directives/pipes, only html content.

I can’t decide what to do now; after implementing dynamic component creation and then learning that in build mode AoT doesn’t let us doing that… What would you do;

  • Load html files into innerHTML (using AoT compiler (–prod mode)):

    • Don’t use directives/pipes
    • Loose interactivity
    • Gain performance (that’s the main purpose of AoT, right? but what if I use hundreds of html pages?)
    • Use hundreds of pre-compiled html pages for grammer lessons, text files…
  • Load html files dynamically as components (using JiT compiler (–dev mode)):

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

I just want to be able to handle these grammar lessons in a simple syntax (like HTML), but maybe I should convert them into JSON files? I’m really confused :frowning: Maybe I should open a new topic for this? :sweat:

If you are using dynamic component loading for language translation, you’re doing it wrong, or maybe just a little too complex? There is a much, much simpler solution, and that is to use i18n translations through the ng2-translate plugin:

I’ve implemented this in another ionic 2 application, where you basically just set the language locale and use pipes in the the templates, or a service in the ts files:

{{ 'some.translation.key' | translate }} → will translate the text mapped to that key to whatever locale you got.

or

translate.instant('some.translation.key'); will translate it directly to a string.

It does this using JSON files you populate with key value pairs. For example:

sv.json (the swedish one)
{ "a_key" : { "a_sub_key": 'some text that is mapped to this key' }, "another_key":'some text here too' }

these keys can then be accessed using 'a_key.a_sub_key" or “another_key”, individually.
I got help with setting this up in a different topic which you can find here:

Good luck!

sorry for the little explanation, and thanks for your help. in fact we already use that plugin, i started a new topic to explain the whole situation: Asking your advise about dynamic/static loading components/pages/html any other ideas are welcome.