Pushing json file into a localStorage array - json

I have a task to make CRUD app in angular 8 but I have to push somehow my JSON file into local storage and then be able to add new objects. I made an array of contacts and put some data in there and if someone can help me to put this JSON data in that array of objects, so I can read all my contacts from localStorage.
I have tried to subscribe to contacts and it kinda works but won't add data to a localStorage.
Contacts Service
import { Contact } from '../models/contact';
import { IContact } from '../models/contact';
import { Observable } from 'rxjs/Observable';
import { HttpClient } from '#angular/common/http';
import { Injectable, OnInit } from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class ContactService {
contacts: Array < Contact > = [{
first_name: "Darko",
last_name: "Lesevic",
emails: ["darko1#test.com", "darko2#test.com"],
phones: [123456789, 123456789, 123456789],
photo: ''
}];
constructor(private http: HttpClient) {
//this won't work
// this.getJSON().subscribe(data => {
// this.contacts = data;
// console.log(data);
// });
}
getJSON(): Observable < Contact[] > {
return this.http.get < Contact[] > ("/assets/data/contacts.json");
}
contacts_serialized: any;
contacts_deserialized: any;
localStorageObj() {
this.contacts_serialized = JSON.stringify(this.contacts); //converts data to string
localStorage.setItem('id', this.contacts_serialized);
this.contacts_deserialized = JSON.parse(localStorage.getItem('id')); //converts string to data
console.log(this.contacts_deserialized);
}
}
Calling contact Service here
import { ContactService } from '../services/contact.service';
import { Component, OnInit } from '#angular/core';
import { Observable } from 'rxjs';
import { Contact } from '../models/contact';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
constructor(private contactService: ContactService) { }
ngOnInit() {
this.contactService.localStorageObj();
}
}
MY JSON FILE
[{
"first_name": "Afonso",
"last_name": "Pinto",
"emails": ["mail01#gmail.com", "mail02#gmail.com"],
"phones": ["123-234-566", "123-234-567", "123-234-568"],
"photo": "http://lorempixel.com/400/300/people/"
},
{
"first_name": "Alexandre",
"last_name": "Paiva",
"emails": ["mail01#gmail.com"],
"phones": ["123-234-560", "123-234-561"],
"photo": null
},
{
"first_name": "Oea",
"last_name": "Romana",
"emails": ["mail01#gmail.com", "mail02#gmail.com"],
"phones": ["123-234-566", "123-234-567", "123-234-568"],
"photo": "http://lorempixel.com/400/300/people/"
},
{
"first_name": "Nuria",
"last_name": "Pelayo",
"emails": ["mail01#gmail.com", "mail02#gmail.com"],
"phones": ["123-234-568"],
"photo": "http://lorempixel.com/400/300/people/"
},
{
"first_name": "Lisandro",
"last_name": "Matos",
"emails": ["mail01#gmail.com", "mail02#gmail.com"],
"phones": ["123-234-566", "123-234-567"],
"photo": null
}
]

First of all, you need to subscribe and then use setItem
this.contactService.getJSON().subscribe((data) => {
localStorage.setItem('myData', JSON.stringify(data);
});

Related

Why would an angular service api not render to data bindings in the html?

I am still new to angular... But, this html renders as a blank page, nothing is shown in the browser. Console.log will log out the data to the console so I know it is visible. This also causes blank rows in a p-table or any other table that you might be using.
What am I doing wrong?
component.html
<div *ngFor="let item of myData">{{ item.id }}</div> <!-- should be: 1 2 3 -->
<div>{{ item[0].id }}</div> <!-- should be: 1 -->
component.ts
#Component({
selector: 'app-testing-table',
templateUrl: './testing-table.component.html',
styleUrls: ['./testing-table.component.css'],
})
export class TestingTableComponent implements OnInit {
myData: Posts[] = [];
constructor(
private postService: PostService,
) {}
ngOnInit(): void {
this.postService.get().subscribe((resp) => {
console.log('got all posts', resp);
this.myData = resp;
});
}
}
service.ts
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/internal/Observable';
import { Posts } from '../models/posts';
#Injectable({
providedIn: 'root',
})
export class PostService {
public URL = 'https://something.com/typicode/demo/posts';
constructor(protected http: HttpClient) {}
public get(): Observable<Array<Posts>> {
return this.http.get<Array<Posts>>(`${this.URL}`);
}
}
model.ts
export class Posts {
id: number;
title: string;
}
Response Data from the API get() service.ts
[
{
"ID": 1,
"Title": "Post 1"
},
{
"ID": 2,
"Title": "Post 2"
},
{
"ID": 3,
"Title": "Post 3"
}
]
This took me a few good days of work with some help from a friend to find out angular is very strict with how it maps the JSON to the Model. The response data has to match 1:1 with the case or it wont work. The error is here:
Make the models match the response:
model.ts
export class Posts {
ID: number;
Title: string;
}
OR
Have the api service change what it returns as JSON, and have it return this instead:
Response Data from the API get() service.ts
[
{
"id": 1,
"title": "Post 1"
},
{
"id": 2,
"title": "Post 2"
},
{
"id": 3,
"title": "Post 3"
}
]

