Angular returns undefined - javascript

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;
}
}

Related

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));
}
}

event after asyn function finished in typescript

hi i made a simple ionic app to connect to an api as the instruction at here :
https://www.freecodecamp.org/news/how-to-build-your-first-ionic-4-app-with-api-calls-f6ea747dc17a/
u have a service like this:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class MovieService {
url = 'http://www.omdbapi.com/';
apiKey = '';
constructor(private http: HttpClient) { }
searchData(title: string): Observable<any> {
return this.http.get(`${this.url}?s=${encodeURI(title)}&apikey=${this.apiKey}`).pipe(
map(results => results['Search'])
);
}
}
also I have another page.ts which works like this:
import { MovieService, SearchType } from './../../services/movie.service';
import { Component, OnInit } from '#angular/core';
import { Observable } from 'rxjs';
#Component({
selector: 'app-movies',
templateUrl: './movies.page.html',
styleUrls: ['./movies.page.scss'],
})
export class MoviesPage implements OnInit {
results: Observable<any>;
searchTerm: string = '';
constructor(private movieService: MovieService) { }
ngOnInit() { }
doSearch() {
this.results = this.movieService.searchData(this.searchTerm);
}
}
how can I launch an event like for example navigate to another page when doSearch finished it's job?
because if i use like this:
doSearch() {
this.results = this.movieService.searchData(this.searchTerm);
alert("fin");
}
the alert show up although the result job is still working
You just need to make desirable changes inside subscribe method.
doSearch() {
this.movieService.searchData(this.searchTerm).subscribe(result
=> {
alert("fin");
});
}

Angular: Can't return value

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:
Informacije component:
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() {
return this.restaurantService.getRestaurant(this.restaurantID).toPromise().then(data => {
this.loggedRestaurant = data;
});
}
async ngOnInit() {
await this.restaurantService.getRestaurant(this.restaurantID).subscribe(
data => {
this.loggedRestaurant = data;
console.log(this.loggedRestaurant)
})
this.restaurant = this.authService.currRestaurant[0];
console.log(this.restaurant)
console.log(this.loggedRestaurant)
console.log(this.restaurantService.restaurantID)
}
}
restaurant.service
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 = 'xxxxxx';
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 razmak' + this.restaurantID);
return this.http.post<LoggedRestaurant>(this.restaurantUrl, ID);
}
}
auth.service
import { Injectable } from '#angular/core';
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '#angular/common/http';
import { throwError, Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { Restaurant } from '../models/Restaurant';
#Injectable({
providedIn: 'root'
})
export class AuthService {
loginUrl = 'xxxxx';
errorData: {};
constructor(private http: HttpClient) { }
redirectUrl: string;
login(email: string, password: string) {
var postData = {email: email, password: password};
return this.http.post<Restaurant>(this.loginUrl, postData)
.pipe(map(restaurant => {
if (restaurant) {
localStorage.setItem('currentRestaurant', JSON.stringify(restaurant));
return restaurant;
}
}),
catchError(this.handleError)
);
}
isLoggedIn() {
if (localStorage.getItem('currentRestaurant')) {
return true;
}
return false;
}
getAuthorizationToken() {
const currentRestaurant = JSON.parse(localStorage.getItem('currentRestaurant'));
return currentRestaurant.token;
}
logout() {
localStorage.removeItem('currentRestaurant');
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong.
console.error(`Backend returned code ${error.status}, ` + `body was: ${error.error}`);
}
// return an observable with a user-facing error message
this.errorData = {
errorTitle: 'Oops! Request for document failed',
errorDesc: 'Something bad happened. Please try again later.'
};
return throwError(this.errorData);
}
currRestaurant: Restaurant = JSON.parse(localStorage.getItem('currentRestaurant'));
currID = this. currRestaurant.id;
}
Being a post request, if you want to see the data you need to return the full response.
Add {observe: 'response'} to your request like so:
getRestaurant(ID): Observable<HttpResponse<LoggedRestaurant>> {
console.log('ID je razmak' + this.restaurantID);
return this.http.post<LoggedRestaurant>(this.restaurantUrl, ID, {observe:'response'});
}
and retrieve it like so:
this.restaurantService.getRestaurant(this.restaurantID).subscribe(
data => {
this.loggedRestaurant = data.body;
console.log(this.loggedRestaurant)
})
Let me know if that worked :)
Try like this:
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() {
return this.restaurantService.getRestaurant(this.restaurantID).toPromise().then(data => {
this.loggedRestaurant = data;
});
}
ngOnInit() {
this.restaurant = this.authService.currRestaurant[0];
this.restaurantService.getRestaurant(this.restaurantID).subscribe(
data => {
this.loggedRestaurant = data;
console.log(this.loggedRestaurant)
})
console.log(this.restaurant)
console.log(this.loggedRestaurant)
console.log(this.restaurantService.restaurantID)
}
}
restaurant.service
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 = 'xxxxxx';
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 razmak' + this.restaurantID);
return this.http.post<LoggedRestaurant>(this.restaurantUrl, ID);
}
}

