Angular 2 send data from component to service - javascript

My target is to send data from Angular component to service and use service methods to work on it. Example:
export class SomeComponent {
public data: Array<any> = MyData;
public constructor(private myService: MyService) {
this.myService.data = this.data;
}
}
and service:
#Injectable()
export class TablePageService {
public data: Array<any>;
constructor() {
console.log(this.data);
// undefined
}
}
Getting data is undefined. How to make it works?

An example if interaction between service and component could be:
Service:
#Injectable()
export class MyService {
myMethod$: Observable<any>;
private myMethodSubject = new Subject<any>();
constructor() {
this.myMethod$ = this.myMethodSubject.asObservable();
}
myMethod(data) {
console.log(data); // I have data! Let's return it so subscribers can use it!
// we can do stuff with data if we want
this.myMethodSubject.next(data);
}
}
Component1 (sender):
export class SomeComponent {
public data: Array<any> = MyData;
public constructor(private myService: MyService) {
this.myService.myMethod(this.data);
}
}
Component2 (receiver):
export class SomeComponent2 {
public data: Array<any> = MyData;
public constructor(private myService: MyService) {
this.myService.myMethod$.subscribe((data) => {
this.data = data; // And he have data here too!
}
);
}
}
Explanation:
MyService is managing the data. You can still do stuff with data if you want, but is better to leave that to Component2.
Basically MyService receives data from Component1 and sends it to whoever is subscribed to the method myMethod().
Component1 is sending data to the MyService and that's all he does.
Component2 is subscribed to the myMethod() so each time myMethod() get called, Component2 will listen and get whatever myMethod() is returning.

There is a small issue with the receiver component in #SrAxi s reply as it can't subscribe to the service data. Consider using BehaviorSubject instead of Subject. It worked for me!
private myMethodSubject = new BehaviorSubject<any>("");

Related

How to publish event from a component and receive it from another component in nativescript

How can I publish custom event from a component and receive it from another component in nativescript.
something like:
ComponentOne.ts
this.event.publish('someEvent', {name: 'a name'})
ComponentTwo.ts
this.event.subscribe('someEvent', (data) => {
const name = data.name;
})
You can use subject for this case
import { Injectable } from "#angular/core";
import { Subject } from "rxjs";
#Injectable()
export class MessageService {
private subject = new Subject<any>();
constructor() {}
sendMessage(message: any) {
this.subject.next(message);
}
getData() {
return this.subject.asObservable();
}
}
I defined 2 method here. The first method using next() to send message to the next subcriber. So in your component you just need to simply subscribe like this to get the data
private subscription$: Subscription;
public ngOnInit(): void {
this.subscription$ = this.messageervice
.getData()
.subscribe(data => { console.log(data); })
}
public ngOnDestroy(): void {
this.subscription$.unsubscribe();
}
Found a workaround.
the basic idea is to register a custom event on the root frame of the app and listen on it from the other components
ComponentOne.ts
frameModule.topmost().notify({
eventName: 'punched',
object: frameModule.topmost(),
})
ComponentTwo.ts
frameModule.topmost().on('punched', () => {
console.log('event received');
})

How can I create an instance of a service (injectable) with Angular inside a class

import { Store } from '#ngxs/store';
export class Service {
constructor(private _store: Store) {}
}
export abstract class A {
constructor( private _service: Service ) { }
}
export class B extends A {
constructor( private _service: Service ) {
super(_service);
}
}
I'd like to avoid B (and other 10 classes like B) to declare and pass that service to A.
I was reading about using ReflectiveInjector, but apparently it works only when all providers got #Injectable() decorator, which is not provided in Store.
Any idea if and how is doable?
You can make an instance of a class if you also insert the dependency:
public store: Store = new Store()
public service: Service = new Service(this.store);

Confusing while Passing data between the components

