Pass data to router-outlet - problem when multiply routers with names

Viewed 287

I have problem with pass data to router outlet. Usually I do something like below:

<router-outlet (activate)="setConfig($event)"></router-outlet>

and

setConfig(component: { [key: string]: any }) {
   component.data = this.data;
}

and it works perfect.

But problem is when I have multiply router-outlet with empty path and name. So in routing.module I have:

  {
    path: 'test',
    component: TestComponent,
    children: [
      {
        path: '',
        loadChildren: () => loadRemoteModule({
          remoteName: 'test1',
          remoteEntry: `/c/test1/remoteEntry.js`,
          exposedModule: 'Test1Module',
        }).then(m => m.Test1Module)
      },
      {
        path: '',
        outlet: 'test2',
        loadChildren: () => loadRemoteModule({
          remoteName: 'test2',
          remoteEntry: `/c/test2/remoteEntry.js`,
          exposedModule: 'Test2Module',
        }).then(m => m.Test2Module)
      }
    ]
  },

and in component:

<router-outlet (activate)="setConfig($event)"></router-outlet>
<router-outlet (activate)="setConfig($event)" name="test2"></router-outlet>

In this case I can't set component.data = this.data, because when I console.log component inside setConfig it isn't my component from child route as I expected, it is "ɵEmptyOutletComponent", and I don't know how to pass data to this component in this case.

Test1 and Test2 are microfrontends, there are independents projects and there arent't part of project where Test Component is.

1 Answers

when I console.log component inside setConfig it isn't my component from child route as I expected, it is "ɵEmptyOutletComponent"

That's because there is no component provided in the children route:

children: [
      {
        path: '',
        loadChildren: () => loadRemoteModule({
          remoteName: 'test1',
          remoteEntry: `/c/test1/remoteEntry.js`,
          exposedModule: 'Test1Module',
        }).then(m => m.Test1Module),
        // component: myComponent   <======= MISSING HERE
      }
]

Of course you don't need to provide one since you only want to lazy load the module.

Instead of assigning the data to the component via activate EventEmitter, you should create a service that can store the data. This way, any of your components can have access to it.


share-data.service.ts (which stores the data)

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

import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class ShareDataService {

  // This is the data to be shared by components which
  // includes Test component, Test1 component, Test2 component, etc.
  // BehaviorSubject is better then Subject because it will
  // send the last known value even if the subscriber subscribe late.

  public data = new BehaviorSubject<string>('');

  constructor() {}
}

test.component.ts ( which assigns new value to the data)

import { Component } from '@angular/core';
import { ShareDataService } from './share-data.service';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css'],
})
export class TestComponent implements OnInit {
  constructor(private readonly _serv: ShareDataService) {}

  public ngOnInit() {

    // We want to broadcast the new value to the
    // service so all other component can be notify
    // if they are subscribed to the share-data service.

    this._serv.data.next('new data!');
  }
}

test1.component.ts (which fetches the new value from the data)

import { Component, OnInit } from '@angular/core';
import { ShareDataService } from './share-data.service';

@Component({
  selector: 'app-test1',
  templateUrl: './test1.component.html',
  styleUrls: ['./test1.component.css'],
})
export class Test1Component implements OnInit {
  private _myData: string;
 
  constructor(private readonly _serv: ShareDataService) {}

  public ngOnInit() {

    // We pull data from the service and assign the value to the _myData.
    // The subscribe part is to make sure we pull the latest value.

    this._serv.data.subscribe(data => this._myData = data);
  }
}
Related