how get item by id from JSON API with Angular 2+? - json

i have my service with 2 methods getAll() and getById(), from which i receive the data:
job.service.ts
export class JobService {
constructor(private http: HttpClient) {}
url: string =
'https://api.json-generator.com/templates/......../data?access_token=............';
getAll(): Observable<Jobs[]> {
return this.http.get<Jobs[]>(this.url)
}
getById(id: string): Observable<Jobs> {
const path = `${this.url}`;
return this.http.get<Jobs>(path)
}
}
with getAll() method i form a list of items, from where with routerLink and *queryParams * i need to go to the separate page of item, that i clicked
job-list-card.component.html
<a routerLink="/details" [queryParams]="{ id: jobs.id }">
<h2 class="card-info__title">
{{ jobs.title }}
</h2>
</a>
and here is my the separate page of item ts-file:
job-detail.component.ts
export class JobDetailComponent implements OnInit {
jobs: Jobs | undefined;
constructor(
private route: ActivatedRoute,
private location: Location,
private jobService: JobService
) {}
ngOnInit(): void {
this.getJob();
}
getJob(): void {
const id = String(this.route.snapshot.paramMap.get('id'));
this.jobService.getById(id)
.subscribe(jobs => this.jobs = jobs);
}
goBack(): void {
this.location.back();
}
}
but everything i get in my page is only template without any api data.
so, what's wrong with my service or job-detail?
how can i get one item from list of items, that i receive from remote JSON API?

Related

How to use private properties in my html-file?

I am trying to show a list of Animals in my html page with their corresponding name and color.
My frontend gets the data from a spring backend that returns a list of Animals.
And I stumbled upon 2 questions that I have:
1)
I made the name and color properties private in the Animal class.
Code of the animal class:
interface AnimalJson {
name: string;
color: string;
}
export class Animal {
constructor(private name: string, private color: string) {}
static fromJSON(json: AnimalJson): Animal {
const a = new Animal(json.name, json.color);
return a;
}
}
code of my animal-component:
import { Component, OnInit } from '#angular/core';
import { Observable } from 'rxjs';
import { DataServiceService } from '../data-service.service';
import { Animal } from '../models/Animal';
#Component({
selector: 'app-animal',
templateUrl: './animal.component.html',
styleUrls: ['./animal.component.css'],
})
export class AnimalComponent implements OnInit {
public animals: Observable<Animal[]>;
constructor(private dataService: DataServiceService) {
this.animals = new Observable<Animal[]>();
}
ngOnInit(): void {
this.animals = this.dataService.getAnimals();
}
}
code of the service:
#Injectable({
providedIn: 'root',
})
export class DataServiceService {
constructor(private http: HttpClient) {}
getAnimals(): Observable<Animal[]> {
return this.http
.get<Animal[]>('http://localhost:8080/animals')
.pipe(map((animals: any[]): Animal[] => animals.map(Animal.fromJSON)));
}
}
code of the html-page:
<div *ngFor="let animal of animals | async">
<p>{{ animal.name }}</p>
</div>
Now when I try to get the animal.name, it gives an error that the name is private so I cant use it in my html page. How should I fix this? Should I just make it public? Or is there something I forget?
2)
Is this how you work with observables? Or am I using my observables in a wrong way?
Using the http get methode to get the observable and than call it in my animal-component and use async in my html-file to go over all the values in it?
If you use private then it should not be used in the html, am not sure why you are using a class for initializing the array. Just use a simple map statement.
If you are going to show it in the HTML then don't make the property private.
So the changes are.
interface Animal {
name: string;
color: string;
}
Service will be.
#Injectable({
providedIn: 'root',
})
export class DataServiceService {
constructor(private http: HttpClient) {}
getAnimals(): Observable<Animal[]> {
return this.http
.get<Animal[]>('http://localhost:8080/animals')
.pipe(map((animals: any[]): Animal[] => animals.map((item: Animal) => ({name: item.name, color: item.color}))));
}
}
Note: class can also be used as an interface, so when using animal you defined the properties as private, so you are unable to use in the HTML.

How to send data to back-end of Asp.net Project