Unable to Parse JSON data in angular requested through API

I am trying to get the data of movie from imdb site with the help of an API but unable to process the data further.
Here is the link i pass ("https://sg.media-imdb.com/suggests/j/johnwick.json") in the get method and opening the browser it looks like this:
imdb$johnwick({
"v": 1,
"q": "johnwick",
"d": [
{
"l": "John Wick: Chapter 3 - Parabellum",
"id": "tt6146586",
"s": "Keanu Reeves, Ian McShane",
"y": 2019,
"q": "feature",
"vt": 5,
"i": [
"https://m.media-amazon.com/images/M/MV5BNDU3YzJlY2EtODA3NS00ZWM3LWJhYjUtZWE3MmE2YmEzNWYwXkEyXkFqcGdeQXVyNDMzMzI5MjM#._V1_.jpg",
4050,
6000
],
"v": [
{
"l": "Official Trailer",
"id": "vi3978017305",
"s": "2:18",
"i": [
"https://m.media-amazon.com/images/M/MV5BNTg2YzEyNjktMmRmZi00NjU4LWIxNzYtMGE0Y2U2MDI5Y2Q1XkEyXkFqcGdeQW1yb3NzZXI#._V1_.jpg",
1920,
1080
]
}
]
},
{
"l": "John Wick",
"id": "tt2911666",
"s": "Keanu Reeves, Michael Nyqvist",
"y": 2014,
"q": "feature",
"vt": 23,
"i": [
"https://m.media-amazon.com/images/M/MV5BMTU2NjA1ODgzMF5BMl5BanBnXkFtZTgwMTM2MTI4MjE#._V1_.jpg",
1365,
2048
],
"v": [
{
"l": "Trailer #2",
"id": "vi2273816345",
"s": "1:00",
"i": [
"https://m.media-amazon.com/images/M/MV5BMjU0OTQwMjUyN15BMl5BanBnXkFtZTgwODQ5OTE4MjE#._V1_.jpg",
640,
480
]
},
{
"l": "Clip",
"id": "vi3905924889",
"s": "0:29",
"i": [
"https://m.media-amazon.com/images/M/MV5BNDYwMTUwNTMyNF5BMl5BanBnXkFtZTgwNDcyMjExMzE#._V1_.jpg",
1280,
720
]
},
{
"l": "John Wick",
"id": "vi2809377049",
"s": "4:18",
"i": [
"https://m.media-amazon.com/images/M/MV5BNGQ1YjYwOTUtODRkOS00NjU3LWJjZTMtOWM1MWE2YmFiN2ZjXkEyXkFqcGdeQXVyNzU1NzE3NTg#._V1_.jpg",
480,
360
]
}
]
},
{
"l": "John Wick: Chapter 2",
"id": "tt4425200",
"s": "Keanu Reeves, Riccardo Scamarcio",
"y": 2017,
"q": "feature",
"i": [
"https://m.media-amazon.com/images/M/MV5BMjE2NDkxNTY2M15BMl5BanBnXkFtZTgwMDc2NzE0MTI#._V1_.jpg",
1328,
2048
]
},
{
"l": "John Williams",
"id": "nm0002354",
"s": "Music Department, Star Wars: Episode I - The Phantom Menace (1999)",
"i": [
"https://m.media-amazon.com/images/M/MV5BMjY5MTgzMTQ1NF5BMl5BanBnXkFtZTYwNDg3OTcz._V1_.jpg",
280,
400
]
},
{
"l": "John Witherspoon",
"id": "nm0936762",
"s": "Actor, Friday (1995)",
"i": [
"https://m.media-amazon.com/images/M/MV5BMTM2NTg4MDcxNV5BMl5BanBnXkFtZTYwMDAxMzY0._V1_.jpg",
317,
400
]
},
{
"l": "John Williams",
"id": "nm0002369",
"s": "Actor, Sabrina (1954)",
"i": [
"https://m.media-amazon.com/images/M/MV5BMTUyNDg1MTU5MV5BMl5BanBnXkFtZTcwMTgwNTUxOA##._V1_.jpg",
1107,
1426
]
},
{
"l": "John Wilder",
"id": "nm0928588",
"s": "Writer, Centennial (1978-1979)",
"i": [
"https://m.media-amazon.com/images/M/MV5BMjAxNjE0NzE1MV5BMl5BanBnXkFtZTcwNzUzNjI0NA##._V1_.jpg",
473,
650
]
},
{
"l": "John Wick Chapter 2: Wick-vizzed",
"id": "tt7161870",
"s": "Pedro Hollywood, J.J. Perry",
"y": 2017,
"q": "video",
"i": [
"https://m.media-amazon.com/images/M/MV5BNDNkZDI0MjktMmZiYS00ZjI4LWI3ZDctMTBhMTMyYjczMDhlXkEyXkFqcGdeQXVyODA1NjQ0OTY#._V1_.jpg",
2000,
3000
]
}
]
})
Here is my angular code (The service file):
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class MovieProviderService {
storeMovie: any[];
constructor(private http: HttpClient) { }
getmovies(): Observable<any>
{
return this.http.get('https://sg.media-imdb.com/suggests/j/johnwick.json');
}
}
The below code is the file getting served:
import { Component, OnInit } from '#angular/core';
import { MovieProviderService } from '../movie-provider.service';
#Component({
selector: 'app-movie-container',
templateUrl: './movie-container.component.html',
styleUrls: ['./movie-container.component.scss']
})
export class MovieContainerComponent implements OnInit {
constructor(private movieService: MovieProviderService) { }
ngOnInit() {
let obs = this.movieService.getmovies();
obs.subscribe(
(response)=>{
const data = response.json();
console.log(data);},
(error)=>{console.log(error)}
)
}
}
It is giving the parsing error on console of chrome like unable to parse JSON at position 0...
I can see that the JSON data is contained inside imdb$johnwick( JSON ). How to get rid of that or may be tell some other good way or some topics which i need to learn. THANKYOU
IMDB return data in JSONP format so here you need to import HttpClientModule and HttpClientJsonpModule into your module.
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
// Import relevant http modules
import { HttpClientModule, HttpClientJsonpModule } from '#angular/common/http';
import { AppComponent } from './app.component';
import { ExampleService } from './example.service';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
// Import relevant http modules
HttpClientModule,
HttpClientJsonpModule
],
providers: [ExampleService],
bootstrap: [AppComponent]
})
export class AppModule { }
model-provider.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class MovieProviderService {
storeMovie: any[];
constructor(private http: HttpClient) { }
getmovies(): Observable<any>
{
return this.http.jsonp('https://sg.media-imdb.com/suggests/j/johnwick.json', 'callback');
}
}
Hope this will help!
In the service.js pass the option to handle the response as "text". We want to handle the reformatting of the text response in the service so we do not need to account for this in every component.
Using /(?:^.*?(\{)|\)$)/gm replaces everything before the first { and the ending ). The gm is "global" and "multi-line" for matching and will only replace the text if these rules are matched. We will then replace with first capture group of the RegExp (if there is no capture group one $1 becomes a blank string).
I took this approach to ensure if the source passes valid JSON in the future we wont be breaking/replacing valid JSON.
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class MovieProviderService {
storeMovie: any[];
constructor(private http: HttpClient) { }
getmovies(): Observable<string>
{
return this.http.get('https://sg.media-imdb.com/suggests/j/johnwick.json', { responseType: 'text' })
.map((res) => {
return JSON.parse(res.replace(/(?:^.*?(\{)|\)$)/gm, "$1"));
});
}
}
import { Component, OnInit } from '#angular/core';
import { MovieProviderService } from '../movie-provider.service';
#Component({
selector: 'app-movie-container',
templateUrl: './movie-container.component.html',
styleUrls: ['./movie-container.component.scss']
})
export class MovieContainerComponent implements OnInit {
constructor(private movieService: MovieProviderService) { }
ngOnInit() {
let obs = this.movieService.getmovies();
obs.subscribe(
(response)=>{
const data = response; // no longer need to call .json()
console.log(data);},
(error)=>{console.log(error)}
)
}
}

