7

I have two angular application say A and B. Now in B application's One tab i want to load entire application A. How do i achieve this?

Please let me know how to achieve this functionality. Does angular has any special tag which i can use

3 Answers 3

6

One solution to your problem might be to create the tag you are asking for yourself. I implemented Angular application A in Angular application B by a technique named web component or Angular elements as stated above, see e.g. https://www.techiediaries.com/angular/angular-9-elements-web-components/

In the following steps a tag shiny-app-a is defined in application A which is used later on in application B by importing the JavaScript files of A into B and referencing them by the tag.

It works in the following environment:

  • Angular CLI: 11.0.2
  • Node: 12.16.1
  • OS: win32 x64

The steps to make it run are:

1. Create application A

This application additionally needs the package @angular/elements.

1.1. Create the skeleton of application A

$ ng new App-A
$ cd  App-A
$ ng add @angular/elements

1.2. Apply changes to app.modules.ts to create the web component / element and define the corresponding tag shiny-app-a

My app.modules.ts looks like this:

import { BrowserModule } from '@angular/platform-browser';
// import Injector
import { Injector, NgModule } from '@angular/core';
// import createCustomElement
import { createCustomElement } from '@angular/elements';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
  AppComponent
  ],
  imports: [
  BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {

  constructor(private injector: Injector){}

  ngDoBootstrap(){
    const el = createCustomElement(AppComponent, {injector:this.injector});
    // Here you define your new tag shiny-app-a
    customElements.define('shiny-app-a', el);
  }
 }

1.3. Build project

$ ng build --prod --output-hashing none

This generates among others the files:

  • runtime.js
  • main.js
  • polyfills.js

You will find them in the folder [...]\App-A\dist\App-A

1.4. Test it

Run

$ ng serve

and see in the browser your newly built application A.

2. Create application B

Note: no @angular/elements is needed here.

2.1. Create the skeleton of application B

$ ng new App-B

2.2. Copy the files from application A to a folder accessible by application B

In this example I use the folder [...]/src/assets.

$ cd App-B/src/assets/

and copy the JavaScript from application A to this folder, i.e.:

  • [...]/App-A/dist/App-A/main.js
  • [...]/App-A/dist/App-A/polyfills.js
  • [...]/App-A/dist/App-A/runtime.js

2.3. Adapt source of application B to use the tag defined in step 1.

2.3.1 Make custom elements known to application B in app.module.ts

The crucial item to implement is CUSTOM_ELEMENTS_SCHEMA. My app.modules.ts of application B looks like this:

import { BrowserModule } from '@angular/platform-browser';
// import CUSTOM_ELEMENTS_SCHEMA
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  // add schemas
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
2.3.2 Load JavaScript from external source in app.component.ts

The JavaScript files may also be loaded from any source. In this case the files are loaded by OnInit() from the [...]/assets folder. Thus my app.component.ts of application B looks like this:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'App-B';

  ngOnInit() {
    this.loadScript('/assets/runtime.js');
    this.loadScript('/assets/main.js');
    this.loadScript('/assets/polyfills.js');
  }

  public loadScript(url: string) {
    const body = <HTMLDivElement> document.body;
    const script = document.createElement('script');
    script.innerHTML = '';
    script.src = url;
    script.async = false;
    script.defer = true;
    body.appendChild(script);
  }
}
2.3.3 Use tag in app.component.html

Replace anything from the file app.component.html and just by:

<shiny-app-a></shiny-app-a>

2.4. Test it

Run

$ ng serve

and see in the browser application A in application B.

Sign up to request clarification or add additional context in comments.

2 Comments

This works partially for me. I well show the component of the second angular app, but it's in fullscreen so I don't show the base app. How can I fix it ?
I run into the problem that the compiler says: Cannot find app-root element. I tried using a prefix and even changing the app root element from my main project but always the same... :/
2

You want something like MICRO front ends, build Application A as Angular custom element (web component - Angular Elements), the output will be a script. Load this script in Application B. place the selector which you provided while creating a custom element in Micro App B where ever you want to load App A.

For More read about Micro Front Ends (Angular Elements)

Please don't use iframe they become really difficult to manage, To know more read a little about Micro Front End with Angular there are lots of well-written blogs on the same.

2 Comments

in this examples thy are just loading one component.. I want to load entire app inside another app
Angular Element is not just a component, it's a complete application wrapped as a component.
0

As Akshay mentioned you could use Angular Elements to expose your app A as a custom element and use it in app B.

In your case, you want to expose your AppComponent as a custom element.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.