user11352561
user11352561

Reputation: 2637

Angular - How to call and activate a function from another component

In my Angular-12 I have two components, employee-detail and employee-edit.

employee-detail.component.ts:

profileTemplate: boolean = false;
contactTemplate: boolean = false;

profileFunction() {
  this.profileTemplate = true;
  this.contactTemplate = false;
}

contactFunction() {
  this.profileTemplate = false;
  this.contactTemplate = true;
}

employee-detail.component.html

<div class="card-body">
  <div id="external-events">
    <button (click)="profileFunction()" type="button" class="btn btn-block btn-primary">Profile</button>
    <button (click)="contactFunction()" type="button" class="btn btn-block btn-success">Contact</button>
  </div>
</div>

<div *ngIf="profileTemplate" class="card card-default color-palette-box">

</div>

<div *ngIf="contactTemplate" class="card card-default color-palette-box">

</div>

From the above code, the function on the button click determines which of the two divs is visible. Now I have another component, employee-edit.

employee-edit.component.ts:

onSubmitProfile() {
  this.router.navigate(['/employees-detail', this._id]);
}

onSubmitContact() {
  this.router.navigate(['/employees-detail', this._id]);
}

What I want to achieve is that when onSubmitProfile() is called it should activate profileFunction() and make

<div *ngIf="profileTemplate" class="card card-default color-palette-box"> 

visible, else if it is onSubmitContact() it should be

<div *ngIf="contactTemplate" class="card card-default color-palette-box"> 

How do I achieve this?

Thanks

Upvotes: 1

Views: 4508

Answers (1)

Yong Shun
Yong Shun

Reputation: 51195

Solution 1: Fragment

1.1 Pass the event (contact or profile) in the fragment with NavigationExtras.

employee-edit.component.ts

export class EmployeeEditComponent implements OnInit {

  onSubmitProfile() {
    this.router.navigate(['/employees-detail', this._id], {
      fragment: 'contact'
    });
  }

  onSubmitContact() {
    this.router.navigate(['/employees-detail', this._id], {
      fragment: 'contact'
    });
  }
}

1.2 Retrieve fragment from activatedRoute and do the action based on fragment.

employee-detail.component.ts

import { ActivatedRoute, Router } from '@angular/router';

export class EmployeeDetailComponent implements OnInit {
  constructor(private activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    this.activatedRoute.fragment.subscribe(fragment => {
      if (fragment == 'profile') this.profileFunction();
      else if (fragment == 'contact') this.contactFunction();
    });
  }
}

Sample Solution 1 on StackBlitz

Benefit: Easier to implement and manipulate content with fragment #event.

Disadvantage: The URL will show the fragment #event since it is implemented.


Solution 2: Build Simple Service to Share Data

2.1 Create EmployeeEventService with getter and setter methods for event$.

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable, Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class EmployeeEventService {
  private event$: BehaviorSubject<
    keyof typeof EVENT | null
  > = new BehaviorSubject(null as keyof typeof EVENT | null);

  setEvent(event: keyof typeof EVENT) {
    this.event$.next(event);
  }

  getEvent() {
    return this.event$.asObservable();
  }
}

export enum EVENT {
  contact,
  profile
}

2.2 Inject EmployeeEventService and set the event via setEvent().

import { EmployeeEventService } from '../employee-event.service';

export class EmployeeEditComponent implements OnInit {
  constructor(
    public employeeEventService: EmployeeEventService
  ) {}

  onSubmitProfile() {
    this.employeeEventService.setEvent('profile');
    this.router.navigate(['/employees-detail', this._id]);
  }

  onSubmitContact() {
    this.employeeEventService.setEvent('contact');
    this.router.navigate(['/employees-detail', this._id]);
  }
}

2.3 Inject EmployeeEventService and get event$ Observable via getEvent().

import { EmployeeEventService } from '../employee-event.service';

export class EmployeeDetailComponent implements OnInit {
  constructor(
    public employeeEventService: EmployeeEventService
  ) {}

  ngOnInit() {
    this.employeeEventService.getEvent().subscribe(event => {
      if (event == 'profile') this.profileFunction();
      else if (event == 'contact') this.contactFunction();
    });
  }
}

Sample Solution 2 on StackBlitz

Benefit: Control event by the service (Benefit for Solution 1's disadvantage).

Disadvantage: Harder to implement compared to Solution 1.

Upvotes: 1

Related Questions