I want to know how to create PHP to get data for show home.html
and I get `Error data is not defined
I don't know this correct? please check this. I have not idea to create PHP, I want to set $path to keep my URL.
<ion-content>
<ion-list inset>
<ion-item>
<ion-label>Username</ion-label>
<ion-input [(ngModel)]="data.username" type="text"></ion-input>
</ion-item>
</ion-list>
<div padding>
<button ion-button block (click)="getRepos()">Search</button>
</div>
<ion-card *ngFor="let repo of foundRepos" >
<ion-card-header>
{{ repo.data.name }}
</ion-card-header>
<ion-card-content>
{{ repo.data.description }}
</ion-card-content>
</ion-card>
</ion-content>
.
import { Component } from "#angular/core";
import { NavController } from 'ionic-angular';
import { Http } from '#angular/http';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
public foundRepos;
constructor(public http: Http) {
this.data = {}; >>>>>>>data is not defined
data.username = ''; >>>>>data is not defined
this.http = http;
}
getRepos() {
var link = 'http://localhost/github.php';
var data = JSON.stringify({username: this.data.username}); <<<<this.data.username (data is not defined)
this.http.get(link, data) <<<<data is not defined
.subscribe(data => {
this.foundRepos = data.json();
},
err => console.error(err),
() => console.log('getRepos completed')
);
}
}
github.php
<?php
$postdata = file_get_contents("php://input");
if (isset($postdata)) {
$request = json_decode($postdata);
$username = $request->username;
if ($username != "") {
$path = "https://api.github.com/users/".$username."/repos";
echo $path ;
}
else {
echo "Empty username parameter!";
}
}
else {
echo "Not called properly with username parameter!";
}
?>
Ah I see.
In your php you're retrieving a value called $postdata. So I assume you want to send the username from your ionic 2 application to your php file.
2 options, you should try them both because I do not understand php so I'm not sure what the right solution is.
But I do know what the problem is. You're making an http.get() call, and you're passing 2 arguments in this. link and data. The GET method is for getting data from your link, not giving it. The http.get takes 2 parameters, the url, in your case named link, and an HttpHeaders object, so not data.
Solution with parameter in http.get
So, as mentioned above, http.get() can't send your data. Unless you add it as a parameter in your URL. Then your typescript would look like this (note: backticks instead of ' ', makes string concatination easier):
var link = `http://localhost/github.php?username=${this.data.username}`;
this.http.get(link).subscribe(data) { .... }
And in php replace
$username = $response->username
with
$username = $_GET['username']
So final typscript looks like this (since php get request returned 403, Github probably disallowed it)
getRepos() {
var link = `localhost/…${this.data.username}`;
this.http.get(link)
.subscribe(data => {
let repoUrl = data.text();
this.http.get(repoUrl).subscribe(githubResponse => {
this.foundRepos = githubResponse.json();
});
},
err => console.error(err),
() => console.log('getRepos completed')
);
}
If anyone is seeking detailed explanation to why we came to this answer, pleek look in the chat below
You have not declared data variable in the class.
export class HomePage {
public foundRepos;
public data;//here
constructor(public http: Http){
this.data = {};
this.data.username = '';//to refer to data in any function always use 'this'
}
//other functions
Related
First of all, sorry if my english isn't perfect, I'm french.
I'm creating a mobil app with Ionic 3 / angular 4.
My data are stored in a local JSON file in "assets/data" and I'm accessing it with a Provider.
I have a homePage with formular with data value for my 'selector/option input' and I request my provider which returns data by filter/sort etc ...
Everything works but ... it's kind of ugly.
For now, I'm actually using a button at the top of my form to initialize my Provider because I'm calling the 'http.get' method in my Provider constructor (Yeah ... I know it's kind of bad).
I'm using this temporary solution while waiting to find a way to initialize my Provider on the splash screen or in 'ionViewDidLoad' Event ...
my Provider constructor :
#Injectable()
export class DataBaseProvider {
capaciteUrl = './assets/data/capacite.json';
mixageUrl = "./assets/data/mixage.json";
mixageData: any;
capaciteData: any;
constructor(public http: Http) {
console.log('dataBase init');
this.http.get(this.capaciteUrl)
.map(res => res.json())
.subscribe( data => this.capaciteData = data.data);
this.http.get(this.mixageUrl)
.map(res => res.json())
.subscribe( data => this.mixageData = data.data);
}
my 'initializer' function in my homePage.ts ( called by button )
init() {
this.dataBase.getDataSelector()
.then(data => {
this.mixage = data['mixage'];
this.capacite = data['capacite'];
this.firstIngredient = this.secondIngredient = data['ingredient'];
})
}
A part of my form :
<ion-select [(ngModel)]="mixageSelector" okText="Select">
<ion-option *ngFor="let mix of mixage" [value]="mix.id"> {{mix.name}} </ion-option>
</ion-select>
Where can I call the Http.get method or How can I rewrite my module to call Http method at loading/splashScreen of my application ? ( I also try to call my getDataSelector() in an ionViewDidLoadEvent() but nothing changes ... )
I am trying to pass/get a specific data from one page to another page using NavParams but I always get undefined result in the console. I do not know what seems to be the problem. Here is my code:
order.ts (TS file where I want to get the data)
postOrder(ordernum) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
let data=JSON.stringify({
mode_code: this.data2code,
order_totalpayment: this.dataquantity,
order_status: this.status
});
this.http.post('http://<--My JSON API-->/xxx/api.php/ordered?transform=1',data,headers)
.map(res => res.json())
.subscribe(res => {
console.log("Success Order No.: "+res);
this.ordernum = res;
let data2=JSON.stringify({
order_no: this.ordernum,
prod_id: this.dataid,
order_subtotal: this.dataquantity
});
this.http.post('http://xxxx/xxx/api.php/order_list?transform=1',data2,headers)
.map(resp => resp.json())
.subscribe(resp => {
console.log("Order List No.: "+resp);
this.nav.setRoot(ConfirmorderPage, { ordernum: ordernum });
}, (err) => {
this.showPopup("Oops!", "Something went wrong.");
});
}, (err) => {
this.showPopup("Oops!", "Something went wrong.");
});
}
In the code, what I am trying to get is the this.ordernum data. So that I use this codes: postOrder(ordernum) this.nav.setRoot(ConfirmorderPage, { ordernum: ordernum });
order.html (HTML file in where I did pass the data to another page)
<div">
<div padding>
<p>Your Order Number is {{ordernum}}</p>
</div>
</div>
<div style="margin: 10px;">
<button ion-button block color="orange" (click)="postOrder(ordernum)" >Place Order</button>
</div>
</div>
the data I wanted was the ordernum so that I put it in the click function (click)="postOrder(ordernum)"
confirmorder.ts (TS file where I want to pass the data ordernum from the orderpage)
constructor(public navCtrl: NavController, public navParams: NavParams) {
this.order = this.navParams.get('ordernum');
console.log(this.order);
}
I used this.navParams.get('ordernum') to get the data from the orderpage and
I pass the ordernum data to the this.order variable but when I tried to show it in the console, I am getting undefined result. I have no idea what is wrong with my code. Hope you guys can help me. Thank you in advance.
this.nav.setRoot(ConfirmorderPage, { ordernum: ordernum });
Here in your object, both key and value are the value of variable ordernum. Your key needs to be a string so use quotes.
Also use this to ensure you point to the correct variable (you seem to have a class variable as well as a parameter of name ordernum?).
Do:
this.nav.setRoot(ConfirmorderPage, { 'ordernum': this.ordernum });
I'm writing my first Ionic 2 app and am struggling to get my head around something that I didn't have to worry about in Ionic 1.
I have a list view which lists items fetched from an API. This works fine. When you click on an item in the list view, you go to a detail view (which makes another ajax call to fetch additional details). This view renders before the ajax call has completed and I'm really not sure why.
Service:
import {Injectable} from '#angular/core';
import {Http} from '#angular/http';
import 'rxjs/Rx';
#Injectable()
export class DataService {
http: any;
baseUrl: String;
apiKey: String;
constructor(http:Http) {
this.http = http;
this.baseUrl = 'http://localhost:8100/api';
this.apiKey = 'xxx';
}
getList(token, page) {
return this.http.get(this.baseUrl + '/list?key=' + this.apiKey + '&token=' + token + '&page=' + page + '&per_page=20')
.map(res => res.json());
}
getDetails(token, ref) {
return this.http.get(this.baseUrl + '/details/' + ref + '?key=' + this.apiKey + '&token=' + token)
.map(res => res.json());
}
}
Problem page:
import { Component } from '#angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { Storage } from '#ionic/storage';
import { DataService } from '../../app/services/data.service';
#Component({
selector: 'details',
templateUrl: 'details.html'
})
export class DetailsPage {
token: string;
item: any;
ref: string;
constructor(public navCtrl: NavController, private dataService:DataService, private storage: Storage, public params:NavParams) {
this.ref = params.get('ref');
}
getDetail(token, ref) {
this.dataService.getDetails(token, ref).subscribe(
data => {
// this completes after the view has rendered, so the view errors
this.item = data;
console.log('this.item = ');
console.log(this.item);
},
err => {
console.log(err);
// handle expired token and redirect
}
);
}
ngOnInit() {
console.log('on init ran...');
this.storage.get('token').then((val) => {
this.token = val;
this.getDetail(this.token, this.ref);
});
}
}
Every var in my template errors, for example, the first is:
Runtime Error
Cannot read property 'ref' of undefined
Am I missing something obvious or is there a better way to go about this? All the tutorials I find have the ajax call in the class and not in a service which can't be right...
--- edit ---
As requested here is the nav push from the list page:
viewDetailsPage(ref) {
this.navCtrl.push(DetailsPage, {
ref: ref
})
}
--- edit 2 ---
As requested here is the list page template:
<ion-header>
<ion-navbar>
<ion-title>Items</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<button ion-item *ngFor="let item of items" (click)="viewDetailsPage(item.reference)" icon-start>
<h2>{{item.reference}}</h2>
<p>{{item.type.title}}</p>
<ion-badge item-end>{{item.status.title}}</ion-badge>
</button>
</ion-list>
</ion-content>
and the details page template:
<ion-header>
<ion-navbar>
<ion-title>Item</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<h4>{{item.reference}}</h4>
</ion-content>
Change {{item.reference}} to {{item?.reference}}
or
item: any = {} instead of item: any;
As view render before ajax call, it try to get reference property of item. Since item is still type of any and not object, it throw error.
{{item?.reference}} to handle asynchronous variables.
After not being able to find a single example anywhere of a "popped" page making ajax calls I ended up making the getDetail ajax call from the list page instead and passing the data to the details page like:
List page, when a list item is clicked:
viewDetailsPage(ref) {
this.DataService. getDetails(this.token, ref).subscribe(
data => {
this.item = data;
this.navCtrl.push(DetailsPage, {
item: this.item
})
},
err => {
console.log(err);
// handle expired token and redirect
}
);
}
Feels like this is the proper way of doing it though would love some confirmation of this.
---- update ----
whilst this works, I ended up going with the accepted answer.
I'm working on a feature for my website to provide news feed. To get news feed, I have generated an API key from here : News API. The problem I'm facing is that, I'm not able to display the content in my browser. Let me share my code :
results.component.html
<ul type="none" id="search-options">
<li [class.active_view]="Display('all')" (click)="docClick()">All</li>
<li [class.active_view]="Display('news')" (click)="newsContent()">News</li>
<li [class.active_view]="Display('images')" (click)="imageClick()">Images</li>
<li [class.active_view]="Display('videos')" (click)="videoClick()">Videos</li>
</ul>
In results.component.html, it has 4 tabs. In tabs with name : All, Image, Video - I'm getting data from the server from which the desired results are fetched based on query. But in News tab, I'm trying to integrate it with the API which I have mentioned above. Clicking on that tab, should show news feed (just keeping it simple). But, it does not displays anything when news tab is clicked. (No console errors) However, if I use html repeater, how I'm going to use it here ?
news.component.ts
newsFeed: {};
resultDisplay: string;
constructor(private _newsService: NewsService) {}
Display(S) {
return (this.resultDisplay === S);
}
newsContent() {
this.resultDisplay = 'news';
this._newsService.getNews().subscribe(data => {
this.newsFeed = Object.assign({}, data);
});
}
news.service.ts
import { Injectable } from '#angular/core';
import { Http, Jsonp } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class NewsService {
public generalNews: string = 'https://newsapi.org/v1/articles?source=bbc-news&sortBy=top&apiKey=abc123';
constructor(
private http: Http,
private jsonp: Jsonp
) { }
getNews() {
return this.http.get(this.generalNews).map(response => {
response.json()
});
}
}
It would be great if anybody can point out what mistake I'm doing and provide me the solution to improve it. Thanks in advance. :)
Based on what I got from your question. You should do the following.
Have a repeater on your html first. Something like:
<div *ngFor = "let news of newsList">
<p> {{news}} </p>
</div>
This way you can iterate the news array on your html one news at a time.
Next thing, is getting the response and passing it to the view. I am assuming you get the news on click of <li>, as that is all your view presently contains. So in your component you should have
private newsList: any[] = [] //initializing a blank list of type any.
newsContent() {
this.resultDisplay = 'news'; //not sure why you need this, but let it be for now
this._newsService.getNews().subscribe(data => {
this.newsList = data; //assuming data is the actual news array, if the data is entire response you might have to go for data.data
});
}
This way your newsList variable is populated and will be iterated on the html. May be you might have to make few adjustment but it should help you start.
Let me know if it helps or any further issue faced.
Few more changes would be required based on your response:
First : return data from your service method like:
getNews() {
return this.http.get(this.generalNews).map(response:any => {
return response.json()
});
}
Second, your data contains news in article array. So use that instead:
newsContent() {
this.resultDisplay = 'news'; //not sure why you need this, but let it be for now
this._newsService.getNews().subscribe(data => {
this.newsList = data.article; //assuming data is the actual news array, if the data is entire response you might have to go for data.data
});
}
Next edit your html to bind a particular field of your news. I am binding title you can bind one or more that you like:
<div *ngFor = "let news of newsList">
<p> {{news.title}} </p>
</div>
Try this. should work now.
You have missed return statement return response.json().
news.service.ts
import { Injectable } from '#angular/core';
import { Http, Jsonp } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class NewsService {
public generalNews: string = 'https://newsapi.org/v1/articles?source=bbc-news&sortBy=top&apiKey=abc123';
constructor(
private http: Http,
private jsonp: Jsonp
) { }
getNews() {
return this.http.get(this.generalNews).map(response => {
return response.json();
});
}
}
I have an problem with the .subscribe function.
First I have an function to send a request to the server. That's it.
protected sendRequest(data:string,url:string):Observable<any>{
let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
let options = new RequestOptions({ headers: headers });
//let body = 'email=' + 'email' + '&password=' + 'password';
return this.http.post(url, data, options).map(response => response.json());
}
Now the user.service delegates the sendResquest to this file, I have injected the server.service in the user.service and so on.
public login(email:string, password:string):Observable<any>{
//format data to send
let data:string = 'email=' + email + '&password=' + password;
//let body = 'email=' + 'email' + '&password=' + 'password';
let serverReturn:Observable<any> = this.sendRequest(data,"server/request/signin.php");
//Log the server return
//console.log(serverReturn);
serverReturn.subscribe(
//set the token and session elements of a logged user
function(data){
//console.log(data);
//console.log(data.isSigned);
if(data.isSigned == "true"){
sessionStorage.setItem("isSigned","true");
sessionStorage.setItem("userToken", data.userToken);
} else if(data.userBlocked == "true"){
sessionStorage.setItem("isSigned", "false");
} else {
sessionStorage.setItem("isSigned", "false");
}
}
);
return serverReturn;
}
Now what I whant is get this serverReturn in the componentLogin, so there I have to know what to do based on the response for this calling.
But the callback from .subscribe seems not to have access to the properties of this class.
I'm following this answer
There I learned that:
Usually, you take the results from the success callback and assign it to your variable.
Finally this is my login component witch call the login from user.service
import { Component, ElementRef, ViewChild } from '#angular/core';
import { ModalComponent } from '../../ui/modal/modal.component';
import { UserService } from '../../utils/user.service';
#Component({
selector: 'login',
templateUrl: 'app/system/login/tpl.html',
styleUrls: ['app/system/login/style.css'],
directives: [ModalComponent],
providers: [UserService]
})
export class LoginComponent {
constructor(private userService:UserService, private elementRef:ElementRef){
}
private result:Array<any>;
#ViewChild(ModalComponent) modal:ModalComponent;
private signin():void{
let email:string = this.elementRef.nativeElement.querySelector("#email").value;
let password:string = this.elementRef.nativeElement.querySelector("#password").value;
this.userService.login(email, password).subscribe(data => this.result = data);
console.log(this.result);
//this.modal.showModal('Login ','Login');
}
}
The problem is that any variable or change that I try to do within the success callback I get an undefined return. If I call a method, any method from the subscribe this get me an error too.
For example, if I try to do this.
this.userService.login(email, password).subscribe(
function(data){
this.modal.showModal('Login ','Login');
}
);
I get an error:
EXCEPTION: TypeError: Cannot read property 'showModal' of undefined
What I get wrong? I'll try to set the result to an class variable. Why that all I call within the subscribe callback function seems to be undefined?
I'll appreciate any help on this. Thanks.
As Jason Goemaat already mentioned, you need to use lambdas to access class properties.
The reason why you won't see them in the debugger is that in the transpiled code this is assigned to _this.
You will see a line
var _this = this;
and for the rest of the lambda _this is used. That's why the debugger doesn't know any this. variables inside lambdas.
Try WebStorm for example. That IDE comes with a debugger that is aware of that issue and compensates for it automatically. However, it works with chrome only, as it is dependent on a chrome add-on.