Http call as service in Angular

I am brand new to Angular and I am attempting to make a simple http request for data. How do I access this data in my component? I am getting the error 'Cannot read property 'get' of undefined'
data.service.ts
import { Injectable } from '#angular/core'
import { HttpClient } from '#angular/common/http'
#Injectable()
export class FetchData {
private url: string = 'https://jsonplaceholder.typicode.com/users'
constructor(private http: HttpClient){}
get(){
return this.http.get(this.url).subscribe(data => {
console.log(data)
})
}
}
table.component.ts
import { FetchData } from './datatable.service';
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-datatable',
templateUrl: './datatable.component.html',
styleUrls: ['./datatable.component.css']
})
export class DatatableComponent implements OnInit {
Data: FetchData
constructor() { }
ngOnInit() {
this.Data.get()
}
}
You need to "Inject" the service in your component and also make the subscription in your component.
In your service you should "map" your response.
import { Injectable } from '#angular/core'
import { HttpClient } from '#angular/common/http'
import 'rxjs/add/operator/map';
#Injectable()
export class FetchData {
private url: string = 'https://jsonplaceholder.typicode.com/users'
constructor(private http: HttpClient){}
get(){
return this.http.get(this.url).map(data => {
return data.json();
})
}
}
Your component:
import { FetchData } from './datatable.service';
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-datatable',
templateUrl: './datatable.component.html',
styleUrls: ['./datatable.component.css']
})
export class DatatableComponent implements OnInit {
constructor(private fetchDataService: FetchData) { }
ngOnInit() {
this.fetchDataService.get().subscribe(res => {
console.log(response);
});
}
}
try this:
export class DatatableComponent implements OnInit {
constructor(private dataService: FetchData) { }
ngOnInit() {
this.dataService.get()
}}

GET http://localhost:4200/api/x.json 404 (Not Found) - angular 2

Hello, There is a problem with a project that does not recognize a json file - and I do not know why. Is there anything I need to change or make it work?
this is my folders:
this is my service:
import { Injectable } from "#angular/core";
import { Ibrides } from "./brides";
import { HttpClient, HttpErrorResponse } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
#Injectable()
export class brideService {
private _brideUrl = 'api/brides.json';
constructor(private _http: HttpClient) { };
getBrides(): Observable<Ibrides[]> {
return this._http.get<Ibrides[]>(this._brideUrl)
.do(data => console.log('All:' + JSON.stringify(data)))
.catch(this.handleError)
}
private handleError(err: HttpErrorResponse) {
console.log(err.message);
return Observable.throw(err.message);
}
}
this is my component
import { Component, OnInit } from '#angular/core';
import { Ibrides } from "./brides";
import { brideService } from "./brides.service"
#Component({
selector: 'pm-brides',
templateUrl: './brides_list.component.html',
styleUrls: []
})
export class bridesListComponent implements OnInit {
constructor(private _brideService: brideService) {
}
errorMessage: string;
brides: Ibrides[] = [];
ngOnInit(): void {
this._brideService.getBrides()
.subscribe(brides => {
this.brides = brides
},
error => this.errorMessage = <any>error);
}
}
Just reference the file from the root level like this:
_brideUrl = 'app/api/brides.json'
For more information you can refer to this.

Categories