Hello i have a problem returning data on html file using an Ionic app. I use an auth-service.ts provider to connect to database and the results are returning fine on console-> network-> XHR (friendsNewsFeed)
On ionic serve i am getting error
trying to diff [object Object] only arrays and iterables are allowed
https://forum.ionicframework.com/t/problem-with-ngfor/121590
home.ts
import { Component, ViewChild } from "#angular/core";
import { NavController, App, AlertController } from "ionic-angular";
import { AuthService } from "../../providers/auth-service";
import { Common } from "../../providers/common";
import { Camera, CameraOptions } from "#ionic-native/camera";
#Component({ selector: "page-home", templateUrl: "home.html" })
export class HomePage {
public photos: any;
public base64Image: string;
public fileImage: string;
public userDetails: any;
public resposeData: any;
public dataSet: any;
public noRecords: boolean;
userPostData = {
uid: "",
token: "",
created: "",
message: ""
};
constructor(
public authService: AuthService
) {
const data = JSON.parse(localStorage.getItem("userData"));
this.userDetails = data.userData;
this.userPostData.uid = this.userDetails.uid;
this.userPostData.token = this.userDetails.token;
this.userPostData.created = "";
this.noRecords = false
this.getFeed();
}
ngOnInit() {
this.dataSet = [];
}
getFeed() {
this.common.presentLoading();
this.authService.postData(this.userPostData, "userNewsFeed").then(
result => {
this.resposeData = result;
if (this.resposeData) {
this.common.closeLoading();
this.dataSet = this.resposeData;
console.log(this.dataSet);
} else {
console.log("No access");
}
},
err => {
//Connection failed message
}
);
}
home.html
<ion-card *ngFor="let item of dataSet; let msgIndex = index">
<ion-item>
<ion-card-content>
<p [innerHTML]="item.message | linky"></p>
</ion-card-content>
</ion-item>
</ion-card>
auth-service.ts
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import 'rxjs/add/operator/map';
let apiUrl = "http://localhost/PHP-Slim-Restful1/api/";
//let apiUrl = 'https://api.thewallscript.com/restful/';
/*
Generated class for the AuthService provider.
See https://angular.io/docs/ts/latest/guide/dependency-injection.html
for more info on providers and Angular 2 DI.
*/
#Injectable()
export class AuthService {
constructor(public http: Http) {
console.log('Hello AuthService Provider');
}
postData(credentials, type){
return new Promise((resolve, reject) =>{
let headers = new Headers();
this.http.post(apiUrl+type, JSON.stringify(credentials), {headers: headers}).
subscribe(res =>{
resolve(res.json());
}, (err) =>{
reject(err);
});
});
}
}
any hint?
Related
Client given below Ajax Post call, when i will open below PHP api file in browser then the static data is inserting correctly, now i am trying using Angular, but I am not able to understand how to convert this below call into component.ts and service
<?php
//creating payload parameters:
$classTitle = 'Demo Class on 3rd April, 2020';
$classInfo = 'This is a demo class scheduled to understand API';
$classDateTime = '2020-11-12 11:30 AM';
$timezone = 'Asia/Kolkata';
$classDuration = 15;
$classRecording = 'yes';
$classAutoStart = false;
$recordingAutoStart = false;
$classVideoRes = 720;
/*xyz.com*/
$apiKey = '12345';
$secretKey = '12345';
// Create token header as a JSON string
$header = json_encode(['alg' => 'HS256','typ' => 'JWT']); // ensure to place first alg part and next typ part
// Create token payload as a JSON string
$payload = json_encode(['classTitle' => $classTitle ,'classInfo' => $classInfo ,'classDateTime' => $classDateTime ,'timezone' => $timezone ,'classDuration' => $classDuration ,'classRecording' => $classRecording ,'classAutoStart' => $classAutoStart ,'recordingAutoStart' => $recordingAutoStart ,'classVideoRes' => $classVideoRes ,'apiKey' => $apiKey]);
// Encode Header to Base64Url String
$base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
// Encode Payload to Base64Url String
$base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload));
// Create Signature Hash
$signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, $secretKey , true);
// Encode Signature to Base64Url String
$base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));
// creating JWT token variable
$jwt_token = $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature;
// creating authorization varibale
$authorization = 'Bearer '.$jwt_token;
?>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript">
$.ajax
({
type: "POST",
url: 'https://xyz/client/schedule',
contentType: 'application/json',
data: JSON.stringify({
"apiKey": "12345"
}),
dataType : 'json',
headers: {
'authorization': '<?php echo $authorization; ?>'
},
success: function(retval)
{
// alert(retval);
console.log(retval);
// var success = retval.success;
}
});
</script>
I have updated Question and added after two replied answer
Below is my model class
export class Schedule1 {
classTitle: string;
classInfo: string;
classDateTime: string;
timezone: string;
classDuration: number;
classRecording:string;
classAutoStart: boolean;
recordingAutoStart: boolean;
classVideoRes: number;
constructor() {
}
}
Below is component.ts on button click passing static values
import { Schedule1 } from '../Models/Schedule1.model'
Schedule1: Schedule1 = new Schedule1();
addSchedule(scheduleForm: NgForm): void {
//static data parameter passing
this.Schedule1.classTitle='hi Class on 3rd April, 2020';
this.Schedule1.classInfo= 'This is a demo class scheduled to understand API';
this.Schedule1.classDateTime= '2020-11-12 11:30 AM';
this.Schedule1.timezone= 'Asia/Kolkata';
this.Schedule1.classDuration= 15;
this.Schedule1.classRecording= 'yes';
this.Schedule1.classAutoStart= false;
this.Schedule1.recordingAutoStart= false;
this.Schedule1.classVideoRes= 720;
//const data = JSON.stringify(this.Schedule1);
const data = {
apiKey: "dcbf187d-bdfe-431b-8f60-fa19bf51cd85",
data: JSON.stringify(this.Schedule1)
}
this.subscription = this.userSvc
.fetchData("https: //xyz.com/client/schedule", data)
.subscribe(
data => {
// Data on Success
console.log("data", data);
},
error => {
console.log("error", error);
}
);
}
Below is service.ts
fetchData(url: string, data: any): Observable<any> {
const headers = {
Authorization: "Bearer "+"1234",
"My-Custom-Header": "foobar",
contentType: "application/json"
};
return this.http.post(url, data, {
headers
});
}
in console getting this error.
Parsing HTTP request is pretty simple in Angular. Below are the steps you need to follow:
Step 1:
import the HttpClientModule in your app module like this:
import { HttpClientModule } from '#angular/common/http';
imports: [ HttpClientModule ]
Step 2:
Create a service for your application where you will store all the HTTP request calls.
NOTE: This part is not necessary as you can do HTTP calls directly in your component but for best practice and good structure this should be followed
So for this step, import HttpClient either in your service (if you have created) or in your component and then do like this below:
import { HttpClient } from '#angular/common/http';
constructor(private http: HttpClient) { }
createExamCategory(data) {
return this.http.post<{ message: string }>(this.url + '/category/create_exam', data);
}
Let me explain the createExamCategory() method.
The parameter data is the value that is coming from your HTML or any source. And this data will be passed in POST request.
The next line is as I am explaining with service I have just returned the call and will subscribe to it in the component.
The <{ message: string }> is the response that I am getting from the API request. If you are not sure what response you are getting you can just keep it as <any> and Angular will decide the type of response.
Then in the post method (this method is coming from HttpClient declared above) we have 2 pass to parameters by default & the third parameter which is HttpHeader is optional. The 2 parameters are:
URL OF the API.
The request body data for the POST request.
So that's all from the calling side now coming to the subscription part:
If you are directly writing the above part in component then continue with .subscribe(). Now for the service part:
Step 1:
Import the service:
import { SampleService } from 'sample.service';
constructor(private service: SampleService) { }
// Do the call where it is required. I am doing in a normal method
httpMethod() {
this.service.createExamCategory(data).subscribe(response => {
console.log(response); // This is the API response
});
}
Interceptor
import { HttpInterceptor, HttpErrorResponse, HttpEvent, HttpRequest, HttpHandler } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { catchError } from 'rxjs/operators';
import { Observable, of } from 'rxjs';
import { Router } from '#angular/router';
import { Service } from 'service.service';
#Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private router: Router, private service: Service) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (sessionStorage.getItem('token')) {
const cloned = req.clone({
headers: req.headers.set('Authorization', 'Bearer ' + sessionStorage.getItem('token'))
});
return next.handle(cloned).pipe(
catchError((err, caught: Observable<HttpEvent<any>>) => {
if (err instanceof HttpErrorResponse && (err.status == 401))
{
this.adminAuthService.clearAuthData();
this.router.navigate(['required route path']);
alert('Session Timeout !! Login Again');
return of(err as any);
}
throw err;
})
);
}
return next.handle(req);
}
}
Here what I have done is while login/authentication I have stored the generated JWT token by the backend service in session and validated if the API url is valid or not.
After doing this in app.module.ts specify the interceptor in the providers like this:
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
]
Hoping this will help you 🙂
create a service like below.
import { Injectable } from "#angular/core";
import { HttpClient } from "#angular/common/http";
import { Observable } from "rxjs";
#Injectable({
providedIn: "root"
})
export class ScheduleDataService {
constructor(private _http: HttpClient) {}
fetchData(url: string, data: any): Observable<any> {
const headers = {
Authorization: "Bearer my-token",
"My-Custom-Header": "foobar",
contentType: "application/json"
};
return this._http.post(url, data, {
headers
});
}
}
then you can call this service in your component like below.
import { Component, OnDestroy, OnInit, VERSION } from "#angular/core";
import { ScheduleDataService } from "./schedule-data.service.ts";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit, OnDestroy {
name = "Angular " + VERSION.major;
private subscription;
constructor(private _scheduleDataService: ScheduleDataService) {}
ngOnInit() {
this.subscription = this._scheduleDataService
.fetchData("https://xyz/client/schedule", {
apiKey: "myapikey"
})
.subscribe(
data => {
// Data on Success
console.log("data", data);
},
error => {
console.log("error", error);
}
);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Let me know if you have any doubt.
You can Create service Like and call in component.
services.ts
import { HttpClient, HttpHeaders } from '#angular/common/http';
#Injectable({
providedIn: "root"
})
export class UserService{
constructor(public http: HttpClient){}
let headers = new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': ''
});
public getData(url: string, data: any): Observable<any> {
return this.http.post(url, data, { headers: headers});
}
}
components.ts
import { Component, OnInit } from '#angular/core';
import { UserService } from './services.ts';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class Components implements OnInit {
constructor(public userService: UserService){}
public ngOnInit(): void {
const data = { apiKey: "myapikey" }
this.userService.getData(url, data).subscribe((res)=>{
code...
})
}
}
I am new to Ionic 3 and mobile development. I am trying to connect a MySQL DB to my Ionic app and a PHP Restful API. I tested the API with Postman and it is working just fine, in order to implement it in Ionic I did the following,
I first made a provider named Authservice:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import 'rxjs/add/operator/map';
let apiUrl = "http://localhost/api/"
/*
Generated class for the AuthServiceProvider provider.
See https://angular.io/guide/dependency-injection for more info on
and Angular DI.
*/
#Injectable()
export class AuthServiceProvider {
constructor(public http: HttpClient) {
console.log('Hello AuthServiceProvider Provider');
}
postData(credentials, type) {
return new Promise((resolve, reject) => {
let headers = new HttpHeaders();
this.http.post(apiUrl + type, JSON.stringify(credentials), { headers: headers })
.subscribe(res => {
resolve(res.json());
}, (err) => {
reject(err);
});
});
}
}
And a Signup page:
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { AuthServiceProvider } from '../../providers/auth-service/auth- service';
/**
* Generated class for the SignupPage page.
*
* See https://ionicframework.com/docs/components/#navigation for more info on
* Ionic pages and navigation.
*/
#IonicPage()
#Component({
selector: 'page-signup',
templateUrl: 'signup.html',
})
export class SignupPage {
responseData: any;
userData = {"username": "","password": "", "name": "","email": ""};
constructor(public navCtrl: NavController, public authServiceProvider: AuthServiceProvider) {
}
signUp() {
this.authServiceProvider.postData(this.userData, "signup").then((result) =>{
this.responseData = result;
console.log(this.responseData);
localStorage.setItem('userData', JSON.stringify(this.responseData));
});
}
goToLogin() {
this.navCtrl.pop();
}
}
When running this I am getting an Uncaught (in promise): [object Object] error as can be seen here.
UPDATE
I am now getting the following error:
Object { headers: {…}, status: 404, statusText: "Not Found", url: "http://localhost/PHP-SLIM-RESTFUL/API/signup", ok: false, name: "HttpErrorResponse", message: "Http failure response for http://localhost/PHP-SLIM-RESTFUL/API/signup: 404 Not Found", error: "<html><head><title>404 Page Not Found</title><style>body{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana,sans-serif;}h1{margin:0;font-size:48px;font-weight:normal;line-height:48px;}strong{display:inline-block;width:65px;}</style></head><body><h1>404 Page Not Found</h1><p>The page you are looking for could not be found. Check the address bar to ensure your URL is spelled correctly. If all else fails, you can visit our home page at the link below.</p>Visit the Home Page</body></html>" } signup.ts:36:6
postData(credentials, type) {
let headers = new HttpHeaders();
return this.http.post(apiUrl + type, JSON.stringify(credentials), { headers: headers });
}
this will return observable on the signup page, just subscribe it.
You can make use of Typescript's async methods to make your life easier
Your postData method in async
AuthServiceProvider:
public async postData(credentials, type): Promise<any> {
let headers = new HttpHeaders();
await this.http.post(apiUrl + type, JSON.stringify(credentials), { headers: headers }).toPromise();
}
Signup page:
public async signUp(): void {
try {
// request successful
this.responseData = await this.authServiceProvider.postData(this.userData, "signup");
console.log(this.responseData);
localStorage.setItem('userData', JSON.stringify(this.responseData));
}
catch(e) {
// some error occured, handle it here..
console.log(e);
}
}
Don't forget to import toPromise operator in AuthServiceProvider
import 'rxjs/add/operator/toPromise';
Try importing HttpModule in app.module.ts;
{import HttpModule } from '#angular/http'
Then add HttpModule to the imports;
imports :
[BrowserModule,
HttpModule,
IonicModule.forRoot(MyApp)
]
I want to get variable from my getData.php file that is in src/assets folder of angular project.
<?php
...
echo json_encode('test');
?>
get-data.service :
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map';
#Injectable()
export class GetDataService {
constructor(private http: Http) {}
getTest(): Observable<any> {
return this.http.get('assets/getData.php')
.map(response => response.json());
}
}
app.component :
import { Component } from '#angular/core';
import { GetDataService } from './services/get-data.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private getDataService: GetDataService) { }
title = 'Run Chart Generator';
data;
getTestTwo() {
this.getDataService.getTest()
.subscribe(data => {
this.data = data;
console.log(this.data)
});
}
}
When I call function getTestTwo I've got:
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
When I change php from echo json_encode('test') to echo 'test' and service from .map(response => response.json()) to .map(response => response) then I've got in console:
Object { _body: "<?php include('simple_html_dom.ph…", status: 200, ok: true, statusText: "OK", headers: Object, type: 2, url: "http://localhost:4200/assets/getDat…" }
How can I retrieve a variable from my php file?
#angular/cli: 1.4.1
#angular/core: 4.3.6
Your PHP file won't work under a NodeJS project.
You need to separate your Angular App from your server logic. Use Nginx or Apache to serve your PHP file, then you will be able to call it in your getTest() function.
I'm building a mobile app to display news feed. In my app, one should be able to post a status.
The status will be sent to PHP server using POST method.
Now my problem is PHP cant read the POST request I sent using angular2.
This is my code:
form.html
<form class="sample-form post-form" [formGroup]="post_form" (ngSubmit)="createStatus()">
<ion-item>
<ion-textarea rows="7" placeholder="What's happening?'" formControlName="status"></ion-textarea>
</ion-item>
<section class="form-section">
<button ion-button block class="form-action-button create-post-button" type="submit" [disabled]="!post_form.valid">Post</button>
</section>
</form>
form.ts
import { Component } from '#angular/core';
import { NavController, AlertController } from 'ionic-angular';
import { Validators, FormGroup, FormControl } from '#angular/forms';
import { Http, Headers } from '#angular/http';
import 'rxjs/add/operator/map';
#Component({
selector: 'form-page',
templateUrl: 'form.html'
})
export class FormLayoutPage {
section: string;
post_form: any;
url: string;
headers: Headers;
constructor(public nav: NavController, public alertCtrl: AlertController, public http: Http) {
this.headers = new Headers();
this.headers.append("Content-Type", "application/x-www-form-urlencoded");
this.section = "post";
this.post_form = new FormGroup({
status: new FormControl('', Validators.required),
});
}
createStatus(){
console.log(this.post_form.value);
this.url = "https://domain.com/mobileREST/poststatus.php";
this.http.post(this.url, this.post_form.value, { headers: this.headers})
.map(res => res.json())
.subscribe(res => {
console.log(res);
},
err => {
console.log(err);
})
}
}
poststatus.php
<?php
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
$status = $_POST["status"];
echo json_encode($status);
?>
Firebug Console:
I cant seem to find the error here. Really appreciate your help
I had the same problem. You can't send the POST params like the javascript object. You have to pass it like URLSearchParams. I've made a function which will do it for you. It will loop through the object and make URLSearchParam and return it as string.
private _buildParams(params: any) {
let urlSearchParams = new URLSearchParams();
for(let key in params){
if(params.hasOwnProperty(key)){
urlSearchParams.append(key, params[key]);
}
}
return urlSearchParams.toString();
}
And then you call http post:
this._http.post(this.url, this._buildParams(params), {headers: this.headers});
To get the posted data just add this line in your php file
// get posted data
$data = json_decode(file_get_contents("php://input"));
I'm looking to check if promise is resolved in ionic 2. Here is my code:
ionViewDidLoad() {
this.loader.present();
this.getCourses();//after resolve to do something
}
public getCourses(){
this.coursesData.LoadData()
.subscribe(courseList=> {
courseList.forEach(course=>{
var newCourse={
id_course:course.id_course ,
key_course:course.key_course,
course_name:course.course_name ,
course_type:course.course_type ,
start:course.start ,
end:course.end ,
point_course:course.point_course ,
day:course.Day,
class:course.class,
lecture_name:course.lecture_name
}
this.coursesA.push(newCourse);
console.log(this.coursesA);
});
this.loader.dismiss();
// return this.coursesA;
},err=>{
console.log(err);
});
}
I have this.getCourses() function, after it is resolved I want to do something else with the data. This is my provider course-data.ts
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
/*
Generated class for the CoursesData provider.
See https://angular.io/docs/ts/latest/guide/dependency-injection.html
for more info on providers and Angular 2 DI.
*/
#Injectable()
export class CoursesData {
public data: any = null;
constructor(public http: Http) {
console.log('Hello CoursesData Provider');
}
LoadData(){
let link = "http://adirzoari.16mb.com/selectCourses.php";
return this.http.get(link)
.map(res => res.json());
}
}
You can do promise chaining.
public getCourses(){
return new Promise(function(resolve, reject){
this.coursesData.LoadData()
.subscribe(courseList=> {
courseList.forEach(course=>{
var newCourse={
id_course:course.id_course ,
key_course:course.key_course,
course_name:course.course_name ,
course_type:course.course_type ,
start:course.start ,
end:course.end ,
point_course:course.point_course ,
day:course.Day,
class:course.class,
lecture_name:course.lecture_name
}
this.coursesA.push(newCourse);
console.log(this.coursesA);
});
this.loader.dismiss();
resolve();
},err=>{
console.log(err);
reject(err);
});
});
}
ionViewDidLoad() {
this.loader.present();
var getCoursesPromise = this.getCourses();
var nextStepPromise = getCoursesPromise.then(function(result){
//do what you want to do after this.getCourses
}).catch(function(reject){
console.log(reject);
});
}
You will have to decided when you want to trigger resolve() to return the promise object.