1
votes

I've a Layout Page that mat-sidenav-container and router-outlet in it.I try to call the function and pass data to LayoutPage from router-outlet Page By EventEmitter but it's not working. I found the similar problem with me here: @Output with EventEmitter from child to parent, view doesn't update in parent

And it's work if replacing router-outlet tag to component selector tag (app-child),but router-outlet tag is necessary for me.I need to navigate the webPage By router-outlet tag.How could I do then?

layout.component.html

<mat-sidenav-container>
    <mat-sidenav #sideNav opened="true" mode="side" class="sidebar" style="background-image: url('assets/images/test.png');">
      <ul class="nav">
        <li routerLinkActive="active" *ngFor="let menuItem of menuItems" class="test nav-item">
            <a class="nav-link" [routerLink]="[menuItem.path]" [queryParams]="filter">
                <i class="material-icons">{{menuItem.icon}}</i>
                <p>{{menuItem.title}}</p>
            </a>
        </li>
    </ul>
    </mat-sidenav>
  
    <mat-sidenav-content class="content">
        <app-header></app-header>
      <router-outlet (onDatePicked)='doSomething($event)' > </router-outlet>
      
    </mat-sidenav-content>
  </mat-sidenav-container>

layout.component.ts

@Component({
  selector: 'app-layout',
  templateUrl: './layout.component.html',
  styleUrls: ['./layout.component.css']
})
export class ChemoLayoutComponent implements OnInit {

  filter:Filter
  menuItems: any[];
  constructor(private route: ActivatedRoute,private app: ApplicationRef) {
    this.menuItems = [
      { path: '/chemo/child', title: 'aaa',  icon: 'library_books' },
      { path: '/chemo/child1', title: 'bbb',  icon:'build'},
      { path: '/chemo/child2', title: 'ccc',  icon:'search' },
  ];
  this.filter = new Filter();
   }

  ngOnInit(): void {
    this.route.queryParams.subscribe((params) => {
      this.filter.CHARTNO = params['CHARTNO'];
    });
  }

  doSomething($event){  //<== It's not working
    this.app.tick();
    console.log("Test");
  }
}

child.component.ts

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {

  @Output() onDatePicked: EventEmitter<any> = new EventEmitter<any>();
  constructor() {

   }
  ngOnInit(): void {
  this.onDatePicked.emit("hello");
}
}
1

1 Answers

2
votes

<router-outlet (onDatePicked)='doSomething($event)' > </router-outlet>

This will not work because onDatePicked output does not exist on RouterOutlet (cf. Angular doc).

If you want to communicate from child to parent component without being limited by routing, you need to implement a service. It can look like this :

child-to-parent.service.ts

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

  onDatePicked$ = new Subject<any>();

  constructor() { }

}

layout.component.ts

@Component({
  selector: 'app-layout',
  templateUrl: './layout.component.html',
  styleUrls: ['./layout.component.css']
})
export class ChemoLayoutComponent implements OnDestroy {

  onDatePickedSub: Subscription;

  constructor(
    private childToParentService: ChildToParentService
  ) {
    this.onDatePickedSub = this.childToParentService.onDatePicked$.subscribe($event => {
      this.doSomething($event);
    });
  }

  ngOnDestroy(): void {
    if (this.onDatePickedSub) {
      this.onDatePickedSub.unsubscribe();
    }
  }

  doSomething($event): void {
    this.app.tick();
    console.log("Test");
  }

}

child.component.ts

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {

  constructor(
    private childToParentService: ChildToParentService
  ) { }

  ngOnInit(): void {
    this.childToParentService.onDatePicked$.next('hello');
  }

}