I'm starting with angular2. And I try to get data from an php script.
I followed the turorial at the angular docs. But I recently get this confusing error messeage:
zone.js:463 ViewWrappedException {_wrapperMessage: "Error in app/components/catch-data/catch-data.component.html:7:5", _originalException: TypeError: Cannot read property 'name' of undefined
at DebugAppView._View_CatchDataComponent0.de…, _originalStack: "TypeError: Cannot read property 'name' of undefine…t/node_modules/#angular/core/core.umd.js:9996:18)", _context: DebugContext, _wrapperStack: "Error: Error in app/components/catch-data/catch-da…tChangesInternal (AppComponent.template.js:121:8)"}
containing this message:
TypeError: Cannot read property 'name' of undefined
at DebugAppView._View_CatchDataComponent0.detectChangesInternal (CatchDataComponent.template.js:62)
at DebugAppView.AppView.detectChanges (core.umd.js:9996)
at DebugAppView.detectChanges (core.umd.js:10084)
at DebugAppView.AppView.detectViewChildrenChanges (core.umd.js:10016)
at DebugAppView._View_CatchDataComponent_Host0.detectChangesInternal (CatchDataComponent_Host.template.js:36)
at DebugAppView.AppView.detectChanges (core.umd.js:9996)
at DebugAppView.detectChanges (core.umd.js:10084)
at DebugAppView.AppView.detectContentChildrenChanges (core.umd.js:10011)
at DebugAppView._View_AppComponent0.detectChangesInternal (AppComponent.template.js:121)
at DebugAppView.AppView.detectChanges (core.umd.js:9996)
I have no idea where this error comes from. Here is my code:
model.service.ts
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import { Model } from '../../class/model/model';
#Injectable()
export class ModelService
{
constructor(private http: Http){}
private modelUrl = '../../server/clientFunc/getModel.php';
getModel (): Promise<Model> {
return this.http.get(this.modelUrl).toPromise().then(response => response.json()).catch(this.handleError);
}
private handleError(error: any) {
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
}
catch-data.component.ts
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router-deprecated';
import {Model} from '../../class/model/model';
import {ModelService} from '../../services/model/model.service';
#Component({
selector: 'catch-data',
templateUrl: 'app/components/catch-data/catch-data.component.html',
providers: [ModelService]
})
export class CatchDataComponent implements OnInit
{
constructor(private modelService:ModelService) {
}
model:Model;
errorMessage:string;
testItem = "Test-Item";
ngOnInit():any {
this.getModel();
}
getModel() {
this.modelService.getModel()
.then(response => {
this.model = new Model();
this.model.deserialize(response);
})
.catch(error => {
this.errorMessage = error;
console.log(error);
}); // TODO: Display
}
}
and the model.ts
export class Model
{
id:number;
name:string;
constructor(){
}
deserialize(object){
this.name = object.name;
this.id = object.id;
}
}
The template looks like:
<h1>Search and catch data</h1>
<h3>Model: {{testItem}}</h3>
<div>Name: {{model.name}}</div>
So as I could detect the CatchDataComponent gets null as I call getModel().
So in ngOnInit this is not null but a call later in getModel() this is null.
I have no Idea why this happens.
I hope you have an idea or any suggestions.
I think that you could use the Elvis operator:
<div>Name: {{model?.name}}</div>
because the model property is loaded asynchronously and not available when the model.name is evaluated at first...
Related
So I am relatively new to Ionic and Firebase, and I am trying to display user data that already exists in Firebase.
Here is the error that I am getting:
invalidpipeargument: '[object object']: error showing.
I do know what the issue is after looking at other questions similar to mine. It seems I cannot assign the async function as database.object does not return an observable. So I have tried to add .valueChanges(); to make it an observable, but I believe this is clashing with the angularfireobject as that is already assigned to the variable profile.data so this would not work.
I have also tried this:
// get (): AngularFireObject<any[]>{
//return this.afDatabase.list`/profile/${data.uid}`;
//}
If you point me in the right direction that would be great.
Here is my code:
.ts file
import { Component } from '#angular/core';
import { NavController, ToastController } from 'ionic-angular';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFireDatabase, AngularFireObject} from 'angularfire2/database';
import { Profile } from '../../model/profile';
import { DEFAULT_INTERPOLATION_CONFIG } from '#angular/compiler';
#Component({
selector: 'page-about',
templateUrl: 'about.html'
})
export class AboutPage {
profileData: AngularFireObject<Profile>
// get (): AngularFireObject<any[]>{
//return this.afDatabase.list`/profile/${data.uid}`;
//}
constructor(private afAuth:AngularFireAuth, private afDatabase: AngularFireDatabase,
public navCtrl: NavController, private toast: ToastController) {
}
ionViewDidLoad() {
this.afAuth.authState.take(1).subscribe(data =>{
if (data && data.email && data.uid){
this.toast.create({
message: `Welcome to MatchMyFighter ${data.email}`,
duration: 3000,
}).present();
// this.profileData = this.afDatabase.object(`profile/${data.uid}`)
this.profileData = this.afDatabase.object(`/profile/${data.uid}`).valueChanges();;
}
else{
this.toast.create({
message:`could not autenticate`,
duration:3000
}).present;
}
})
}
}
.html
<p>
Username: {{(profileData | async)?.username}}
</p>
The call to valueChanges() converts the AngularFireObject<Profile> to an observable.
You have to change the type to Observable<Profile> like so:
profileData: Observable<Profile>;
constructor(private db: AngularFireDatabase) { } // other stuff emitted ...
ionViewDidLoad() {
// ...
this.profileData = this.db.object<Profile>(`/profile/${data.uid}`).valueChanges();
// ...
}
I have seen this error on SO quite a few times, all I can find on it is that I need to make sure that I have my service Provided in my app.modules, and then call it in my constructor of my component. I have done this and am still getting the error. Also I have both http and HTTPMODULES in my application. The error only occurs when I use the delete functionality in my application. Here is the error error_handler.js:45 EXCEPTION: Cannot read property 'get' of undefined, here is some relevant code....
app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { HttpModule, JsonpModule } from '#angular/http'; <------------HTTP
import { AppComponent } from './app.component';
import { PostRantComponent } from './postRant.component';
import { PostDataService } from './PostData.Service'; <------------service
import { Constants } from './app.const.service';
import { Routing } from './app.routes';
import { FormsModule } from '#angular/forms';
#NgModule({
imports: [NgbModule.forRoot(), BrowserModule, Routing, FormsModule, HttpModule, JsonpModule],
declarations: [AppComponent,,PostRantComponent],
providers: [PostDataService, Constants],
bootstrap: [AppComponent]
})
export class AppModule { }
Service (tried cutting it down to just show relevant code)
import { Injectable } from '#angular/core';
import { Http, Response, Headers } from '#angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { Observable } from 'rxjs/Observable';
import { PostViewModel } from './models/Post';
import { Constants } from './app.const.service';
#Injectable()
export class PostDataService{
private actionUrl: string;
private headers: Headers;
constructor( private _http: Http, private _constants: Constants ){
this.actionUrl = _constants.ServerWithApi;
this.headers = new Headers();
this.headers.append('Content-Type', 'application/json');
this.headers.append('Accept','application/json');
}
public GetAll = (): Observable<PostViewModel[]> => {
return this._http.get(this.actionUrl)
.map((response: Response) => <PostViewModel[]>response.json())
.catch(this.handleError);
}
public Delete = (id: string) =>{
return this._http.delete(this.actionUrl + id)
.map(res => res.json())
.catch(this.handleError);
}
}
Component
import { Component, Attribute, OnInit,ViewChild } from '#angular/core';
import { PostViewModel } from './models/Post';
import { PostDataService } from './PostData.Service';
import { Constants } from './app.const.service';
#Component({
selector: 'postRant',
templateUrl: 'html/postRant.html',
})
export class PostRantComponent implements OnInit {
txtTitle: string;
txtDescription: string;
public myPosts : Array<PostViewModel>;
public newPost : PostViewModel = new PostViewModel();
constructor(private auth:Auth, private _dataservice: PostDataService){
}
ngOnInit(){
this.getAllItems();
}
private getAllItems():void {
this._dataservice
.GetAll()
.subscribe((Post: Array<PostViewModel>) => this.myPosts = Post,
error => console.log(error),
() => console.log('get all items complete'))
}
delete(id){
console.log(id);
this._dataservice.Delete(id)
.subscribe((res) => {
this.myPosts = res;
});
var index = this.myPosts.findIndex(x => x.id == id);
this.myPosts.splice(index, 1);
}
}
If you are interested in all the code I have it posted on my git located here, however it is rather large.
EDIT
picture of error....
it appears that the error is produced by line 52 of PostData.Service.ts
i.e. var applicationError = error.headers.get('Application-Error');
this makes me guess that your GetAll Http call is erroring out, but the server you are asking for data is not returning data in the format of error.headers
Add a debugger; to the handleError and check the object that it is receiving.
I am currently building an Angular2 application accessing an MVC web API i have built. However, it does not seem to retrieve any data. I am obviously missing something but i am not sure what.
I know that the URL i am using works along with the headers as i am able to retrieve the data correctly through fiddler.
My repack.service.ts is as follows:
import { Injectable } from '#angular/core';
import { Headers, Http } from '#angular/http';
import 'rxjs/add/operator/toPromise';
import { RepackIndex } from './RepackIndex';
#Injectable()
export class RepackService{
private baseUrl = 'https://localhost:44321/api/Repack/All';
private headers = new Headers({'Content-Type': 'application/json'});
constructor(private http: Http) { }
getAllRepacks(): Promise<RepackIndex[]>{
var data = this.http.get(this.baseUrl)
.toPromise()
.then(response => response.json().data as RepackIndex[])
.catch(this.handleError);
return data;
}
private handleError(error: any): Promise<any>{
console.error("An error occured in repack.service", error);
return Promise.reject(error.message || error);
}
}
And this is my component:
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { RepackIndex } from './repackIndex';
import { RepackService } from './repack.service';
#Component({
selector: 'index',
templateUrl: 'app/index.component.html',
providers: [RepackService]
})
export class IndexComponent implements OnInit{
repacks: RepackIndex[];
selectedRepack: RepackIndex;
constructor(private router: Router, private repackService: RepackService) { }
onSelect(repack: RepackIndex): void{
this.selectedRepack = repack;
}
getRepacks(): void{
this.repackService.getAllRepacks().then(repacks => this.repacks = repacks);
}
ngOnInit(): void{
this.getRepacks();
}
}
I have tried putting in a breakpoint and adding a console.log line but no data is returned to the component.
I am fairly new to Angular2 so any help would be greatly appreciated.
Thanks,
Right I have managed to get it to work by using an observable rather than a promise.
My service method now looks like this:
public GetAll = (): Observable<RepackIndex[]> => {
return this.http.get(this.baseUrl)
.map((response: Response) => <RepackIndex[]>response.json())
.catch(this.handleError);
}
And my Component call now looks like this:
getRepacks(): void{
this.repackService.GetAll()
.subscribe((data:RepackIndex[]) => this.repacks = data,
error => console.log(error),
() => console.log('Get All repacks complete'));
}
I found the answer here
Hope this helps someone else
I'trying to use the HTTP service in Angular2 and i have some concerns.
I'm taking meteo datas from openweather API and I just want to put it inside a typeScript variable (meteo: {}) and use it as i want in my template.
Here are my .ts files:
meteo.service.ts
import {Injectable} from "angular2/core";
import {Http, Response} from "angular2/http";
import {Observable} from "rxjs/Observable";
import {MeteoComponent} from "../widgets/meteo/meteo.component";
import {Meteo} from "../widgets/meteo/meteo";
#Injectable()
export class MeteoService {
constructor(private http: Http) {}
// Nom de la ville sans accent
private _ville = 'Montreal';
// Initiales du pays
private _country = 'ca';
// Units (metric/imperial)
private _units = 'metric';
// API KEY
private _APPID = 'ewfw54f5646';
// url to get data
private _meteoUrl = 'http://api.openweathermap.org/data/2.5/weather?q='+this._ville+','+this._country+'&units='+this._units+'&APPID='+this._APPID;
getMeteo (): Observable<Meteo> {
return this.http.get(this._meteoUrl)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
if(res.status < 200 || res.status >= 300) {
throw new Error('Bad response status: ' + res.status);
}
let body = res.json();
return body || { };
}
private handleError(error: any) {
let errMsg = error.message || 'server error';
console.error(errMsg);
return Observable.throw(errMsg);
}
}
meteo.component.ts
import {Component, OnInit, OnChanges, AfterContentInit} from "angular2/core";
import {MeteoService} from "../../services/meteo.service";
import {Meteo} from "./meteo";
#Component({
selector: 'meteo',
templateUrl: 'dev/widgets/meteo/meteo.component.html',
providers: [MeteoService]
})
export class MeteoComponent implements OnInit {
errorMessage: string;
meteo: Meteo;
// We inject the service into the constructor
constructor (private _meteoService: MeteoService) {}
// Instantiate data in the ngOnInit function to keep the constructor simple
ngOnInit() {
this.getMeteo();
}
getMeteo() {
this._meteoService.getMeteo()
.subscribe(
data => this.meteo = data,
error => this.errorMessage = <any>error);
}
}
meteo.ts
export class Meteo {
data: {};
}
and meteo.component.html
<span class="meteo">{{meteo | json}}°C</span>
Actually the result is the entire json object:
{
"coord": {
"lon":-73.59,
"lat":45.51
},
"weather":[
{
"id":803,
"main":"Clouds",
"description":"broken clouds",
"icon":"04d"
}
],
"base":"cmc stations",
"main":{
"temp":3.96,
"pressure":1020,
"humidity":32,
"temp_min":2,
"temp_max":6.67
},
"wind":{
"speed":2.1
},
"clouds":{
"all":75
},
"dt":1461594860,
"sys":{
"type":1,
"id":3829,
"message":0.004,
"country":"CA",
"sunrise":1461577807,
"sunset":1461628497
},
"id":6077243,
"name":"Montreal",
"cod":200
}
And I would like to display just the temp field.
If you have any idea guys it's welcomed!
Thanks a lot.
You could leverage the Elvis operator since your data are loaded asynchronously:
<span class="meteo">{{meteo?.main.temp | json}}°C</span>
Try setting the data on this.meteo.data
getMeteo() {
this._meteoService.getMeteo()
.subscribe(
data => this.meteo.data = data,
error => this.errorMessage = <any>error);
}
and then displaying it with
<span class="meteo">{{meteo.data.main.temp}}°C</span>
Angular 2 is fairly new. I have been using firebase-angular2 to create a service.
I ran the firebase-angular2 demo here https://github.com/KallynGowdy/firebase-angular2-demo but when I have been running it I get the following error
EXCEPTION: TypeError: heroes.map is not a function
angular2.dev.js:23083 EXCEPTION: TypeError: heroes.map is not a function
As far as I can tell it is referring to this section of code at ts/firebase-heros.service.ts
import {Injectable} from "../../node_modules/angular2/core";
import {HeroService} from "./hero.service";
import {Observable} from "../../node_modules/rxjs/Rx";
import {FirebaseService} from '../../node_modules/firebase-angular2/core';
import {Hero} from "./../interfaces/hero";
#Injectable()
export class FirebaseHeroService extends HeroService {
private service:FirebaseService;
constructor(firebaseService:FirebaseService) {
this.service = firebaseService.child('heroes');
}
getHeroes() {
var service = this.service;
return service.value.map((heroes) => {
return heroes.map((h, i) => {
// TODO: Cleanup
return {
id: h.id,
name: h.name,
save: function () {
return service.child(i.toString()).setData({
id: this.id,
name: this.name
});
}
}
})
});
}
}
Any ideas of what may be causing this problem?
thanks in advance
heroes is not array at this line, that's why you're getting an error:
return service.value.map((heroes) => {
console.log(heroes);
...
If you log it's value you can check what type it is and take appropriate action. If it's a response, you might need to convert it to JSON before processing it further
return service.value
.map(response => response.json())
.map((heroes) => {...