Inject data from service to component - javascript

Currently, I'm using Rx.JS and Angular 7. My problem contains with the issue in Observable.
The problem is I can't fetch data from service to form-code.component.
After I've used setShortCode() there isset data, but in form-code.component.ts i can't see seebscribe() data
shortcode.service.ts
import { Injectable, NgZone } from '#angular/core';
import { Subject, Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class ShortcodeService {
public shortcode = new Subject<any>();
constructor(private zone: NgZone) {}
setShortCode(code) {
this.zone.run(() => {
this.shortcode.next(code);
});
}
getShortCode(): Observable<any> {
return this.shortcode.asObservable();
}
}
dnd.component.ts
this.textAreaText = `<iframe src="${window.location.origin +
'/form/' +
project.id}/design" width="100%" height="500px" frameborder="0"></iframe>`;
this.shortCodeService.setShortCode(this.textAreaText);
this.router.navigate(['/form-copy']);
form-code.components.ts
import { Component, OnInit, OnDestroy, AfterViewInit } from '#angular/core';
import { ShortcodeService } from '../../services/shortcode.service';
import { DomSanitizer, SafeHtml } from '#angular/platform-browser';
import { Subscription } from 'rxjs';
#Component({
selector: 'app-form-code',
templateUrl: './form-code.component.html',
styleUrls: ['./form-code.component.scss']
})
export class FormCodeComponent implements OnInit, OnDestroy {
constructor(
private sanitizer: DomSanitizer,
private shortCodeService: ShortcodeService
) {}
shortText: string;
sub: Subscription;
ngOnInit() {
this.sub = this.shortCodeService.getShortCode().subscribe(
shortcode => {
console.log(shortcode);
this.shortText = shortcode;
},
error => console.log(error),
() => {}
);
}
ngOnDestroy(): void {
//Called once, before the instance is destroyed.
//Add 'implements OnDestroy' to the class.
this.sub.unsubscribe();
}
}

Working, When I changed Subject to BehaviorSubject

Related

How do I push data from a Subject observable to an array in the component?

