When utilizing custom ngDoBootstrap and createCustomElement in Angular, the router fails to recognize the URL being used

WHEN I implement a custom ngDoBootstrap function instead of the default bootstrap: [AppComponent] like shown below:

@NgModule({
  imports:      [ BrowserModule, FormsModule, AppRoutingModule ],
  declarations: [ AppComponent, HelloComponent ],
  exports: [ AppComponent ],
  entryComponents: [ AppComponent ],
  // bootstrap: [AppComponent],
})
export class AppModule {
  constructor(private injector: Injector) {
  }

  public ngDoBootstrap(): any {
    const appElement = createCustomElement(AppComponent, { injector: this.injector });
    customElements.define('my-app', appElement);
  }
}

THEN The application routing experiences issues.

It fails to respond to changes in the URL and only functions correctly when clicking on <a [routerLink]='...'>. Additionally, the initial route / is not loaded as expected.

This issue seems to stem from the custom bootstrap mechanism, as uncommenting the bootstrap: [AppComponent] resolves the problem.

You can access the full code here: stackblitz sample (requires downloading and running locally due to the TypeScript version used by stackblitz)

Any suggestions on how to ensure proper routing with a custom app module bootstrapping?

Answer №1

After following a helpful tutorial, I was able to successfully implement the functionality I needed in my Angular application. The tutorial can be found here.

I discovered that angular elements may not fully support internal application routing, as mentioned in this SO post and this Github issue.

To address this limitation, I had to manually guide the router to navigate to internal routes when there are changes in the location.

