I have two elements in my angular project that are completely independent. The first one shows a list of license plates and two buttons for each plate: "View current position" and "View positions for the last 24h". Those two buttons redirect to the same component which shows in a map some points depending of a variable "method". I want to set the "method" in a certain value when the button is clicked, but I have no idea how to do this.
I have tried about the Subject/Subscribe thing but did not work for me. It is possible that I did not apply it properly, as I am not very confident about how it works. In the examples I have found, the subject was emmited by some @Injectable, but I am working with two @Component.
Thank you all.
Edit: I will try to explain what I have tried.
I have the service
import { Inject, Injectable } from "@angular/core";
import { MatriculasListadoComponent } from "../components/matriculas-listado/matriculas-listado.component";
import { Metodos } from "../models/metodos";
@Injectable({
providedIn: 'root'
})
export class ConexionDataService {
metodoBoton: Subject<Metodos>
constructor() {
this.metodoBoton = new Subject<Metodos>();
}
}
Then I have a method in my component from where I want to send the data which is called clicking the buttons:
constructor(private matriculaService: MatriculaService, private conexionDataService: ConexionDataService) {
this.dataSource = new MatTableDataSource<Matricula>([]);
}
...
enviarMetodo(metodo:Metodos) {
this.conexionDataService.metodoBoton.next(metodo);
}
And I have this NgOnInit in the component where I want to recieve the data
providers: [ListaPosicionesService, DatePipe, ConexionDataService]
...
ngOnInit(): void {
this.conexionDataService.metodoBoton.subscribe(log=> {
this.metodo=log
console.log(log)
})
I am getting log as "undefined". Probably I am not doing it properly as I do not understand at all how those services work...
When passing data between components that lack a direct connection, such as siblings, grandchildren, etc, you should use a shared service. When you have data that should aways been in sync, I find the RxJS BehaviorSubject very useful in this situation.
You can also use a regular RxJS Subject for sharing data via the service, but here's why I prefer a BehaviorSubject.
Here is the working demo BehaviorSubject | Stackblitz
shared service
private messageSource = new BehaviorSubject('default message');
changeMessage(message: string) {
this.messageSource.next(message);
}
Parent-Component
constructor(private data: DataService)
this.data.changeMessage('Hello from About component');
sibling-Component
constructor(private data: DataService)
this.data.currentMessage.subscribe(
(message) => (this.message = message)
);
Whenever the parent emits using the next method, you can receive the data in other component and act on it.
In the demo i have created it will redirect as well and updated data will be available in the component we redirected to.
You can use a library like NgRx . This will allow you to communicate between components easily without creating the relation "parent-child" between them.
Just dispatch an action from your current component and create an effect to catch and trigger the other component
If its a complicated app then NGRX to maintain state is a good idea. However, its a lot of boilerplate code for a simple app where BehaviourSubjects maybe what you are after.
BehaviourSubjects are observables that require initialisation. They tend to sit on an existing service you may have defined (DI injected via your component constructor).
BehaviorSubject vs Observable?
The flow is like this...
Define your BehaviourSubject on a service. Mine is a service called CommonSvc. Here is a good article about services. https://angular.io/tutorial/toh-pt4
public loadingSub: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
Create a public method to expose the subject and set the next value
public setLoading(loading: boolean,): void {
this.loadingSub.next(loading);
}
On your component, inject your service into the constructor.
private commonSvc: CommonService
You can now access the BehaviourSubject directly. Something like this.
this.commonSvc.loadingSub
.subscribe((loading) => {
this.loading = loading;
});
...and it you need to update the BehaviourSubject, call the public method.
this.commonSvc.setLoading(true);
Now, the beauty of this method is that everywhere you subscribe to the BehaviourSubject, the same value will be presented. You can inject the service anywhere in your components so it makes it pretty flexible too.
The downside is that when you have lots of them (Subjects & BehaviourSubjects) they can get tricky to manage. That's where NGRX comes in.
PS. If you are subscribing to subscriptions, don't forget to unsubscribe when you are done.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.