I am trying to push a message into an array that is already declared as a variable in the component. I am using a service and have created a subject observable to take data from one component and inject it into another component. When I try to push the data onto the array after subscribing to the variable, it's updated temporarily but when I open that component, the data is not pushed. The array updates when I console log from inside the subscribe method but it's reset once I open that component. I don't know what is the problem. This is the code:
Service.ts
import { Injectable } from '#angular/core';
import { User } from './user';
import { Subject } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class SerService {
private message = new Subject<string>();
sourceMessage$ = this.message.asObservable();
constructor() { }
sendMessage(message: string) {
this.message.next(message);
}
}
Receiver component
import { Component, OnInit } from '#angular/core';
import { SerService } from '../ser.service';
import { User } from "../user";
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
public messages = ['hi', 'hello', 'bye'];
constructor(private _service: Service) { }
ngOnInit() {
this._service.message$
.subscribe(
message => {
this.messages.push(message);
}
);
}
}
Sender Component
import { Component, OnInit } from '#angular/core';
import { SerService } from '../ser.service';
import { User } from '../user';
#Component({
selector: 'app-sign-up',
templateUrl: './sign-up.component.html',
styleUrls: ['./sign-up.component.css']
})
export class SignUpComponent {
userModel = new User('', '', '', '', false);
constructor (private _service : SerService) {}
onSubmit(){
this._service.sendMessage(this.userModel.message);
}
}
I can't update the message array. How do I do this with minimal changes?
You can create a service to send data from one component to another by using BehaviourSubject
Service:
import { Injectable } from '#angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
#Injectable({
providedIn: 'root'
})
export class DataService {
private userDetails = new BehaviorSubject<any>('');
currentUserDetails = this.userDetails.asObservable();
constructor() { }
sendUserDetails(message){
this.userDetails.next(message)
}
}
Sender Component:
import { DataService } from '/services/data.service';
export class SignupComponent implements OnInit {
public userDetails;
constructor(private _dataService: DataService) {}
ngOnInit(){
userDetails = new User('', '', '', '', false);
this._dataService.sendUserDetails(this.userDetails);
}
}
Receiver Component
import { DataService } from '/services/data.service';
export class LoginComponent implements OnInit {
public userDetails;
constructor(private _dataService: DataService) {}
ngOnInit(): void {
this._dataService.currentUserDetails.subscribe(userDetails => this.userDetails = userDetails);
}
Blockquote

Angular9:core.js:6228 ERROR Error: Uncaught (in promise): Error: Can't resolve all parameters for Subscription: (?)

I'm a newbie and learning Angular.
I want to pass data between two components (not a parent-child component). I write a service.ts file to achieve it then met this error. I have found a lot in Stackoverflow, but seems no effects.
I don't know what went wrong, so I will put all the code out.
Below is the code.
By the way, how to solve "It looks like your post is mostly code; please add some more details."?
//service
import { Injectable } from '#angular/core';
import {Observable} from 'rxjs';
import { Subject } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class TransfermessageService {
public receiveMsg:any;
constructor() { }
public subject = new Subject<any>();
sendMessage(message: any) {
this.subject.next({ text: message });
}
clearMessage() {
this.subject.next();
}
getMessage(): Observable<any> {
return this.subject.asObservable();
}
}
//component 1
import { Component, OnInit } from '#angular/core';
import {RequestService} from '../../../services/request/request.service';
import {Router,NavigationStart, GuardsCheckEnd,ResolveStart,NavigationError, Event as NavigationEvent } from '#angular/router';
import {TransfermessageService} from '../../../services/common/transfermessage/transfermessage.service';
#Component({
selector: 'app-login-session-code',
templateUrl: './login-session-code.component.html',
styleUrls: ['./login-session-code.component.scss'],
})
export class LoginSessionCodeComponent implements OnInit {
public riskRole: string = localStorage.getItem('userRole');
public sessioncode: any;
public token_user: any;
constructor(
public RS: RequestService,
public router: Router,
public TMS: TransfermessageService,
) {
}
ngOnInit(){
}
checkInputCall(){
const api = this.RS.baseURL+ '/login/checkInput';
const token_api= this.RS.baseURL+ '/login/checkToken';
const parameters:object = {
"email": localStorage.getItem('email'),
"input": this.sessioncode,
"type": localStorage.getItem('type')
}
this.RS.checkInput(api,parameters).subscribe(res => {
if(res['data'].input_check) {
localStorage.setItem('checkInput', JSON.stringify(res['data']));
this.RS.checkToken(token_api,{"token": res['data'].user.token}).subscribe(res => {
this.token_user = res;
this.TMS.sendMessage({"ss": "ssss"});
this.router.navigate(['/home']);
// console.log(res); //return token_user
})
}else {
alert("session code is not true");
}
})
}
ngAfterViewChecked(): void {
this.router.events.subscribe((event: NavigationEvent) => {
if(event instanceof NavigationStart) {
console.log(event);
}
});
this.router.events.subscribe((event: NavigationEvent) => {
if(event instanceof GuardsCheckEnd) {
console.log(event,'GuardsCheckEnd');
}
});
this.router.events.subscribe((event: NavigationEvent) => {
if(event instanceof NavigationError) {
console.log(event,'NavigationError');
}
});
}
}
//components 2
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import {TransfermessageService} from '../../services/common/transfermessage/transfermessage.service';
import {Subscription} from 'rxjs';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss'],
providers: [TransfermessageService]
})
export class HomeComponent implements OnInit {
public ctrlHomeDetailTag: boolean = true;
public ctrlHomeBasicTag: boolean = true;
public ctrlTags: boolean = true;
public receiveMsg: any;
constructor(
public router: Router,
public TMS: TransfermessageService,
public Subscription: Subscription
) {
}
ngOnInit(): void {
console.log('home page');
const receiveMsg = this.TMS.getMessage();
console.log(receiveMsg,'parameters');
}
// ngAfterViewInit():void {
// this.Subscription = this.TMS.getMessage().subscribe(message => {
// this.receiveMsg = JSON.parse(message);
// console.log('this.receiveMsg', this.receiveMsg);
// })
//}
ngonChanges() {
}
ngDoCheck() {
}
ngOnDestroy(): void {
// this.Subscription.unsubscribe();
}
}

Trigger function with event emitter