I have created a simple form on the Asp.net boiler template project. I have a total of three fields
In Table 1
Product name
Quantity
In Table2
Tags with product List
I wanted to store third field data in another table in the database.
but I'm confused as I'm a beginner.
The product name and quantity is working fine. Can someone please guide me? Why data in the 2nd table is stored as null?
(1) This is chips code ( from priming)
(2) This is my class code (in which all three data members exist
(3) This is my Product list class code for storing chips
(4) This is database table of Product
(5) This is Database table of Product list class
This is new attached image
Error Image
import {Component,Injector,OnInit,EventEmitter,Output,} from '#angular/core';
import { finalize } from 'rxjs/operators';
import { BsModalRef } from 'ngx-bootstrap/modal';
import * as _ from 'lodash';
import { AppComponentBase } from '#shared/app-component-base';
import {
ProductServiceProxy,
ProductDto,
Product_listDto,
Product_listServiceProxy
} from '#shared/service-proxies/service-proxies';
#Component({
templateUrl: 'create-product.component.html'
})
export class CreateProductComponent extends AppComponentBase
implements OnInit {
saving = false;
product = new ProductDto();
#Output() onSave = new EventEmitter<any>();
constructor(
injector: Injector,
private _productService: ProductServiceProxy,
public bsModalRef: BsModalRef
) {
super(injector);
}
ngOnInit(): void {
}
save(): void {
this.saving = true;
console.log("input",this.product)
const product = new ProductDto();
product.init(this.product);
this._productService
.create(product)
.pipe(
finalize(() => {
this.saving = false;
})
)
.subscribe(() => {
this.notify.info(this.l('SavedSuccessfully'));
this.bsModalRef.hide();
this.onSave.emit();
});
}
}
Your p-chip returns a string array but your back end requiring a object of product_list.you need to pass the a `product_list' object array to the backend.
save(): void {
this.saving = true;
console.log("input",this.product)
let productList = [...this.product.productList];
this.product.productList = productList.map(item=>{
return {
Id: 0,
Name: item
}
});
const product = new ProductDto();
product.init(this.product);
}

Angular 6 - Sending an object between component using a Service

Actually I'm confronted to 2 issues with Angular.
My first consists on adding articles in a basket in different component. I send an object to a service and a second component retrieve it ...
My second issue is when i want to have a second product, i wish to display both of them and not overwritting it. I have been reading this : http://jasonwatmore.com/post/2018/06/25/angular-6-communicating-between-components-with-observable-subject in order to give me some skills ...
In my view i added a button :
<button class="btn btn-danger" (click)="onAddProduct()">Ajouter</button>
Here is my article component :
export class ProductComponent implements OnInit {
#Input() private product: Product;
private basketData: BasketdataService;
constructor(private basketData: BasketdataService) { }
ngOnInit() {
}
onAddProduct() {
console.log(this.product);
this.basketData.onAddBasket(this.product);
}
}
My service here retrieve the datas and share them with the basket component
export class BasketdataService {
private subject = new Subject<any>();
onAddBasket(product: Product) {
this.subject.next(product);
}
onGetBasket(): Observable<Product> {
return this.subject.asObservable();
}
removeArticleBasket() {
this.subject.next();
}
Here is my basketComponent
export class BasketmenuComponent implements OnInit, OnDestroy {
product : Product;
subscription : Subscription;
constructor(private basketdataService: BasketdataService) {
this.subscription = this.basketdataService.onGetBasket().subscribe(message => { this.product = product; });
}
ngOnInit() {
}
ngOnDestroy() {
// unsubscribe to ensure no memory leaks
this.subscription.unsubscribe();
}
}
I receive this error :
ERROR ReferenceError: product is not defined at SafeSubscriber._next
In basketComponent you've an error, try this:
export class BasketmenuComponent implements OnInit, OnDestroy {
product : Product;
subscription : Subscription;
constructor(private basketdataService: BasketdataService) {
this.subscription = this.basketdataService.onGetBasket().subscribe(product=> { this.product = product; });
}
ngOnInit() {
}
ngOnDestroy() {
// unsubscribe to ensure no memory leaks
this.subscription.unsubscribe();
}
}
It's not "message", but "product" in this.subscription

How would one access this from the Class inside a function in an object using TypeScript / Angular2

In my angular2 project I have a DataService class.
I want to have a DataService.await.get() and DataService.await.put() but I'm having trouble getting the correct 'this' inside those methods.
This is what I have now:
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { ReplaySubject } from 'rxjs/ReplaySubject';
#Injectable()
export class DataService {
public await = {
get(req): Observable<any> {
return this.getIt(req); // I need 'this' to be the DataService
},
put(req, data): boolean {
return this.putIt(req, data); // I need 'this' to be the DataService
}
constructor() {}
private getIt(req: string): Observable<any> {
return new ReplaySubject(1).AsObservable();
}
private putIt(req: string, data: any): boolean {
return true;
}
}
I have seen some examples using arrow functions for functions within functions, but not for functions within an object...
How do I get 'this' to be a reference to the class?
You could change your property to a function that returns an object and use a little trick like this:
public await() {
let that = this;
return {
get(req): Observable<any> {
return that.getIt(req);
},
put(req, data): boolean {
return that.putIt(req, data);
}
};
}
or you could initialize the await property in the constructor:
await: { get(req): Observable<any>, put(req, data): boolean };
constructor() {
let that = this;
this.await = {
get(req): Observable<any> {
return that.getIt(req);
},
put(req, data): boolean {
return that.putIt(req, data);
}
};
}
I managed to solve it using arrow after all, appearantly all this time I was trying with get= instead of get:
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { ReplaySubject } from 'rxjs/ReplaySubject';
#Injectable()
export class DataService {
public await = {
get: (req): Observable<any> => {
return this.getIt(req); // I need 'this' to be the DataService
},
put: (req, data): boolean => {
return this.putIt(req, data); // I need 'this' to be the DataService
}
constructor() {}
private getIt(req: string): Observable<any> {
return new ReplaySubject(1).AsObservable();
}
private putIt(req: string, data: any): boolean {
return true;
}
}

Getting data from Web API in Angular 2

Thanks to tutorial on Angular 2 page called "Tour of Heroes", I managed to create a simple Angular 2 application. Then using Enitity Framework I decided to create a database. And fill the list of heroes from it (not from the file). I created Web Api Controller and added simple get method.
Then in hero.service.ts I call this method in order to get list of heroes. When I lunch my app it shows the list of heroes but without any values (name and id are blank). When I debug my application in the browser I can see this.heroes object in heroes.component.ts contains right data. So what is going on? Why aren't name and id showing?
hero.service.ts:
import {Injectable} from 'angular2/core';
import {HEROES} from './mock-heroes';
import {Hero} from './hero';
import {Http, Response} from 'angular2/http';
import 'rxjs/Rx';
import {Observable} from 'rxjs/Observable';
#Injectable()
export class HeroService {
public values: any;
constructor(public _http: Http) { }
private _heroesUrl = 'http://localhost:61553/api/values'; // URL to web api
getHeroes() {
return this._http.get(this._heroesUrl)
.map(res => <Hero[]>res.json())
.catch(this.handleError);
}
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
heroes.component.ts:
import {Component, OnInit} from 'angular2/core';
import {Router} from 'angular2/router';
import {Hero} from './hero';
import {HeroDetailComponent} from './hero-detail.component';
import {HeroService} from './hero.service';
#Component({
selector: 'my-heroes',
templateUrl: 'templates/heroes.component.html',
styleUrls: ['styles/heroes-component.css'],
directives: [HeroDetailComponent]
})
export class HeroesComponent implements OnInit {
constructor(private _heroservice: HeroService, private _router: Router) { }
errorMessage: string;
public heroes: Hero[];
selectedHero: Hero;
ngOnInit() {
this.getHeroes();
}
onSelect(hero: Hero)
{
this.selectedHero = hero;
}
getHeroes() {
this._heroservice.getHeroes()
.subscribe(
value => this.heroes = value,
error => this.errorMessage = <any>error);
}
gotoDetail() {
this._router.navigate(['HeroDetail', { id: this.selectedHero.Id }]);
}
}
heroes.component.html:
<h2>My Heroes</h2>
<ul class="heroes">
<li *ngFor="#hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)">
<span class="badge">{{hero.Id}}</span> {{hero.Name}}
</li>
</ul>
<div *ngIf="selectedHero">
<h2>
{{selectedHero.Name | uppercase}} is my hero
</h2>
<button (click)="gotoDetail()">View Details</button>
</div>
hero.ts:
export class Hero {
Id: number;
Name: string;
}
Web API Controller:
using Microsoft.AspNet.Mvc;
using System.Collections.Generic;
using TestApplicationDataAccess;
using TestApplicationDataAccess.Entities;
namespace WebApplication2.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly TestAppDbContext _dbContext;
public ValuesController(TestAppDbContext dbContext)
{
_dbContext = dbContext;
}
// GET: api/values
[HttpGet]
public IEnumerable<Hero> Get()
{
return _dbContext.Heroes;
}
}
}
Hero Entity:
namespace TestApplicationDataAccess.Entities
{
public class Hero
{
public int Id { get; set; }
public string Name { get; set; }
}
}
JSON retrieved from WEB API Controller:
[{"Id":1,"Name":"Superman"}]
getHeroes() {
this._heroservice.getHeroes()
.subscribe(res=>{
this.heroes=res;
console.log(this.heroes); // make sure you get data here.
},
(err)=>console.log(err),
()=>console.log("Done")
);
}
Try this :public heroes: Hero[] = [];
In my case the issue was related to the visual studio 2015 bug. There was nothing wrong with the code itself. Sometimes changes made in vs were not refreshed in the browser. Updating vs to the latest version helped.