Call JSON with subscribe or promise

If I use the promise function, I get the Error:
**Property 'TEST' does not exist on type 'Object'**
my ServiceClass
with the method:
getTEST() {
return this.http.get(this.configUrl)
.toPromise()
.then(res => <Tariftabelle[]> res.TEST)
.then(data => { return data; });
}
And my json-Date:
{
"TEST": [
{"leistung": "hello", "sb": "World"},
{"leistung": "hellooo", "sb": "Test-Wordl"}
],
"TEST2": [
{"leistung": "hola", "basic": "1", "premium": "2", "exzellent": "3"},
{"leistung": "hola two", "basic": "2", "premium": "4", "exzellent": "6"},
{"leistung": "hola three", "basic": "4", "premium": "7", "exzellent": "9"}
]
}
or how can iIuse subscribe without promise?
Service
#Injectable({
providedIn: 'root'
})
export class MyService {
getTEST(): Observable<any> {
return this.http.get(this.configUrl);
}
}
Component
#Component({
selector: 'app-my-component',
templateUrl: './my-component.html',
styleUrls: ['./my-component.scss']
})
export class MyComponent implements OnInit {
data: any;
constructor(private myServ: MyService) {}
ngOnInit() {
this.myServ.getTEST().subscribe(res => {
this.data = res;
});
}
}
Template
<pre>{{ data | json }}</pre>
As you can see in the init of your component you subscribe for the service getTEST request. In the subscribe, when you receive json data, you assign them to your local data variable. Now you can access it into your template.