Is it possible to trigger a function in another component from the current component with EventEmitter, as sort of a callback? For example, after I finish the API request a success function occurs, like so:
#Output() afterAPIRequest = new EventEmitter();
handleSuccess() {
this.afterAPIRequest.emit();
}
Now, can I catch that somehow in another component and trigger another function, something like this?
// when emitted, run this
refreshListIfEmitted() {
this.refreshMyList();
}
use a service
import { Injectable } from '#angular/core';
import { Observable, Subject } from 'rxjs';
#Injectable()
export class MessageService {
private _message: Subject<any>;
constructor() {
this._message = new Subject();
}
get changes(): Observable<any> {
return this._message.asObservable();
}
set message(message: any) {
this._message.next(message);
}
}
component one
import { Component } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'app-one',
templateUrl: './one.component.html',
styleUrls: ['./one.component.scss'],
})
export class OneComponent {
constructor(private _http: HttpClient, private _message: MessageService) { }
apiRequest(): void {
this._http.get('end-point').subscribe(value => this._message.message = value);
}
}
component two
import { Component } from '#angular/core';
#Component({
selector: 'app-two',
templateUrl: './two.component.html',
styleUrls: ['./two.component.scss'],
})
export class TwoComponent {
constructor(private _message: MessageService) {
this._message.changes.subscribe(value => console.log(value));
}
}

Angular returns undefined

I have API for getting information about one specific restaurant in the database, but I have to get it with a POST request. I successfully get restaurantID from auth.service and another API when the restaurant is logged in, But when I tried to log restaurant in console, I get undefined. Uniformly I don't have permission to show API here. The code:
restaurant.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Restaurant } from '../models/Restaurant';
import { LoggedRestaurant } from '../models/LoggedRestaurant';
import { AuthService } from './auth.service'
#Injectable({
providedIn: 'root'
})
export class RestaurantService {
private restaurantUrl = 'https://dm.dnevnimeni.com/dmnew/podacirestorana.php';
public restaurant: Restaurant;
public loggedRestaurant: LoggedRestaurant
public restaurantID = this.authService.currRestaurant[0].id
constructor(private http: HttpClient, private authService: AuthService) { }
getRestaurant(ID): Observable<LoggedRestaurant> {
console.log('ID je' + this.restaurantID);
return this.http.post<LoggedRestaurant>(this.restaurantUrl, ID);
}
}
informacije.component.ts
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../services/auth.service';
import { RestaurantService } from '../services/restaurant.service';
import { Restaurant } from '../models/Restaurant';
import { LoggedRestaurant } from '../models/LoggedRestaurant';
import { Observable } from 'rxjs';
#Component({
selector: 'app-informacije',
templateUrl: './informacije.component.html',
styleUrls: ['./informacije.component.scss']
})
export class InformacijeComponent implements OnInit {
restaurant: Restaurant;
loggedRestaurant: LoggedRestaurant;
restaurantID = this.authService.currRestaurant[0].id;;
constructor(private restaurantService: RestaurantService, private authService: AuthService ) { }
getRestaurant() {
this.restaurantService.getRestaurant().subscribe(data => {
this.loggedRestaurant = data;
});
}
ngOnInit() {
this.getRestaurant();
this.restaurant = this.authService.currRestaurant[0];
console.log(this.restaurant)
console.log(this.loggedRestaurant)
this.restaurantID = this.restaurant.id;
console.log(this.restaurantID)
this.restaurantService.restaurantID =this.restaurantID;
}
}
Update
Your code should be like this
Since you just need to get data you dont have to use post
so you can change from this
return this.http.post<LoggedRestaurant>(this.restaurantUrl, this.restaurantID);
to this
return this.http.get<LoggedRestaurant>(`${this.restaurantUrl}/${this.restaurantID}`);
and add in ngOnInit
ngOnInit() {
this.restaurantService.getRestaurant().subscribe(data => {
this.loggedRestaurant = data;
// do something else
});
Because your getRestaurant() method is not called in ngOnInit life cycle hook so the data is not avaibled
You have a few issues with your code. First, you never actually call the getRestaurant() function, thus the service call will never be requested.
Second, you're dealing with asynchronous code and can't expect the service call to be complete before the console.log(this.loggedRestaurant) is run.
My suggestion is that you change your function to return an Observable<LoggedRestaurant> and subscribe to that.
getRestaurant(): Observable<LoggedRestaurant> {
this.restaurantService.getRestaurant().subscribe(data => {
this.loggedRestaurant = data;
});
}
Then you can use it as
ngOnInit() {
this.getRestaurant().subscribe(loggedRestaurant => {
console.log(loggedRestaurant);
});
}
Try this:
informacije.component.ts
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../services/auth.service';
import { RestaurantService } from '../services/restaurant.service';
import { Restaurant } from '../models/Restaurant';
import { LoggedRestaurant } from '../models/LoggedRestaurant';
import { Observable } from 'rxjs';
#Component({
selector: 'app-informacije',
templateUrl: './informacije.component.html',
styleUrls: ['./informacije.component.scss']
})
export class InformacijeComponent implements OnInit {
restaurant: Restaurant;
loggedRestaurant: LoggedRestaurant;
restaurantID;
constructor(private restaurantService: RestaurantService, private authService: AuthService ) { }
getRestaurant() {
this.restaurantService.getRestaurant().subscribe(data => {
this.loggedRestaurant = data;
});
}
ngOnInit() {
this.getRestaurant(); // add this line
this.restaurant = this.authService.currRestaurant[0];
console.log(this.restaurant)
console.log(this.loggedRestaurant)
this.restaurantID = this.restaurant.id;
console.log(this.restaurantID)
this.restaurantService.restaurantID =this.restaurantID;
}
}

