Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular elements with Angular routing

Tags:

angular

I would like to use Angular routing in a component that's bootstrapped as a custom element. It appears that if I place several custom elements on a page, only the last element receives the router-outlet.

Here is the repo with a sample on GitHub

I generated this sample project by:

  • ng new (with routing)
  • ng add @angular/elements
  • changed to bootstrap via createCustomElement (my-el is the element name)
  • changed TypeScript "target" to Es6
  • changed Index.html to host two my-el elements

Do you know why only the last instance of my component has router-output and all other instances route to that element?

like image 850
user1044169 Avatar asked Apr 28 '19 01:04

user1044169


People also ask

What are the two elements of routes in Angular?

Each route in this array is a JavaScript object that contains two properties. The first property, path , defines the URL path for the route. The second property, component , defines the component Angular should use for the corresponding path.

How can I use Angular element in another Angular project?

In order to use it in another Angular app, we don't really need to build the component; as it is a simple Angular component, we can just import and use it. But if we only have access to compiled files, we can include them with the scripts field in our angular.

Which modules are needed for routing in Angular?

In Angular, the best practice is to load and configure the router in a separate, top-level module. The router is dedicated to routing and imported by the root AppModule . By convention, the module class name is AppRoutingModule and it belongs in the app-routing.module.ts in the src/app directory.


1 Answers

It's because you can have only one primary router outlet per module. (Primary outlet is the one with no name specified in the template) I found this article helpful: https://www.techiediaries.com/angular-router-multiple-outlets/

You can work around that by naming your outlets - but since you are using the same app components I think you will need something along those lines:

app.component.ts:

@Input() name: string;

getRouterLink(url: string): object {
    return { outlets: { primary: url, first: url, second: url } };
}

index.html

<my-el name="first"></my-el>
<my-el name="second"></my-el>

app-routing.module.ts:

const routes: Routes = [
    { path: "", redirectTo: "page1", pathMatch: "full" },
    { path: "page1", component: Page1Component },
    { path: "page2", component: Page1Component },
    { outlet: "first", path: "page1", component: Page1Component },
    { outlet: "first", path: "page2", component: Page2Component },
    { outlet: "second", path: "page1", component: Page1Component },
    { outlet: "second", path: "page2", component: Page2Component }
];

app.component.html:

<h2><a href="#" [routerLink]="getRouterLink('page1')">Page1</a></h2>
<h2><a href="#" [routerLink]="getRouterLink('page2')">Page2</a></h2>
<ng-container *ngIf="name === 'first'">
    <router-outlet name="first"></router-outlet>
</ng-container>
<ng-container *ngIf="name === 'second'">
    <router-outlet name="second"></router-outlet>
</ng-container>

This could be made nicer ofc but should be enough to illustrate the point.

I've tried binding router-outlet's 'name' dynamically (<router-outlet [name]="name">) so it's not wrapped in those ng-containers, but that's not possible since 'name' is an @Attribute and not an @Input of the router-outlet (https://github.com/angular/angular/blob/f8096d499324cf0961f092944bbaedd05364eea1/packages/router/src/directives/router_outlet.ts#L50)

like image 157
watofundefined Avatar answered Sep 18 '22 04:09

watofundefined