I am learning Angular and trying to consume an online web API in which I have app.module.ts, a service file, a model named comments, app.component.ts and app.component.html files
I am trying to show posts in my browser from the online web API from https://jsonplaceholder.typicode.com/posts/1/comments URL.
My code compiles successfully, but doesn't show any data in the browser and I can't find any errors. I am working in Angular 8/9. My code is below.
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpClientModule } from '#angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { FreeapiService } from './services/freeapi.service';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule
],
providers: [FreeapiService],
bootstrap: [AppComponent]
})
export class AppModule { }
freeapi.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class FreeapiService {
constructor(private http: HttpClient) { }
getComments(): Observable<any> {
return this.http.get("https://jsonplaceholder.typicode.com/posts/1/comments")
}
}
Comments Class
export class Comments {
postId: number;
id: number;
name: string;
email: string;
body: string;
}
App.component.ts
import { Component, OnInit } from '#angular/core';
import { FreeapiService } from './services/freeapi.service';
import { Comments } from './classes/comments';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'angular-apicall';
constructor(private _freeApiService: FreeapiService) { }
istComments: Comments[];
ngOnInt() {
this._freeApiService.getComments()
.subscribe
(
data => {
this.istComments = data;
}
);
console.log("This is working");
}
}
This my app.component.html file in which I want to show data in a table, but only show header
<table>
<tr>
<th>ID</th>
<th>Post Id</th>
<th>Name</th>
<th>Email</th>
<th>Body</th>
</tr>
<tr *ngFor="let com of istComments">
<td>{{com.id}}</td>
<td>{{com.postId}}</td>
<td>{{com.name}}</td>
<td>{{com.email}}</td>`enter code here`
<td>{{com.body]}</td>
</tr>
</table>
What am I missing?
Related
Seems like an obvious design decision for me but i can't seem to find any info on how to implement it.
I did the following:
created /pages folder and turned components in to modules for routing
created /components folder for components only
src/app/components/footer/footer.component.ts :
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-footer',
templateUrl: './footer.component.html',
styleUrls: ['./footer.component.css']
})
export class FooterComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
src/app/pages/home/home.component.ts :
import { Component, OnInit } from '#angular/core';
import { TranslateConfigService } from 'src/app/services/translate-config.service';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor(private translateConfigService: TranslateConfigService) { }
ngOnInit(): void {
}
}
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { RouterModule } from '#angular/router';
import { HomeRoutes } from './home.routes';
import { TranslateModule } from '#ngx-translate/core';
import { HomeComponent } from './home.component';
import { FooterComponent } from 'src/app/components/footer/footer.component';
#NgModule({
declarations: [
HomeComponent,
FooterComponent,
],
exports: [HomeComponent],
imports: [
CommonModule,
RouterModule.forChild(HomeRoutes),
TranslateModule
]
})
export class HomeModule { }
I didn't import anything explicitly, but when i try to use from /components in some page's html - i get an error saying
Error: src/app/pages/terms/terms.component.html:391:1 - error NG8001: 'app-footer' is not a known element:
1. If 'app-footer' is an Angular component, then verify that it is part of this module.
2. If 'app-footer' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.
I used following links https://grokonez.com/python/django-angular-6-example-django-rest-framework-mysql-crud-example-part-2-django-server and https://grokonez.com/frontend/django-angular-6-example-django-rest-framework-angular-crud-mysql-example-part-3-angular-client to create a django rest API and angular app that calls this rest.
Considering that I'm new in such kind of development so I created as a first step an App that just displays customers list.
Django rest API is fine working. I tested it with the browser:
But my problem is with the angular app, seems that it's not able to get message with the same URL: http://localhost:8000/customers
Below is my angular code:
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpClientModule } from '#angular/common/http';
import { AppRoutingModule, routingComponents } from './app-routing.module';
import { AppComponent } from './app.component';
import { CustomersListComponent } from './customers-list/customers-list.component';
#NgModule({
declarations: [
AppComponent,
routingComponents,
CustomersListComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { CustomersListComponent } from './customers-list/customers-list.component';
const routes: Routes = [
{ path: 'customers', component: CustomersListComponent },
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
customer.ts
export class Customer {
id: number;
name: string;
age: number;
active: boolean;
}
customer.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class CustomerService {
private baseUrl = 'http://localhost:8000/customers';
constructor(private http: HttpClient) { }
getCustomersList(): Observable<any> {
return this.http.get(`${this.baseUrl}/`);
}
}
customers-list.component.ts
import { Component, OnInit, Input } from '#angular/core';
import { Observable } from 'rxjs';
import { CustomerService } from '../customer.service';
import { Customer } from '../customer';
#Component({
selector: 'app-customers-list',
templateUrl: './customers-list.component.html',
styleUrls: ['./customers-list.component.css']
})
export class CustomersListComponent implements OnInit {
customers: Observable<Customer[]>;
constructor(private customerService: CustomerService) { }
ngOnInit() {
console.log("Hellllllllo from customers-list.component.ts ngOnInit");
this.reloadData();
}
reloadData() {
this.customers= this.customerService.getCustomersList();
}
}
customers-list.component.html
<h1>Customers {{JSON.stringify(this.customers)}}</h1>
<div *ngFor="let customer of customers" style="width: 300px;">
<h2>Hello iii</h2>
<div>
<label>Name: </label> {{customer.name}}
</div>
<div>
<label>Age: </label> {{customer.age}}
</div>
<div>
<label>Active: </label> {{customer.active}}
</div>
</div>
The result that got when calling /customers from the browser is the following:
"Routing and Navigation" message is coming from app.component.html
As you can see message Customers is displayed but everything that corresponds to the variable customers (which is the list of customers) is not displayed.
Has someone an idea what's the main cause of this issue? and how I can fix it?
Thank you in advance
You should subscribe to get the response from the API because http.get returns an observable, observable invokes only when you subscribe to it. try the following method
reloadData() {
this.customerService.getCustomersList().subscribe((res: any) => {
this.customers = res;
});
}
In your service
getCustomersList(): Observable<any> {
return this.http.get(`${this.baseUrl}/`);
}
This function returns an observable
So you should subscribe to it like this to make the request
this.customerService.getCustomersList().subscribe((res: any) => {
this.customers = res;
});
Or in your html file you can add async pipe like this
*ngFor="let customer of customers | async
I'm currently working on a nativescript/angular/typescript project and I'm basically trying to pass JSON data from one view (property) to another (propertyinfo).
First, I load up a JSON file in property.service.ts:
import { Injectable } from '#angular/core';
import { HttpClientModule, HttpClient } from '#angular/common/http';
#Injectable()
export class PropertyService {
public propertyData: any;
public selectedProperty: any;
constructor(private http: HttpClient) {
this.loadProperties();
}
loadProperties() {
this.http.get('/pages/property/property.json').subscribe(
(data) => {
this.propertyData = data;
}
)
}
}
This JSON data gets displayed in a view property.component.html:
<StackLayout *ngFor="let item of propertyData" class="list-group" xstyle="height: 300">
<GridLayout rows="110" columns="*, 40" (tap)="details(item)">
<StackLayout row="0" col="0">
<Label text="{{item.streetName}} {{item.houseNumber}}" class="text-primary p-l-30 p-t-5"></Label>
<Label text="{{item.etc}} {{item.etc}}" class="text-primary p-l-30 p-t-5"></Label>
</StackLayout>
<Label row="0" col="1" text="" class="fa arrow" verticalAlignment="middle"></Label>
</GridLayout>
<StackLayout class="hr-light"></StackLayout>
Here, the (tap)="details(item)" will call a function in property.component.ts:
import { Component, OnInit } from '#angular/core';
import { Router } from "#angular/router";
import { PropertyService } from './property.service';
#Component({
selector: 'app-property',
templateUrl: 'pages/property/property.component.html',
providers: [PropertyService]
})
export class PropertyComponent implements OnInit {
public propertyData: any;
constructor(private router: Router, private propertyService: PropertyService) {}
ngOnInit() {
this.propertyData = this.propertyService.propertyData;
}
details(item: any) {
this.propertyService.selectedProperty = item;
this.router.navigate(["/propertyinfo"]);
}
}
Now, when I perform a console.log(JSON.stringify(this.propertyService.selectedProperty)); within my details function, the output is as follows:
JS: {"ID":4,"description":"Lorem ipsum dolor sit amet...", "streetName":"Somestreet","houseNumber":459,"etc":"etc"}
This is my propertyinfo.component.ts:
import { Component, OnInit } from '#angular/core';
import { PropertyService } from '../property/property.service';
import { Router } from '#angular/router';
#Component({
selector: 'app-propertyinfo',
templateUrl: 'pages/propertyinfo/propertyinfo.component.html'
})
export class PropertyinfoComponent implements OnInit {
public selectedProperty: any;
constructor(private propertyService: PropertyService, private router: Router) {
this.selectedProperty = this.propertyService.selectedProperty;
}
ngOnInit() { }
}
Yet, when I perform a console.log(JSON.stringify(this.selectedProperty)); inside the constructor, the output is JS: undefined.
At the bottom of this post, I'll add the app.routing.ts and app.module.ts files so you can see all of my imports/directives etc. I'm really at a loss as to what I'm missing. I hope you can help me.
app.routing.ts:
import { NgModule } from "#angular/core";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { Routes } from "#angular/router";
import { PropertyComponent } from "./pages/property/property.component";
import { PropertyinfoComponent } from ".//pages/propertyinfo/propertyinfo.component";
const routes: Routes = [
{ path: "", component: PropertyComponent },
{ path: "propertyinfo", component: PropertyinfoComponent },
];
#NgModule({
imports: [NativeScriptRouterModule.forRoot(routes)],
exports: [NativeScriptRouterModule]
})
export class AppRoutingModule { }
app.module.ts:
import { NgModule, NO_ERRORS_SCHEMA } from "#angular/core";
import { NativeScriptHttpClientModule } from "nativescript-angular/http-client";
import { HttpClientModule, HttpClient } from '#angular/common/http';
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { AppRoutingModule } from "./app.routing";
import { AppComponent } from "./app.component";
import { PropertyService } from "./pages/property/property.service";
import { PropertyComponent } from "./pages/property/property.component";
import { PropertyinfoComponent } from "./pages/propertyinfo/propertyinfo.component";
#NgModule({
bootstrap: [
AppComponent
],
imports: [
NativeScriptModule,
AppRoutingModule,
NativeScriptRouterModule,
HttpClientModule,
NativeScriptHttpClientModule,
],
declarations: [
AppComponent,
PropertyComponent,
PropertyinfoComponent
],
providers: [
PropertyService
],
schemas: [
NO_ERRORS_SCHEMA
]
})
export class AppModule { }
Thank you for any help in advance. If I need to clear things up/provide any more info, please let me know.
console.log(JSON.stringify(this.selectedProperty)) returns undefined in PropertyinfoComponent because the PropertyService service being injected is not the same instance in PropertyinfoComponent than it is in PropertyComponent
you did not post the full .html for both component so I can only assume that you have something like the PropertyComponent is a parent component and has a reference/include a PropertyinfoComponent in the html and because of the way angular work, it injected a new instance of the service instead of using the one from the parent component.
check Thierry Templier answer for more information about angular service injection for this type of issue : How do I create a singleton service in Angular 2?
I am new in Angular 2 and trying to access data from API. As Output, I am getting API response on my browser as all JSON objects. But I don't know how to access the individual properties. below is my code:
test.component.ts
import { Component, OnInit } from '#angular/core';
import { HttpTestService } from './http-test.service';
#Component({
selector: 'http-test',
templateUrl: './http-test.component.html',
providers: [HttpTestService]
})
export class HttpTestComponent implements OnInit {
getData:string;
postData: string;
constructor(private _httpService: HttpTestService) { }
getTest(){
this._httpService.getData()
.subscribe(
data => this.getData = JSON.stringify(data)
);
}
ngOnInit() {
}
}
test.service.ts
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class HttpTestService {
constructor(private _http: Http) { }
getData(){
return this._http.get("http://jsonplaceholder.typicode.com/users")
.map(res => res.json())
}
}
test.component.html
In this file, when I use {{getdata}} I get whole JSON object, but when I try to access any of its property I get ERROR
<button (click)="getTest()">Get Result</button>
output:
<ul>
<li>{{ getData[0][time] }}</li>
</ul>
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { AppComponent } from './app.component';
import { HttpTestComponent } from './http-test/http-test.component';
#NgModule({
declarations: [
AppComponent,
HttpTestComponent,
],
imports: [
BrowserModule,
FormsModule,
HttpModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
**Output: **
this.getData = JSON.stringify(data) will make your object a string and you can't reach a strings fields like an object. Remove it.
Then you need to reach to time key as a "string"
Try:
<li>{{ getData[0]['time'] }}</li>
or
<li>{{ getData[0]?.time }}</li>
Example: http://plnkr.co/edit/CB3oGppm4fvoEExfDSRc?p=preview
Change Your code in plunker as shown below :
import { Component } from '#angular/core';
import { ConfigurationService } from './ConfigurationService';
#Component({
selector: 'my-app',
template: `
<table>
<tr *ngFor="let data of getData">
<td>{{data.address.street}}</td>
<td>{{data.address.geo.lat}}</td>
<td>{{data.name}}</td>
<td>{{data.email}}</td>
</tr>
</table>
`
})
export class AppComponent {
getData : any[] ;
constructor(private _ConfigurationService: ConfigurationService)
{
console.log("Reading _ConfigurationService ");
//console.log(_ConfigurationService.getConfiguration());
this._ConfigurationService.getConfiguration()
.subscribe(
(data)=> {
this.getData = data;
console.log(this.getData);
},
(error) => console.log("error : " + error)
);
}
}
I am facing difficulty in using a component defined in a file named navigation.component.ts directly on HTML Page.
The same component works fine if I use it under template of a component defined on app.component.ts.
Contents of app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { AppComponent } from './app.component';
import { NavigationComponent} from './shared/navigation.component';
#NgModule({
imports: [BrowserModule],
declarations: [AppComponent, NavigationComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Contents of navigation.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'navigation',
templateUrl: '/views/shared/navigation.html'
})
export class NavigationComponent {
userName: string = 'Anonymous';
}
Contents of app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'main-app',
template: '<navigation></navigation><h1>{{pageTitle}}</h1>'
})
export class AppComponent {
pageTitle: string = 'Portal 2.0';
}
Contents of index.html
<body>
<main-app></main-app>
</body>
The above works and renders menus on top but when I try to use <navigation> directly (given below) it doesn't render it, doesn't show any errors either.
<body>
<navigation></navigation>
</body>
Am I doing something wrong?
And the bigger question is how I go debugging issues like this?
Yes you can use web components. Add all the components that you want to load to entrycomponents.
Using createCustomElement you can create elements and use their selector anywhere.
import { BrowserModule } from '#angular/platform-browser';
import { NgModule, Injector } from '#angular/core';
import { createCustomElement } from '#angular/elements';
import { AppComponent } from './app.component';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [],
entryComponents: [AppComponent]
})
export class AppModule {
constructor(private injector: Injector) {
console.log('Elements is loaded: Activation');
this.registerComponent('metro-activation-loader', AppComponent);
}
public ngDoBootstrap(): void {
console.log('Elements is loaded: Activation ngDoBootstrap');
}
// tslint:disable-next-line:no-any
private registerComponent(name: string, component: any): void {
const injector = this.injector;
const customElement = createCustomElement(component, { injector });
customElements.define(name, customElement);
}
}