Angular re-fetch data after parameter change GET request

How to re-fetch data after parameter change from:
oglas/1 to oglas/2 by click, so when put URL and than click ENTER everything works, but when click on oglas/2 button when oglas/1 is rendered URL changes to oglas/2 but data is from oglas/1?
TS
import { Component, OnInit } from "#angular/core";
import { ActivatedRoute } from "#angular/router";
import { Post } from "../post.model";
import { ServerService } from "../server.service";
#Component({
selector: "post",
templateUrl: "./post.component.html",
styleUrls: ["./post.component.css"]
})
export class PostComponent implements OnInit {
post: Post[];
constructor(
private route: ActivatedRoute,
private serverService: ServerService
) {}
ngOnInit(): void {
this.getPost();
}
getPost(): void {
const id = +this.route.snapshot.paramMap.get("id");
this.serverService.getPosts(id).subscribe(post => (this.post = post));
}
}
Service
import { HttpClient } from "#angular/common/http";
import { Injectable } from "#angular/core";
import { Post } from "./post.model";
import { User } from "./user.model";
import { Observable } from "rxjs";
#Injectable({ providedIn: "root" })
export class ServerService {
usersUrl = "http://localhost:3000/users";
postsUrl = "http://localhost:3000/posts";
constructor(private http: HttpClient) {}
getPosts(id: number | string): Observable<Post[]> {
const url = `${this.postsUrl}/${id}`;
return this.http.get<Post[]>(url);
}
getUser(id: number | string): Observable<User[]> {
const url = `${this.usersUrl}/${id}`;
return this.http.get<User[]>(url);
}
}
Since your are making an API call for data in ngOnInit(), requested data may not be available by the time your component loads. And Angular might be reusing the same instance of the component, making ngOnInit() to be called only once.
You can use Angular Resolvers to ensure that you have the required data before loading the component.
1) Create a route resolver to fetch the required data before loading the route.
PostDataResolver.ts:
// ... imports
#Injectable()
export class PostDataResolver implements Resolve<any> {
constructor(private serverService: ServerService) {}
resolve(route: ActivatedRouteSnapshot) {
const id = route.paramMap.get('id');
return this.serverService.getPosts(id);
}
}
2) Add this resolver to your routing module:
{ path: "oglas/:id", component: PostComponent, resolve: { postData: PostDataResolver }}
3) Then access the resolved data in your component.
PostComponent.ts:
export class PostComponent implements OnInit {
post: Post[];
constructor(
private route: ActivatedRoute,
private serverService: ServerService
) {}
ngOnInit(): void {
this.post = this.route.snapshot.data.postData;
}
}
This ensures that you have the latest and appropriate data before the component loads.
Got it...
import { Component, OnInit, OnChanges } from "#angular/core";
import { ActivatedRoute, Router } from "#angular/router";
import { Post } from "../post.model";
import { ServerService } from "../server.service";
#Component({
selector: "post",
templateUrl: "./post.component.html",
styleUrls: ["./post.component.css"]
})
export class PostComponent implements OnInit {
post: Post[];
id: number;
constructor(
private route: ActivatedRoute,
private serverService: ServerService
) {}
ngOnInit(): void {
this.route.paramMap.subscribe(params => {
this.id = parseInt(params.get("id"));
this.getPost(this.id);
});
}
getPost(id: number): void {
this.serverService.getPosts(id).subscribe(post => (this.post = post));
}
}
This code re-fetch data to a component
ngOnInit(): void {
this.route.paramMap.subscribe(params => {
this.id = parseInt(params.get("id"));
this.getPost(this.id);
});
}
Thank you all for your effort!

Categories