HTML table not automatically updating after executing HTTP post - html

I created a dummy website for a 'game library' just to teach myself the http POST, GET, PUT and DELETE methods, I have a separate file for my api with 3 'games' in. The post does work when I enter a new game name and click enter nothing happens but when I refresh the page my html table then displays the first three games plus the one I just posted. I would like to have it post and then display it on the table right away rather than having to refresh the page as its abit sloppy in my opinion.
I have tried putting the input box above the table, but I don't really know what else to try.
<h3>Here is your list of current games in your library</h3>
<table>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
<tr *ngFor="let game of games">
<td>{{game.id}}</td>
<td>{{game.name}}</td>
</tr>
</table>
public games: any = [];
private url = 'http://localhost:3000/api/games';
constructor(private httpClient: HttpClient){
httpClient.get(this.url).subscribe(response => {
this.games = response;
});
}
createGame(name: HTMLInputElement) {
let post = {name : name.value};
name.value = '';
let headers = new HttpHeaders();
headers= headers.set('Content-Type', 'application/json');
this.httpClient.post(this.url, {id: this.games.length + 1,name: post.name }, {headers})
.subscribe(response => {
console.log(response)
})
}
I would like the table to auto update when I post a new game to it.

You have to implements OnInit on your component, see the doc here [https://angular.io/api/core/OnInit]
Your get request should be in the ngOnInit() like this :
ngOnInit(){
httpClient.get(this.url).subscribe(response => {
this.games = response;
});
}
After creating your new data, call ngOnInit() function and
your table will be updated.

You are not retrieving back the changed data. Once the POST call is successful, make a GET call to get the updated data.
createGame(name: HTMLInputElement) {
let post = {name : name.value};
name.value = '';
let headers = new HttpHeaders();
headers= headers.set('Content-Type', 'application/json');
this.httpClient.post(this.url, {id: this.games.length + 1,name: post.name },{headers}).subscribe(response => {
console.log(response)
// Subscribe back the changes
this.httpClient.get(this.url).subscribe(response => {
this.games = response;
});
})
}
Another way is to write another function which uses the GET call to update the data. You can use that one for initially loading the data as well as updating after new game creation.

#sammyleighg try like this,
you can update your games list once you have successfully posting your data, just make another http call to your Server.
create a method to simplified logic.
Component.ts
public games: any = [];
private url = 'http://localhost:3000/api/games';
constructor(private httpClient: HttpClient){
this.getGamesInfo();
}
getGamesInfo() {
this.httpClient.get(this.url).subscribe(response => {
this.games = response;
});
}
createGame(name: HTMLInputElement) {
let post = {name : name.value};
name.value = '';
let headers = new HttpHeaders();
headers= headers.set('Content-Type', 'application/json');
this.httpClient.post(this.url, {id: this.games.length + 1,name: post.name }, {headers})
.subscribe((response: any) => {
if(response.status == 200) {
this.getGamesInfo();
}
})
}
I will recommend to use ngOnInit() for making Api calls rather than in constructor()

You have to add newly created game to games array inside createGame method:
this.games.push({id: this.games.length + 1,name: post.name });
For PUT method you need to find edited item in array and then change its data:
let editedGame = this.games.find(game => game.id === UserInputId);
editedGame.name = UserInputName;

Related

Angular HttpClient - how to convert from Http: JSON.parse(JSON.stringify(data))._body)?

