user1138
user1138

Reputation: 7

Angular 12: How do I access a function in another component?

I have the following app structure:

In the NavComponent, I am trying to show an element in the AppComponent. All I want to do is call the showElement() function inside the AppComponent from the NavComponent. How in the world do I do this?

I've looked through so many examples of services, events, and so forth, and I've tried many of them and could never get my head wrapped around the terminology and/or syntax to get them to work. If someone wouldn't mind giving me a nudge here, I would appreciate it. It can't be this hard to do.

Edit with More Details Below

Thanks, @Eliseo. These are helping, somewhat, but I'm still struggling to get it to fit what I am trying to do. Let me try to flesh out the structure more and perhaps an answer for my specific attempt would help. I will mention I've read the details on Observables about five times so far, and it only sinks in about 50% for whatever reason. I think it's because I don't understand how it functions behind-the-scenes.

Regardless, here is what I want to do:

App Component

There will be multiple page components using a similar structure but changed out with navigation. Each page component will manipulate the bridgeService data in order to show the modal. this.bridgeService.showModal and this.bridgeService.url needs to be updated and the app needs to act on it when the service is updated via a page component (or other component). [I know the syntax below is not correct, mainly because I don't understand the bigger picture.]

html

<page></page>
<app-modal *ngIf="{{this.bridgeService.showModal}}" [url]="{{this.bridgeService.url}}"></app-modal>

ts

export class AppComponent {

  constructor(public bridgeService: BridgeService) {}

}

Bridge Service

Use a service to share these values (a boolean and a URL) between components; these need to be updated by various components and components need to update themselves when these values change. The boolean will turn on/off the Modal component. The URL will affect what is displayed in the Modal component.

ts

public showModal = false;
public modalURL = '';

// not sure how to make these communicate between and update
// the components as observables, eventEmitters, etc.

Page Component

There will be about one hundred of these. Navigation will cycle through these, updating the app component with the specific page component to display. There will be various stages in each page in which a modal should be displayed. These will be custom for each page. Some pages may not show any. Others may need to show more than one, depending on the stage. There is a bit more involved, but if I can get a working example of how to share this data and update the components based on a change in this data, then I can take it from there.

ts

if (this.stage == 3) {
  // show modal
  this.bridgeService.url = "http://custom.com";
  this.bridgeService.showModal = true;
} else {
  // turn off modal for other stages
  this.bridgeService.showModal = false;
}

Upvotes: 0

Views: 1782

Answers (2)

Eliseo
Eliseo

Reputation: 57929

there's another aproach that is simply store variables in a service -and get it from this-

In this case our service can simply like

@Injectable({
  providedIn: 'root',
})
export class BridgeService {
  showModal = false;  //<--it's not necesary use "public", 
                      //by defect in Angular all the variables 
                      //and functions are public
  modalURL = '';
  constructor() { }
}

And yes, if we inject in a component the service we can change the variable or use. If we wnat to use in .html directly we need, when inject in constructor, declare as public

constructor(public bridgeService :BridgeService){}

And we can use in our .html

<app-modal *ngIf="this.bridgeService.showModal" 
      [url]="this.bridgeService.url"></app-modal>

See that we not use "interpolation"( the {{ }}). The interpolation is used when we want to show a variable in html. As tip can be that is we are using quotes (" ") not use interpolation

Then, if we has two method (subjects and variables), why on earth we make something so complex as Subject? The reason is that using variables, Angular check the values each time any change happens. We can check it is we make a getter

get url(){
   console.log("I'm a getter url")
   return this.bridgeService.url;
}
get url(){
   console.log("I'm a getter showModal")
   return this.bridgeService.showModal;
}

And use

<app-modal *ngIf="showModal" 
          [url]="url"></app-modal>

We can see that pass severals times for our getter. Is it important for the perfomance of our app?. Really not -the problem was when in a getter we make a large operation or if we has several, several getters -or it's equivalent construction without getter.

Upvotes: 0

Eliseo
Eliseo

Reputation: 57929

You has the docs , or many examples in SO, e.g. this or this (really there're a lot of answers).

in this stackblitz you has an example (I can not find the SO)

The idea is that one component only know about its parent, its children and the services we can generate.

You can define in one service an "Observable". An Observable is "something" that your component can "listen" (for this you need subscribe to it). That's, when we change this observable our component can received the "change".

Angular is full plenty Observables (Observables every-where), e.g. in a FormControl you has the observable "valueChanges", the ActivatedRouter you has "params" that is another observable, or when we use httpClient, "get" is another observable.

All the observables, when change (in the case of FormControl, when you change the input, in the case of ActivatedRouter when change the query params or in case of HttpClient when receive the value from an url) if you are subcribe to it you can make "something".

The idea of use a Subject is create your "own" observable, how do you change the "value" to get that a component that was subscribe to it take account this change? using "next"

For this, you create the Subject and the Observable in your service. The service can has a function that is which change the "Observable" As you can inject in constructor of the two components the service, one component can subscribe to the Observable and the other can call to the function of the service that change the Observable.

The only you need in subscription is call to your function.

ngOnInit(){
   this.myService.Observable.subscribe((res:any)=>{
        //in "res" we has the value "emitted" by the other component
        //we can use or not
        this.myFunction()
   })
}

See that in this ways the two components are independent (in the meaning that one can live without the other)

I don't know if this "answer" can help you

Upvotes: 1

Related Questions