How to pass data received from service to angular datatable

I have just started working on Angular 4 and I am trying to render some data which I receive from angular service in json format, into angular-datatable, but whichever option i try its not working for me.
The table is coming, the columns are coming, however the data inside the columns are not displaying.
Any help would be great,
Thanks in advance..!!!!
Please find my code below:
component.html
<table datatable [dtOptions]="dtOptions" class="row-border hover"></table>
component.ts
import { Component, OnInit } from '#angular/core';
import { FleetDataService } from '../../services/fleet-data.service';
import { Subject } from 'rxjs/Subject';
#Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit {
private fleetData: any;
dtOptions: DataTables.Settings = {};
dtTrigger: Subject<any> = new Subject();
constructor(private getFleetData:FleetDataService) { }
ngOnInit() {
this.getFleetData.getFleetData().subscribe(
fleetData => {
this.fleetData = fleetData;
console.log(this.fleetData);
this.dtTrigger.next();
},
err => {
console.log(err);
}
);
this.dtOptions = {
pagingType: 'full_numbers',
columns: [{
title: 'First Name',
data: this.fleetData
}, {
title: 'Last Name',
data: this.fleetData
}, {
title: 'Score',
data: this.fleetData
}]
};
}
}
component.service
import { Injectable } from '#angular/core';
import { HttpModule, Http, Response, Headers, RequestOptions } from
'#angular/http';
import { Observable } from 'rxjs/Rx';
#Injectable()
export class FleetDataService {
constructor(private http: Http) { }
getFleetData() {
return this.http.get("../../assets/data/test.json")
.map((res:Response) => res.json())
.catch((error:any) => Observable.throw(error.json().error || 'Server
Error'));
}
}
test.json
[{
"FirstName": "Jill",
"LastName": "Smith",
"Score": "disqualified"
}, {
"FirstName": "Eve",
"LastName": "Jackson",
"Score": "94"
}, {
"FirstName": "John",
"LastName": "Doe",
"Score": "80"
}, {
"FirstName": "Adam",
"LastName": "Johnson",
"Score": "67"
}]
You set your dtOptions outside the subscribe.
If you do this the fleetData stays empty so dtOptions is never set correctly, because an Observable is asynchronous. I propose this code:
export class DashboardComponent implements OnInit {
dtOptions: DataTables.Settings = {};
dtTrigger: Subject<any> = new Subject();
constructor(private getFleetData:FleetDataService) { }
ngOnInit() {
this.getFleetData.getFleetData().subscribe(
fleetData => {
console.log(fleetData);
this.buildDtOptions(fleetData)
this.dtTrigger.next();
},
err => {
console.log(err);
});
}
private buildDtOptions(fleetData: any): void {
this.dtOptions = {
pagingType: 'full_numbers',
columns: [
{title: 'First Name', data: fleetData},
{title: 'Last Name', data: fleetData},
{title: 'Score', data: fleetData}
]
};
}
}
For this error: ERROR TypeError: Cannot read property 'aDataSort' of undefined. You can do a spinner (ngIf / else) in the view and when data are loaded you display the datatable

Make your pipe null-safe by returning null when null is passed as value

While using a pipe I was getting "NgFor only supports binding to Iterables such as Arrays." I received help from Guenter as can be seen from the comments, and then I ran into the issue with the keys pipe with the error "TypeError: Cannot convert undefined or null to object". Guenter then suggested to make the pipe null-safe by returning null when null is passed as value.
Here is my code on Plunker.
I am trying to print out the names of batch jobs in JSON format located here.
Here is the app.ts on Plunker:
import {Component, NgModule} from '#angular/core'
import {BrowserModule} from '#angular/platform-browser'
import { FormsModule } from '#angular/forms';
import { HttpModule, JsonpModule } from '#angular/http';
import { JobListComponent } from './job-list.component';
import { KeysPipe } from './keys.pipe';
import { JobService } from './job.service';
import { Job } from './job';
import { routing } from './app.routes';
#Component({
selector: 'my-app',
template: `
<div>
<header>
<div>
<!-- Title -->
<span>Jobs::</span>
<div>
{{jobs | json}}
<ul>
<li *ngFor="let job of jobs | keys">
<a>{{job.name}}</a>
</li>
</ul>
</div>
</div>
</header>
</div>
`,
})
export class App {
private json;
jobs: Observable<Job[]>;
constructor(private jobService: JobService) {}
ngOnInit() {
this.jobService.listJobs()
.subscribe(
jobs => {
this.jobs = jobs,
console.log(this.jobs)
console.log("AFTER")
});
}
}
#NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule
],
declarations: [ App,KeysPipe ],
providers: [JobService],
bootstrap: [ App ]
})
export class AppModule {}
I am using a pipe and I am trying to print the job name. It is modified as per Guenter's suggestion:
import {Component, Pipe, PipeTransform} from '#angular/core';
#Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
transform(value: any, args?: any[]): any[] {
if(value == null) {
return;
}
let keys = Object.keys(value),
data = [];
keys.forEach(key => {
data.push(value[key]);
});
return data;
}
}
Here is the service:
import { Injectable } from '#angular/core';
//import { Jsonp, URLSearchParams } from '#angular/http';
import {Http, Response} from '#angular/http';
import { Job } from './job'
import 'rxjs/add/operator/map';
import {Observable} from "rxjs";
// Decorator to tell Angular that this class can be injected as a service to another class
#Injectable()
export class JobService {
// Class constructor with Jsonp injected
constructor(private http:Http) { }
// Base URI for Spring Batch Admin
private jobsUrl = 'https://api.myjson.com/bins/1n6lw';
// Get the list of jobs
listJobs() {
// RESTful service, list of jobs:
// http://localhost:8080/batch/jobs.json
const endPoint = 'jobs.json'
// Return response
return this.http.get(this.jobsUrl)
.map(res => <Job[]> res.json().jobs.registrations);
}
}
Here is the JSON I am trying to parse. I am trying to print the {{job.name}}:
{ "mecConsolidatorKickoutJob": { "name": "mecConsolidatorKickoutJob", "resource": "http://localhost:8080/batch/jobs/mecConsolidatorKickoutJob.json", "description": "No description", "executionCount": 460, "launchable": false, "incrementable": false },
"meceinJob": { "name": "meceinJob", "resource": "http://localhost:8080/batch/jobs/meceinJob.json", "description": "No description", "executionCount": 125, "launchable": false, "incrementable": false },
"mecmdwJob": { "name": "mecmdwJob", "resource": "http://localhost:8080/batch/jobs/mecmdwJob.json", "description": "No description", "executionCount": 701, "launchable": false, "incrementable": false },
"mecmdwvalidatingJob": { "name": "mecmdwvalidatingJob", "resource": "http://localhost:8080/batch/jobs/mecmdwvalidatingJob.json", "description": "No description", "executionCount": 1998, "launchable": false, "incrementable": false },
"mecssnJob": { "name": "mecssnJob", "resource": "http://localhost:8080/batch/jobs/mecssnJob.json", "description": "No description", "executionCount": 217, "launchable": false, "incrementable": false } }
Before all bindings are resolved or when inputs are used that are received from async calls or because just a value is never assigned to a property, parameters passed to a pipe can be null.
A pipe should not throw when null is passed. Just check
transform(value) {
if(!value) {
return;
}
// process values that are != null here
return result;
}
Plunker example