Using the Http module, this construction is used:
Http service:
let tokenUrl1 = this.apiUrl + 'login';
let headers1 = new Headers({'Content-Type': 'application/json'});
return this.http.post(tokenUrl1, JSON.stringify(model), {headers: headers1});
Call of the service:
this.loginService.sendCredential(this.model).subscribe(
data => {
// Next statement ... how to convert this for use in an HttpClint environment??
localStorage.setItem("token", JSON.parse(JSON.stringify(data))._body);
The nice HttpClient module parses the http content body with JSON returning an object. Nice!
How can the marked statement, "JSON.parse(JSON.stringify(data))._body)" be rewritten to fit nicely in the HttpClient environment?
You can manipulate the return type to string - that is sufficient for e.g. tokens:
let tokenUrl2 = this.apiUrl + 'users';
let getHeaders = new HttpHeaders({'Authorization':'Bearer '+token});
return this.httpClient.get(tokenUrl2, { observe: 'body', responseType: 'text', headers: getHeaders})
You can add observe in your header.
let tokenUrl1 = this.apiUrl + 'login';
let headers1 = new Headers({'Content-Type': 'application/json'});
return this.http.post(tokenUrl1, JSON.stringify(model), {
headers: headers1,
observe: 'response'
});
And
this.loginService.sendCredential(this.model).subscribe(
data => {
console.log(data.body);
You can use response as JSON object directly to get value like this.
this.loginService.sendCredential(this.model).subscribe(
data => {
let res = data.json();
let tokenValue = res['token']; // based on your json response...
localStorage.setItem("token", tokenValue);
}
And If you are using api-call with type then...(From Angular Doc)
showConfig() {
this.configService.getConfig()
.subscribe((data: Response) => {
// like data.xyz properties of 'Reponse' class
// here you can get values from Your 'Reponse' class directly instead of parsing as above.
});
}
Hope this helps.
Ask me if any query.

ERROR TypeError: Cannot read property 'Name' of undefined after get Json

I have a problem with my application in angular2. I need to connect to api to retrieve records to my Persons [] class. I want to use the second method to get people with individual id. I do the same way as in the tutorial on the Angular site but unfortunately I still have a fault
ERROR TypeError: Cannot read property 'Name' of undefined
This is my service
getPersons(): Promise<Person[]> {
var currentUser = JSON.parse(localStorage.getItem('currentUser'));
var token = currentUser.token;
let headers = new Headers({ 'Authorization': 'Bearer ' + token })
let options = new RequestOptions({ headers: headers });
return this.http.get(this.QuestionsUrl, options)
.toPromise()
.then(response => response.json() as Person[]);
}
getPerson(id: number): Promise<Person> {
return this.getPersons().then(persons => persons.find(person => person.Id === id));
}
My component:
export class PersonsComponent implements OnInit {
activePerson: any = {};
model: any = {};
constructor(private personService: PersonService, private route: ActivatedRoute, private location: Location) {
}
ngOnInit(): void {
this.route.paramMap.switchMap((params: ParamMap) => this.personService.getPerson(+params.get('Id')))
.subscribe(selected => this.activePerson = selected);
}
}
And html:
<body>
{{activePerson.Name}}
Try using
{{activePerson?.Name}}
With a question mark.
The issue is that the template attempts to display the value before the data is retrieved. At that point, activePerson is undefined. Hence the error message.
The "?" is called a safe navigation operator. It prevents navigating to the "dot" property (name in this example) unless the object to the left of the question mark has a value.
use
{{activePerson |json}}
to know if you are receiving any data

How to create ionic 2 infinite scroll with data from database

I'd query about 500 users from database who are active. I am using laravel and ionic framework.
Here is my query using laravel.
public function getUsers(Request $request) {
$users = DB::table('users')->where('status', $request->status)->get();
return Response::json($users);
}
Here might be my .ts code in ionic 2
import { Component } from '#angular/core';
import { Http, Headers, RequestOptions } from "#angular/http";
#Component({
selector: 'page-users',
templateUrl: 'users.html'
})
export class UsersPage {
users: any = [];
constructor(
private http: Http
) {
var headers = new Headers();
headers.append("Accept", 'application/json');
headers.append('Content-Type', 'application/json' );
let options = new RequestOptions({ headers: headers });
let data = { 'status': 'active'}
this.http.post('http://path/to/laravel/api/getUsers', data, options)
.subscribe(res => {
var jsonData = JSON.parse(res['_body']);
this.users = jsonData;
})
}
doInfinite(infiniteScroll) {
// How can I do infinite scroll here???
setTimeout(() => {
infiniteScroll.complete();
}, 1000);
}
}
I am able to get the 500 active users and display it on my view.
However, It is a kind of laggy because there are too many data query at once.
I want to create infinite scroll to optimize the query. But, I don't know how to implement that in ionic 2.
I want atleast 10 users to be query everytime I scroll. Answers are appreciated.
I'll just pull off one of my codes and replace some variable names. Hopefully it will make sense and be helpfull:
Assuming you have this on your html:
<ion-infinite-scroll (ionInfinite)="fetchMore($event)">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
You will need something like this on your .ts:
fetchMore(event) {
this.myService.getMoreItems(10/*number of items to fetch*/,this.collection.length/*you might need to send the "skip" value*/).then(
(moreItems: any[]) => {
if (moreItems.length > 0) {
this.collection = this.collection.concat(moreItems);
}
event.complete();
},
(err) => {
event.complete();
}
);
}
The myService.getMoreItems part will be your service/provider that has the function, return type is a Promise<any>, that will make the Http Request. I think you got the idea.

JSON from API call does not show in HTML part

Hello fellow Programmer,
we have an component which loads after clicking on a link, this components content depends on the the link its got clicked. For Example we click on the Link and load a JSON from an API which contain the Data, this Data is shown on our HTML template.
So far we have an succesfull API call which gets us the JSON and we bind it on an var which is conected to the HTML by {{var}}, but it wont display the JSON at all.
We are pretty sure it is a problem with the asynchron call from the API to get the Data, but we have no idea how to fix this.
component.service.ts with the getVoucher() method
getVoucher() {
let voucherUrl = 'xxx'; // URL to web api
let headers = new Headers();
headers.append('Content-Type', 'application/json;charset=UTF-8');
headers.append('Authorization', 'Basic '+btoa("xxx"));
let options = new RequestOptions({ headers: headers });
return this.http.get(voucherUrl,options).map(response => response.json());
}
component.ts
private gutschein;
private strGutschein;
ngOnInit(): void {
this.voucherService.getVoucher().subscribe(data => {
this.gutschein = data;
console.log(this.gutschein);
});
setTimeout(() => console.log(this.gutschein), 2000);
//console.log(this.gutschein);
this.strGutschein = JSON.stringify(this.gutschein);
}
and the HTML Part component.html
{{strGutschein}}
your component code should be like this
private gutschein;
private strGutschein;
ngOnInit(): void {
this.voucherService.getVoucher().subscribe(data => {
this.gutschein = data;
console.log(this.gutschein);
this.strGutschein = JSON.stringify(this.gutschein);
console.log(this.strGutschein);
});
setTimeout(() => console.log(this.gutschein), 2000);
}
and in html part use
{{ strGutschein | json }}

Angular 2 and .NET Core Web Api: http post does not call the API

I'm trying to perform a post request to my WebAPI controller, but there is no way to make my action to be called.
This is the action:
[HttpPost("about")]
public async Task<IActionResult> PostAbout([FromBody] PostAboutBindingModel model)
{
if (model == null || !ModelState.IsValid)
return BadRequest(ModelState);
var about = new About
{
Text = model.Text,
Date = model.Date,
Images = _jsonSerializer.Serialize(model.Images)
};
_context.Abouts.Add(about);
await _context.SaveChangesAsync();
return Created($"/api/about/{about.Version}", about);
}
The PostAboutBindingModel has only three properties: Text, Date and Images.
This is the angular2 code snippet where I perform the API call:
let model: IAbout = <IAbout>{
date: new Date(),
images: [],
text: "test"
}
let opts = jwtAuthorization();
opts.headers.append("Content-Type", "application/json");
return this.http.post("/api/about", model, opts)
.map((response: Response) => console.log("TEST", response.json()))
.catch(this.handleError);
The jwtAuthorization simply add the Authorization header:
export function jwtAuthorization(): RequestOptions {
"use strict"
if (localStorage.getItem("auth")) {
// create authorization header with jwt token
let auth: IAuth = getAuth(JSON.parse(atob(localStorage.getItem("auth"))));
if (auth && auth.access_token) {
let headers: Headers = new Headers({ "Authorization": auth.token_type + " " + auth.access_token });
return new RequestOptions({ headers: headers });
}
}
}
I've tried to specify, as body, the following things:
model
{ model }
{ model: model }
JSON.stringify(model)
JSON.stringify({ model: model })
I've tried to specify my model as a generic object (without type) too.
I've tried to perform the call with and without the Content-Type header.
None of the previous seems to work. The API action is not called and no errors are returned.
I would like to perform the request specify only model as-is if it's possible but I would be happy in any case, if it works :)
What am I missing?
EDIT
I read now that http requests in angular 2 are "lazy" so they need a subscriber (subscribe) to work.
Thanks for help