I am new in angular 6, I am creating the project using angular 6. I am coming to the problem while sharing the data.
Here is my code:
1) Component Sidebar:
selectedCategory(type:any) {
this.loginService.categoryType = type; // need to pass this data
}
2) List Comp:
export class ListPostsComponent implements OnInit {
ngOnInit() {
// here I need the data
}
}
3) Service:
export class LoginService {
categoryType:any;
}
In your service make categoryType a Subject and call the next() when you need to pass data to another component:
#Injectable({
providedIn: 'root',
})
export class LoginService {
private categoryType: Subject<any> = new Subject<any>();
public categoryType$ = this.categoryType.asObservable();
public sendData(data: any){
this.categoryType.next(data);
}
}
Now in your Component Sidebar, you need to inject the service LoginService and call the sendData method:
constructor(private loginService: LoginService ){ }
selectedCategory(type:any) {
this.loginService.sendData(type);
}
Since a Subject is both an Observer and an Observable you can subscribe to the Subject and listen for changes in the component you wish to receive the data:
export class ListPostsComponent implements OnInit {
constructor(private loginService: LoginService ){ }
ngOnInit() {
this.loginService.categoryType$.subscribe((data) => {
//use your data here
});
}
}
Here is a working example of the above solution in Stackblitz: https://stackblitz.com/edit/angular-2sld4k?file=src%2Fapp%2Floginservice.service.ts

Angular 2+ testing a component

I have the following service which make a call to an API :
export class MoviesService {
constructor(private httpClient: HttpClient) { }
// Return an obsevable with all the movies from the API
getAllMovies(): Observable<Movie[]> {
return this.httpClient.get<EmbeddedTitle>("http://localhost:8080/api/movies", { params: params })
.pipe(
map(response => {
return response;
}
));
}
And here's the component that inject that service and call the getAllMovies method:
export class MoviesListingComponent implements OnInit {
public movies: Movie[];
constructor(private moviesService: MoviesService) { }
ngOnInit(): void {
this.getAllMovies();
}
// Subscribe to method service (getAllMovies) and assign the results to a class object (movies)
getAllMovies(): void {
this.moviesService.getAllMovies()
.subscribe(movies => {
this.movies = movies;
});
}
}
I want to know how to unit testing the component's method getAllMovies with Jasmine.
the method getAllMovies() changes the value of your "movies" variable and you component has a dependency to the service that hold the data, your job is mock the service and create a getAllMovies that return dummy data and make sure that your movie field hold the data that you mock

Angular How to bind service instance and keep it in different classes

How can i pass a service method in a super class from a sub class?
I have next service
import { Injectable, Injector } from '#angular/core';
import { HttpParams } from '#angular/common/http';
import 'rxjs/add/operator/map';
#Injectable
export class MyService {
constructor(private http: Httpclient) {}
getData(param1: string, param2: string): Observable<Model>{
let params = new HttpParams();
{...}
return this.http.get<Model>(this.baseUrl, { params })
.map((data) => new Model());
}
}
Class A as super class
export ClassA implements OnChanges {
constructor(private _serviceMethod: (param1: string, param2: string) => Observable<Model>){}
ngOnChanges() {
this.getData(somedata, somedata);
}
getData(param1?: string, param2?: string) {
this._serviceMethod(param1, param2)
.subscribe((response: Model) => {
this.data = response;
}, (error) => {
{...}
});
}
}
and ClassBComponent as sub class
#Component({
selector: 'class-b',
templateUrl: 'class-b.component.html',
styleUrls: ['class-b.component.css'],
})
export ClassBComponent extends ClassA {
constructor(private myService: MyService){
super(myService.getData);
}
}
ClassBComponent is one of many components that extends ClassA and share some logic in getData(somedata, somedata) method of ClassA. Now, if i do that
this.http.get in MyService throw "TypeError: Cannot read property 'get' of undefined". My http of type HttClient is undefined even if is injected in MyService constructor because 'this' in MyService does not get reference of service anymore and points at ClassBComponent. How can i bind the instance of MyService and used it when i pass the methods in super() of sub classes? Do you have any idea how can i do that? Thank you :)
If a function is supposed to be used as a callback (event listener, etc.), it preferably should be bound on class construction, e.g. with bind or arrow function.
Since getData isn't supposed to be a callback but is used like one, it should be bound in-place:
export ClassBComponent extends ClassA {
constructor(private myService: MyService){
super(myService.getData.bind(myService));
}
}

Categories

Resources