export class AppModule {
  constructor(private injector: Injector, private router: Router,
    private location: Location) {
    const appElement = createCustomElement(AppComponent, { injector: this.injector });
   customElements.define('my-app', appElement);

    /**Include the code snippet below in your implementation**/
   //initiate router with starting path
    this.router.navigateByUrl(this.location.path(true));

    //on every route change, instruct the router to move to the specified route
    this.location.subscribe(data => {
      this.router.navigateByUrl(data.url);
    });

}

You can view a functional example on stackblitz here

Answer №2

When using a custom element, the router.initialNavigation method needed to be manually invoked:

export class AppModule {
  constructor(private injector: Injector, private router: Router,
    private location: Location) {
    const appElement = createCustomElement(AppComponent, { injector: this.injector });
    customElements.define('my-app', appElement);


  public ngDoBootstrap(): void {
    // To address an issue where initial route was not being loaded: https://github.com/angular/angular/issues/23740
    this.router.initialNavigation();
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Build a Node.js application using TypeScript and all necessary dependencies

I've developed a Node.js application using TypeScript and now I'm looking to compile it. Currently, only the source files in the src folder are included in the build. However, I also want to incorporate dependencies such as express, body-parser, ...

When the imagepath in an Angular application is not updated, it will revert to null

Below is the code snippet that I am currently working on: <div class="col-sm-4 pl-5"> <img attr.src="{{item?.imagePath}}" required height="200" width="200"> </div> In my TypeScript file (ts), I have the following function: editBlog ...

Custom Typescript type that runs concurrently with the base type is disregarded

Assumption: When creating a custom type that mirrors an existing type, the expectation is for variables assigned to that type to maintain it and not default back to the base type. In the function f provided below, the expected return type should be Dog ins ...

Determining the type of index to use for an interface

Imagine having an interface called Animal, with some general properties, and then either be a cat or a dog with corresponding properties. interface Dog { dog: { sound: string; } } interface Cat { cat: { lives: number; } } type CatOrDog = Cat | D ...

Best practices for maintaining editable ag-grid cells

Using ag-grd-ng2 (ag-grid for Angular2), I have implemented editable cells and successfully propagated updates to the server. This was achieved by utilizing the gridOptions.onCellValueChanged event. Within my column definition, the properties are set as ...

Leveraging Window Object in Custom Hooks with NextJS

ReferenceError: window is not defined This issue arises on the server side when NextJS attempts to render the page. However, it is possible to utilize window within the useEffect hook by following the guidance provided here. I am seeking advice on creati ...

What is the best way to assign three different dates in my protractor test?

I am facing an issue with setting random dates in 3 date fields in a row using Protractor. The problem is that Protractor sets the dates too quickly and sometimes assigns invalid dates like: first data: 01/08/1990 (correct) second data: 01/09/0009 (inva ...

Issue with Bootstrap 4 column width when using Angular 2 *ngFor

I have a container that displays search results. The layout is set up using Bootstrap columns, but there seems to be excessive padding or margin causing the results to appear very narrow. Interestingly, if I manually input each result instead of using *ngF ...

Integrating additional JavaScript into an Ionic 2 project

Imagine we have a foo.js file containing a variable, function, and class that are not yet part of the project. Now suppose we want to access these elements in our home.ts method or make them globally available for use within a home.ts method. How can this ...

What causes certain webpack / Babel ES6 imports without a specified extension to resolve as "undefined"?

When I try to import certain ES6 files (such as .js, .jsx, .ts, .tsx) using the syntax import ComponentName from './folder/ComponentName'; (without extension), they end up resolving as undefined. This occurs even though there are no errors from W ...

The use of throwError(error) has been phased out, however, no replacement has been introduced for the Error(HttpErrorResponse)

It seems like the use of throwError(error) is deprecated now. VS Code suggests using throwError(() => new Error('error')) instead, as new Error(...) only accepts strings. How can I replace it correctly without causing issues with my HttpErrorH ...

What is the rationale behind permitting surplus properties in Typescript interfaces even though all properties are declared as optional?

Exploring the code snippet... interface Options { allowed?: string; } function test(options: Options) { return options; } const options = { allowed: 'allowed', notAllowed: 'notAllowed', }; test(options); // no error thrown ...

Using TypeScript's Non-Null Assertion Operators in combination with square brackets []

One way to assert that an object has a certain property is by using the `!.` syntax as shown below: type Person = { name: string; age: number; gender?: string; } const myPerson: Person = { name: 'John Cena', age: 123, gender: 's ...

Identifying patterns within a string using JavaScript and TypeScript

Given a user-input pattern, for example [h][a-z][gho], and a string "gkfhxhk", I am attempting to determine if the string contains the specified pattern. The pattern dictates that the first character must be 'h', followed by any letter from a-z, ...

Automatically insert a hyphen (-) between each set of 10 digits in a phone number as it is being typed into the text

I'm attempting to automatically insert a hyphen (-) in between 10 digits of a phone number as it is being typed into the text field, following North American standard formatting. I want the output to look like this: 647-364-3975 I am using the keyup ...

Encountering a compilation error due to a Typescript assignment

While working with Typescript, I encountered a compilation error in the code shown below: console.log('YHISTORY:login: data = '+data); let theData = JSON.parse(data); console.log('YHISTORY:login: theData = '+JSON.stringify(theData)); ...

How to deliver various static files in NestJS using different paths and prefixes?

I've set up static file serving for developer documentation using the following code: app.useStaticAssets(docsLocation, { prefix: "/docs/" }) Now I have another directory with more static content that I want to serve. Is it possible to serve from ...

Error: JSON parsing error - Unexpected token at the start of the JSON data when using JSON.parse() function

Backend code router.route('http://localhost:5007/api/media') .post(mediaCtrl.saveMedia) async saveMedia(req, res) { let file = req.files.file let ext = req.body.extension let path = req.body.path if(_.isNull(file) || _.isEmp ...

Loading custom components dynamically in Angular with SVG: a how-to guide

Looking for a way to dynamically load SVG items with ease. The items needed are quite simple. Here's a basic template: <svg:rect [attr.x]="x" [attr.y]="y" width="10" height="10" /> Component Class Example: export class DraggableSvgItemCompon ...

Tips on verifying the binding of a mat-checkbox in Angular

I am working with an Angular 6 application and want to ensure that the binding of a mat-checkbox is functioning correctly. Here is the template: <div style="text-align:center"> <mat-checkbox id="singleCheckBox" [(ngModel)]="isChecked">Check ...