I have an Angular and Node JS project with Typescript in which I am trying to create the communication between them using a service.
When making a get() request from the front I can't get anything from the back, I don't know what I might be missing to configure or what problem I have in the service.
This is the API response:
This is the service.ts:
import { Injectable } from "#angular/core";
import { HttpClient } from "#angular/common/http";
#Injectable({
providedIn: 'root'
})
export class DashboardService {
private url = 'http://localhost:8080/list/product'
constructor(
private http: HttpClient
) {}
public getTest() {
return this.http.get(`${this.url}`);
}
}
This is the component.ts where I am trying to display the message on the console:
import { Component, OnInit } from '#angular/core';
import { DashboardService } from './dashboard.service';
#Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit {
constructor(
private dashboardService: DashboardService
) {
}
ngOnInit() {
console.log('hola')
console.log(this.dashboardService.getTest().subscribe())
}
}
This is what I get on the console:
How should I do the GET() request to communicate with the back?
You are subscribing but then doing nothing with the subscription. I recomment you read up on angular subscriptions a bit more, but effectively what you want to do is get the result from the subscription like so.
items: string[];
this.dashboardService.getTest().subscribe({
next: result => items = result,
});
Also your get method in your service needs a bit of work.
public getTest(): Observable<string[]> {
return this.http.get<string[]>(`${this.url}`);
}
This is for returning a list of strings
Related
I'm trying to develop a healthcheck endpoint with NestJS (in which I have no experience). One of the dependencies I want to check is Twilio's SMS service. So far, the best URL I've found to gather this information is https://status.twilio.com/api/v2/status.json. The problem here is that I don't want to merely ping this address, but to gather it's JSON response and present some of the information it provides, namely these:
Is it possible, using (or not) the Terminus module? In the official docs I didn't find anything regarding this, only simpler examples using pingCheck / responseCheck: https://docs.nestjs.com/recipes/terminus
Yes, it is possible.
I have never used this, but HttpHealthIndicator has responseCheck method to check depends on the API response message. You can specify a callback function to analyze responses from the API. The callback function should return boolean represents the status of the API.
I couldn't find this in the documents, but you can see it here.
Although meanwhile the logic for this healthcheck has changed (and so this question became obsolete), this was the temporary solution I've found, before it happened (basically a regular endpoint using axios, as pointed out in one of the comments above):
Controller
import { Controller, Get } from '#nestjs/common';
import { TwilioStatusService } from './twilio-status.service';
#Controller('status')
export class TwilioStatusController {
constructor(private readonly twilioStatusService: TwilioStatusService) {}
#Get('twilio')
getTwilioStatus() {
const res = this.twilioStatusService.getTwilioStatus();
return res;
}
}
Service
import { HttpService } from '#nestjs/axios';
import { Injectable } from '#nestjs/common';
import { map } from 'rxjs/operators';
#Injectable()
export class TwilioStatusService {
constructor(private httpService: HttpService) {}
getTwilioStatus() {
return this.httpService
.get('https://status.twilio.com/api/v2/status.json')
.pipe(map((response) => response.data.status));
}
}
Of course this wasn't an optimal solution, since I had to do this endpoint + a separated one for checking MongoDB's availability (a regular NestJS healthcheck, using Terminus), the goal being an healthcheck that glued both endpoints together.
It is possible to merge in any property to the resulting object. You can see that in the TypeScript Interface
/**
* The result object of a health indicator
* #publicApi
*/
export declare type HealthIndicatorResult = {
/**
* The key of the health indicator which should be uniqe
*/
[key: string]: {
/**
* The status if the given health indicator was successful or not
*/
status: HealthIndicatorStatus;
/**
* Optional settings of the health indicator result
*/
[optionalKeys: string]: any;
};
};
And here is an example:
diagnostics/health/healthcheck.controller
import { Controller, Get } from '#nestjs/common'
import { ApiTags } from '#nestjs/swagger'
import { HttpService } from '#nestjs/axios'
import { HealthCheckService, HealthCheck, HealthIndicatorStatus, HealthCheckError } from '#nestjs/terminus'
#ApiTags('diagnostics')
#Controller('diagnostics/health')
export class HealthController {
constructor(
private health: HealthCheckService,
private httpService: HttpService,
) { }
#Get()
#HealthCheck()
check() {
return this.health.check([
() => this.httpService.get('http://localhost:9002/api/v1/diagnostics/health').toPromise().then(({ statusText, config: { url }, data }) => {
const status: HealthIndicatorStatus = statusText === 'OK' ? 'up' : 'down'
return { 'other-service': { status, url, data } }
}).catch(({ code, config: { url } }) => {
throw new HealthCheckError('Other service check failed', { 'other-service': { status: 'down', code, url } })
}),
])
}
}
diagnostics/diagnostics.module.ts
import { Module } from '#nestjs/common'
import { TerminusModule } from '#nestjs/terminus'
import { HttpModule } from '#nestjs/axios'
import { HealthController } from './health/health.controller'
#Module({
imports: [
HttpModule,
TerminusModule,
],
controllers: [HealthController],
})
export class DiagnosticsModule { }
I'm here because I do not understand how Http works in angular. I would create a "news" thread on my website. To do that I have created a service in my angular app that calls a .net core web API.
Also, I would add a paginate to my thread (I want to display news by 5 on the page).
I can get my values, that is not my issue here. But, to create my paginate, I need to have values for number of pages calculation.
I tried to add code to create my paginate (number of pages, number of elements...) but I always get 0 to these values and my array of news is filled after the onInit(). This is what I don't understand.
This is my component:
import { Component, OnInit, OnDestroy } from '#angular/core';
import { NewsService } from '../news.service';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
title = 'News';
news = [];
displayed = [];
numberOfPages = 0;
constructor(private newsService: NewsService) { }
ngOnInit() {
// I don't really understand these lines (mainly the subscribe part)
this.newsService.getAllNews().subscribe((data) => {
this.news = Array.from(Object.keys(data), k => data[k]);
// this console.log appears after the onInit(), why ?
console.log(this.news);
});
this.numberOfPages = this.news.length / 5; // Get 0 here, why ?
}
}
My service:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class NewsService {
private finalData = [];
private apiUrl = 'https://localhost:5001/api/v1/posts';
constructor(private http: HttpClient) { }
getAllNews() {
return this.http.get(this.apiUrl);
}
}
In the browser console, I get this:
console screen
Maybe I forgot something in my code or I don't know what.
Someone can help me to achieve my goal? I want to understand how to proceed to make a working paginate for my news.
You should add
this.numberOfPages = this.news.length / 5;
inside the subscribe
this.newsService.getAllNews().subscribe((data) => {
this.news = Array.from(Object.keys(data), k => data[k]);
// this console.log appears after the onInit(), why ?
console.log(this.news);
});
like so:
this.newsService.getAllNews().subscribe((data) => {
this.news = Array.from(Object.keys(data), k => data[k]);
// this console.log appears after the onInit(), why ?
console.log(this.news);
this.numberOfPages = this.news.length / 5;
});
My guess is that when you try to initialise the this.numberOfPagesthe this.news.length is not yet set(data are not yet retrieved from the API). Hope this helps
I have been searching everywhere I could not find an answer on this. I'm passing a string on the url example. "localhost:4200/home/ABCD%2BrAD4Og%3D%3D" when I subscribe to the param or use snapshot I get something like "ABCD+rAD4Og=="
How do I get what was exactly passed? Thank you
I have found an answer. If you want to get the raw param that was passed all you have to do is use "encodeURIComponent(uri)"
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-example',
template: `<h1>raw URI example</h1>`,
styleUrls: ['./example.component.scss']
})
export class ExampleComponent implements OnInit {
constructor(private router: ActivatedRoute) {}
rawUri: string = null;
ngOnInit() {
this.router.params.subscribe(param => {
// the "id" part inside param[''] could be anything you defined in your route config file.
this.rawUri = encodeURIComponent(param['id']);
console.log('raw url param ', this.rawUri);
}
}
}
This question already has answers here:
How do I return the response from an Observable/http/async call in angular?
(10 answers)
Closed 5 years ago.
I have the following component:
import { Component, Input, OnInit } from '#angular/core';
import { ActivatedRoute, Params } from '#angular/router';
import 'rxjs/add/operator/switchMap';
import { ArticleStore } from '../../state/ArticleStore';
import { Article } from '../../models/article';
#Component({
selector: 'app-article-detail',
templateUrl: './article-detail.component.html',
styleUrls: ['./article-detail.component.css']
})
export class ArticleDetailComponent implements OnInit {
private article: Article;
constructor( private route: ActivatedRoute, private articleStore: ArticleStore ) { }
ngOnInit(): void {
this.route
.queryParamMap
.map((paramMap => paramMap.get('id') || 'None'))
.switchMap((id: string) => this.articleStore.getArticle(id))
.subscribe((article: Article) => {
this.article = new Article(article);
console.log(this.article) // <--returns full-filled object
});
console.log(this.article) // <-- undefined object
}
}
Inside the subscribe function, I get the proper object (this.article) and is what I expect. If I move down to after the this.route, it doesn't work. Should be straight forward to get the value assigned.
The whole project is here => https://github.com/flamusdiu/micro-blog
Edit
Kinda similar to How do I return the response from an Observable/http/async call in angular2?
I understand the async nature of the calls (actually more calls now-a-days are async).
When you nav to article/:id, it fires off the getArticle(id) function from the ArticleStore.ts
public getArticle (id: string) {
return this.pouchdbService.getArticle(id)
.then((res) => {return res.docs[0] });
}
This runs just fine. It pulls from my service:
public getArticle(id: string): Promise<any> {
return this._pouchDb.find({
selector: {_id: id }
});
}
In your application routes you should have something like:
{ path: '/articles/:id', component: ArticleDetailComponent},
Then your router will be able to act on the provided article route.
Also consider using a Resolver for getting data for the component before it is initialized. good luck with the blog :D
I've worked through the Angular superhero tutorial. It all works.
If i close the cmd window running NPM, then re-open a CMD window and reissue the NPM START command I get two errors
src/app/DashBoard.component.ts(12,44) TS2304 : Cannot find name 'OnInit'.
src/app/hero-list.component.ts(16, 434) TS2304 : Cannot find name 'OnInit'.
I can resolve this by removing
Implements OnInit
from both these classes,
run NPM start
re-add them (simply CTL Z in the editor)
make some change , save.
The app recompiles and I am off and running.
I have 4 classes that implement this function. I have studied them and can not figure out what makes 2 fail...
I have read posts that reference TS2304, but this seems to be a generic Function/Variable/Symbol not found message ...
I don't know what to post. I'm happy to post any of the code.
Is this caused by errors in modules this depends on (hero.ts)?
Here is one class that is failing in this manner.
This is the hero-list.component.ts file
(at various points in the demo/online examples, this is also named Heroes.component..)
import { Component } from '#angular/core';
import { Router } from '#angular/router';
import { Hero } from './hero';
import { HeroService } from './hero.service';
#Component({
selector: 'hero-list',
templateUrl: './hero-list.component.html' ,
providers: [HeroService],
styleUrls: [ './hero-list.component.css']
})
export class HeroListComponent implements OnInit {
heroes : Hero[];
selectedHero: Hero;
constructor(
private router : Router ,
private heroService: HeroService
) { }
ngOnInit(): void {
this.getHeroes();
}
onSelect(hero: Hero): void {
this.selectedHero = hero;
}
getHeroes(): void {
this.heroService.getHeroes().then(heroes => this.heroes = heroes);
}
gotoDetail() {
this.router.navigate(['/detail', this.selectedHero.id]);
}
add(name: string): void {
name = name.trim();
if (!name) { return; }
this.heroService.create(name)
.then(hero => {
this.heroes.push(hero);
this.selectedHero = null;
});
}
delete(hero: Hero): void {
this.heroService
.delete(hero.id)
.then(() => {
this.heroes = this.heroes.filter(h => h !== hero);
if (this.selectedHero === hero) { this.selectedHero = null; }
});
}
}
You have to import OnInit.
import { Component, OnInit } from '#angular/core';
The tutorial fails to mention that you need to add the import of OnInit to TypeScript file app.component.ts:
import { Component, OnInit } from '#angular/core';