I have been able to link an external json file and loop through some of the nested objects with ngFor as some of the the html is being put out on the website, but there is no data showing. If have been trying to put the data in an interface but it is still not showing up...
This is my module:
import { NgModule} from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { HttpModule } from '#angular/http';
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import 'rxjs/Rx';
import { Observable } from 'rxjs/Observable';
import { Service } from './app.service';
import { AppComponent } from './component.app';
#NgModule({
imports: [
BrowserModule,
HttpModule
],
declarations: [
AppComponent
],
bootstrap: [
AppComponent
],
providers: [
Service
]
})
export class AppModule {}
This is my component:
import { Component, OnInit } from '#angular/core';
import { Service } from './app.service';
import { Test } from './tests';
#Component({
selector: 'app',
templateUrl: './assets/partials/component-app.html',
styleUrls: ['./assets/css/component-app.css']
})
export class AppComponent implements OnInit{
tests: any;
constructor(private service : Service){}
ngOnInit() {
this.service.getData()
.subscribe(data => {
this.tests = data;
})
}
}
This is my service:
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class Service {
constructor(private _http: Http) {}
getData(): Observable<Test[]>{
return this._http.get('./assets/data/data.json')
.map(res => <Test[]>res.json().test_cases);
.map(res => <Test[]>res.json().test_steps);
}
}
The data interface:
export class Test {
test_run_id: string;
app_name: string;
time_stamp: string;
test_cases: {
test_name: string,
status: string,
test_steps: {
step_name: string,
screenshot: blob,
launch_times: array,
memory: array,
cpu: array
}
}
}
The json:
{
"test_run_id": "A233-CA92-3293-B9AA",
"app_name": "Chewy.com",
"time_stamp": "2018-01-20T12:00:00Z",
"test_cases": [
{
"test_name": "View dog bone",
"status": true,
"test_steps": [
{
"step_name": "Click Dog Category",
"screenshot": "file1.png",
"launch_times": [
100,
134,
123
],
"memory": [
896,
945,
1023
],
"cpu": [
1.1,
1.4,
5.7
]
},
{
"step_name": "Click Treats",
"screenshot": "file2.png",
"launch_times": [
345,
441,
286
],
"memory": [
1320,
1206,
1456
],
"cpu": [
12.1,
13.4,
12.7
]
},
{
"step_name": "Click Bone",
"screenshot": "file3.png",
"launch_times": [
342,
1456,
326
],
"memory": [
1420,
1420,
1420
],
"cpu": [
3.1,
4.4,
2.9
]
},
{
"step_name": "Verify Bone is displayed",
"screenshot": "file4.png",
"launch_times": [
103,
124,
123
],
"memory": [
1502,
1499,
1538
],
"cpu": [
2.1,
3.4,
3.7
]
}
]
},
{
"test_name": "View cat toy",
"status": false,
"test_steps": [
{
"step_name": "Click Cat Category",
"screenshot": "file5.png",
"launch_times": [
108,
194,
163
],
"memory": [
996,
945,
1223
],
"cpu": [
2.2,
2.4,
2.1
]
},
{
"step_name": "Click Toys",
"screenshot": "file6.png",
"launch_times": [
445,
408,
386
],
"memory": [
920,
1132,
995
],
"cpu": [
2.1,
3.2,
2.1
]
}
]
}
]}
HTML:
<section class="tested-app" *ngFor = "let item of tests">
<h2>----<span> {{ item.app_name }} </span>----</h2>
<p class="time"> Time: <span> {{item.time_stamp}} </span> </p>
<section class="flexWrap">
<div class="module" *ngFor="let subItem of item.test_cases">
<h3> {{ subItem.test_name }} </h3>
<p class="status"> {{subItem.status}} </p>
<div class="step" *ngFor = "let testStep of subItem.test_steps">
<h4>{{testStep.step_name}}</h4>
<img src="../assets/images/{{testStep.screenshot}}">
<div class="results">
<p>Launch Times:</p>
<ul>
<li>{{testStep.launch_times[0]}}</li>
<li>{{testStep.launch_times[1]}}</li>
<li>{{testStep.launch_times[2]}}</li>
</ul>
<p>Memory:</p>
<ul>
<li>{{testStep.memory[0]}}</li>
<li>{{testStep.memory[1]}}</li>
<li>{{testStep.memory[2]}}</li>
</ul>
<p>CPU</p>
<ul>
<li>{{testStep.cpu[0]}}</li>
<li>{{testStep.cpu[1]}}</li>
<li>{{testStep.cpu[2]}}</li>
</ul>
</div>
</div>
</div>
</section></section>
After a long discussion I'm pretty sure this should work:
Change your getData method like so:
getData(): Observable<Test[]>{
return this._http.get('./assets/data/data.json')
.map(res => <Test>res.json();
}
And then remove the first ngFor in your template:
<section *ngIf="tests" class="tested-app">
<h2>----<span> {{ tests.app_name }} </span>----</h2>
<p class="time"> Time: <span> {{tests.time_stamp}} </span> </p>
<section class="flexWrap">
<div class="module" *ngFor="let testCase of tests.test_cases">
<h3> {{ testCase.test_name }} </h3>
<p class="status"> {{testCase.status}} </p>
<div class="step" *ngFor = "let testStep of testCase.test_steps">
<h4>{{testStep.step_name}}</h4>
<img src="../assets/images/{{testStep.screenshot}}">
UPDATE:
Please have a look at this working sample. No errors in the console with the changes in the template.
https://stackblitz.com/edit/angular-duzb7z
Related
I am pretty new with Angular and I stuck with problem building up my portfolio project. The problem is with receiving list of (nested) objects like this:
"$id": "1",
"data": {
"$id": "2",
"$values": [
{
"$id": "3",
"id": 1,
"name": "producto",
"shortDescription": "prod11111",
"longDescription": "lorem ipsum bla bla",
"category": "1",
"price": 50.00,
"stockLevel": 10,
"orderDetails": {
"$id": "4",
"$values": []
}
},
{
"$id": "5",
"id": 2,
"name": "segundo",
"shortDescription": "prod222",
"longDescription": "lorem ipsum",
"category": "2",
"price": 30.00,
"stockLevel": 20,
"orderDetails": {
"$id": "6",
"$values": []
}
}
]
},
"error": null
}
This is my app.component.ts:
import { HttpClient } from '#angular/common/http';
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
title = 'Shop';
products: any[] = [];
constructor(private http: HttpClient) {}
ngOnInit(): void {
this.http.get('https://localhost:5001/api/products').subscribe((response: any) => {
this.products = response.data;
}, error => {
console.log(error);
});
}
}
This is app.component.html:
<app-nav-bar></app-nav-bar>
<div class="container" style="margin-top: 140px;">
<h1>Welcome to {{title}}!</h1>
<ul>
<li class="list-unstyled" *ngFor="let product of products">
{{product.name}}
</li>
</ul>
</div>
I looked thru StackOverflow for similar problems but cannot resolve this in my case.
I think that there is problem because of arrays of arrays or nested objects.
Any help is appreciated!
The response.data is not an array. Instead, I believe that response.data.$values is what you need for the products array.
this.http.get('https://localhost:5001/api/products').subscribe((response: any) => {
this.products = response.data.$values;
}, error => {
console.log(error);
});
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)}
)
}
}
I have issue with nested JSON file. I use primeNG templates dataTable and treeTable. When I try to access data via API call in console I can see data but in template I'm getting this error:
ERROR Error: Error trying to diff '[object Object]'. Only arrays and iterables are allowed
json file
{
"CategoryId": "257cf663-f6ba-40f7-69b8-08d527528e70",
"Name": "House Only",
"OverBudgetCalculator": true,
"Scopes": [
{
"ScopeId": 1,
"Name": "Budget",
"Question": {
"QuestionId": 1,
"Content": "What is your maximum budget ?",
"QuestionType": "range",
"Strict": true,
"NeutralScore": 10,
"Weight": 100,
"UpDownSelectionApplied": false,
"Active": true,
"RelatedProductFields": [
{
"RelatedProductFieldId": 3,
"FieldName": "Budget",
"Step": 1000,
"Min": 0,
"Max": 0
}
],
"Answers": []
}
},
{
"ScopeId": 2,
"Name": "Levels",
"Question": {
"QuestionId": 2,
"Content": "Do you want a single or double ?",
"QuestionType": "singleSelection",
"Strict": true,
"NeutralScore": 10,
"Weight": 95,
"UpDownSelectionApplied": false,
"Active": true,
"RelatedProductFields": [
{
"RelatedProductFieldId": 10,
"FieldName": "House_Only_Levels",
"Step": 0,
"Min": 0,
"Max": 0
}
],
"Answers": [
{
"AnswerId": 18,
"Title": "Double Story",
"Content": "Double Story",
"MatchRule": "Double",
"UpDownSpecifications": [],
"Selected": false
},
{
"AnswerId": 19,
"Title": "Single Story",
"Content": "Single Story",
"MatchRule": "Single",
"UpDownSpecifications": [],
"Selected": false
}
]
}
scope.service.ts
import { Injectable } from '#angular/core';
import { Http, Response, Headers, RequestOptions } from "#angular/http";
import { AppSessionService } from '#shared/common/session/app-session.service';
import { Observable } from 'rxjs/Observable';
import { Scope } from './scope';
import { TreeTableModule } from 'primeng/components/treetable/treetable';
#Injectable()
export class ScopeService {
constructor(
private http: Http,
private appSessionService: AppSessionService) { }
// GET api/categories/scopes/257CF663-F6BA-40F7-69B8-08D527528E70
getScopes(categoryId): Observable<any> {
let headers = new Headers({ 'Content-Type': 'application/json' })
let options = new RequestOptions({ headers: headers });
return this.http.get('/api/categories/' + categoryId)
.map((res: Response) => res.json())
.catch(this.handleErrorObservable);
}
private extractData(res: Response) {
let body = res.json();
return body.data || {};
}
private handleErrorObservable(error: Response | any) {
console.error(error.message || error);
return Observable.throw(error.message || error);
}
}
scope.component.ts
import { Component, Injector, OnInit, ViewChild } from '#angular/core';
import { AppComponentBase } from '#shared/common/app-component-base';
import { appModuleAnimation } from '#shared/animations/routerTransition';
import { ScopeService } from './scope.service';
import { DataTable } from 'primeng/components/datatable/datatable';
import { Paginator } from 'primeng/components/paginator/paginator';
import { TreeTableModule } from 'primeng/components/treetable/treetable';
#Component({
templateUrl: './scopes.component.html',
animations: [appModuleAnimation()]
})
export class ScopesComponent extends AppComponentBase implements OnInit {
errorMessage: String;
scopes: any = [];
categoryId: String = '257CF663-F6BA-40F7-69B8-08D527528E70';
constructor(
injector: Injector,
private scopeService: ScopeService
) {
super(injector);
}
ngOnInit(): void {
this.getScopes(this.categoryId);
}
getScopes(categoryId) {
this.scopeService.getScopes(categoryId).subscribe(values => {
this.scopes = values;
console.log(this.scopes);
})
}
}
This is component file with treeTable
scope.component.html (treeTable)
<p-treeTable [value]="scopes" [style]="{'margin-top':'50px'}">
<p-header>Editable Cells with Templating</p-header>
<p-column field="CategoryId" header="ScopeId">
<ng-template let-node="rowData" pTemplate="body">
<input type="text" [(ngModel)]="categories.Scopes.ScopeId" style="width:100%;border-width:0px 0px 1px 0px">
</ng-template>
</p-column>
<p-column field="Name" header="Name">
<ng-template let-node="rowData" pTemplate="body">
<input type="text" [(ngModel)]="categories.Scopes.Name" style="width:100%;border-width:0px 0px 1px 0px">
</ng-template>
</p-column>
</p-treeTable>
This is component file with dataDatable.
scope.components.html (dataTable)
<p-dataTable [value]="scopes"
selectionMode="single"
[rows]="10"
[responsive]="true">
<p-column field="Scopes" header="Scope name">
<ng-template let-account="rowData" pTemplate="body">
<ul>
<li *ngFor="let scope of categories.scopes">
{{scope.ScopeId}} - {{scope.Name}}
</li>
</ul>
</ng-template>
</p-column>
</p-dataTable>
When I use dataTable option I'm getting different error.
ERROR TypeError: val.slice is not a function
enter image description here
enter image description here
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
I am trying to get the json data from an Angular service hero.service.ts. When using the fake http API inMemoryDataService, everything works fine and I am getting the json data from the in-memory-data.service.ts file. But when I try to get the data from a real json file, it does not work and I am getting an error 'collection not found' in the browser.
Here are the files contents (all 3 files are located in the app/ folder):
hero.service.ts :
import { Injectable } from '#angular/core';
import { Headers, Http , Response} from '#angular/http';
import 'rxjs/add/operator/toPromise';
import { Hero } from './hero';
#Injectable()
export class HeroService {
private heroesUrl = 'app/fakeListOfHeroes'; // URL to web api
//private heroesUrl = 'app/heroes.json'; // URL to JSON file
constructor(private http: Http) { }
getHeroes(): Promise<Hero[]>
{
return this.http.get(this.heroesUrl)
.toPromise()
.then(response => response.json().data)
.catch(this.handleError);
}
private handleError(error: any)
{
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
}
hero.service.ts :
export class InMemoryDataService {
createDb() {
let fakeListOfHeroes = [
{id: 11, name: 'Mr. Nice'},
{id: 12, name: 'Narco'},
{id: 13, name: 'Bombasto'},
{id: 14, name: 'Celeritas'},
{id: 15, name: 'Magneta'},
{id: 16, name: 'RubberMan'},
{id: 17, name: 'Dynama'},
{id: 18, name: 'Dr IQ'},
{id: 19, name: 'Magma'},
{id: 20, name: 'Tornado'}
];
return {fakeListOfHeroes};
}
}
heroes.json :
{
"data": [{
"id": 11,
"name": "Mr. Nice"
}, {
"id": 12,
"name": "Narco"
}, {
"id": 13,
"name": "Bombasto"
}, {
"id": 14,
"name": "Celeritas"
}, {
"id": 15,
"name": "Magneta"
}, {
"id": 16,
"name": "RubberMan"
}, {
"id": 17,
"name": "Dynama"
}, {
"id": 18,
"name": "Dr IQ"
}, {
"id": 19,
"name": "Magma"
}, {
"id": 20,
"name": "Tornado"
}]
}
Error in the browser:
error in browser
Any help would be appreciated. Thanks!
Found it ! It was due to the InMemoryBackendService and InMemoryDataService used in main.ts file, that seem to 'redirect' the calls from http.get method. Commenting those lines from main.ts file resolved the issue :
// Imports for loading & configuring the in-memory web api
import { XHRBackend } from '#angular/http';
//import { InMemoryBackendService, SEED_DATA } from 'angular2-in-memory-web-api';
//import { InMemoryDataService } from './in-memory-data.service';
// The usual bootstrapping imports
import { bootstrap } from '#angular/platform-browser-dynamic';
import { HTTP_PROVIDERS } from '#angular/http';
import { AppComponent } from './app.component';
import { appRouterProviders } from './app.routes';
bootstrap(AppComponent, [
appRouterProviders,
HTTP_PROVIDERS
/*,
{ provide: XHRBackend, useClass: InMemoryBackendService }, // in-mem server
{ provide: SEED_DATA, useClass: InMemoryDataService } // in-mem server data
*/
]);