3

I need to initialize an angular app with the component my-app, the problem is that this component exists on a html template that is not loaded on page start so I have to manually initialize, otherwise it gives me an error showing this message: Error: The selector "my-app" did not match any elements

Is that possible?

Don Dev
  • 61
  • 8
  • You may want to stick with the normal process of using App module and App component as your startup process. Have you tried using the Angular CLI to generate that boilerplate code for you? – DeborahK Jul 07 '17 at 00:43

2 Answers2

2

If you're using SystemJS you can create the element dynamically using document.createElement() and append using appendChild() then call System.import() to initialize the app. This assumes that all necessary application assets and SystemJS configuration has been loaded already:

HTML

<body>
  <div id="app"></div>

  <button type="button" id="foo">Click Me</button>

  <script src="app.js"></script>
</body>

JS

(function() {
  var button = document.getElementById('foo');
  var container = document.getElementById('app');

  button.addEventListener('click', function() {
    var myApp = document.createElement('my-app');
    myApp.textContent = 'Loading...';

    container.appendChild(myApp);

    System.import('app')
      .catch(console.error.bind(console));
  });
})();

Here is a plunker demonstrating the functionality. The app element is created, appended, and initialized from within the event handler of the button click.

UPDATE If you're using Webpack and depending on your build/bundling process, you can load the main transpiled/bundle JS file dynamically using a pattern in this question to avoid your error. If you're using @angular/cli this may be more difficult as generated files have identifiers such as main.97e5159ded9c783f627a.bundle.js.

Hopefully that helps!

Alexander Staroselsky
  • 37,209
  • 15
  • 79
  • 91
1

Here is how you can do that. First create a root app module and declare your root component in declarations and entryComponents. Do not add it to bootstrap components. Then define ngDoBootstrap method on the module class to let Angular know you will be bootstrapping the application yourself. Inside this method obtain the reference to the ApplicationRef and then when the time comes simply call bootstrap on it passing the AppComponent class reference. Here is the code:

@NgModule({
  imports: [BrowserModule],
  declarations: [AppComponent],
  entryComponents: [AppComponent]
})
export class AppModule {
  ngDoBootstrap(app: ApplicationRef) {
    // delay bootstrap by 3 seconds
    setTimeout(() => {
      app.bootstrap(AppComponent)
    }, 3000);
  }
}

Essentially this is what Angular does under the hood when you call bootstrapModule(AppModule); with boostrapComponents specified.

Read How to manually bootstrap an Angular application for more details.

Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488