I am trying to put an Angular 6 CRUD together. My addCoins method seems to be adding the record twice.
addCoin(name, price) {
const obj = {
name: name,
price: price
};
const uri = 'http://localhost/ng6crud/api/post-coins/' + name + '/' + price;
this
.http
.post(uri, obj)
.subscribe(res =>
console.log('Done'));
}
I have created a simple PHP api that sits in the ng6crud directory. The following is the code for the api/post-coins/ - If I use postman to post to the API, then it only inserts the data once.
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
$path = ltrim($_SERVER['REQUEST_URI'], '/'); // Trim leading slash(es)
$elements = explode('/', $path); // Split path on slashes
global $name, $price;
if(!empty($elements[3]))
{
$name = $elements[3];
}
if(!empty($elements[4]))
{
$price = $elements[4];
}
global $server;
$server = "localhost";
global $user;
$user = "someU";
global $pwd;
// $pwd = "someP"; // production
$pwd = "someP"; // local
global $db;
$db = "someDb";
//open connection to mysql db
$connection = mysqli_connect($server,$user,$pwd,$db) or die("Error " . mysqli_error($connection));
//fetch table rows from mysql db
$sql = "INSERT into coins (name, price) VALUES('" . $name . "','" . $price . "')";
// echo $sql;
// die();
if ($connection->query($sql) === TRUE) {
// echo "Record updated successfully";
} else {
// echo "Error updating record: " . $connection->error;
}
$connection->close();
?>
The combination of an .htaccess file and the "" tag in the httpd-vhosts.conf file allows the api/post-coins/ to accept two parameters for "name" and "price" to be included in the sql insert statement - for example api/post-coins/rupple/1.00 would insert a row into the db.
The following is the .htaccess file:
IndexIgnore * # prevent directory listing
Order deny,allow
Allow from *
# ------------------------------------------
# Rewrite so that php extentions are not shown
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php%{REQUEST_URI} [QSA,L]
The following is the Location tag within the "" tag in the httpd-vhosts.conf file:
<Location /post-coins>
ForceType appllication/x-http-php
</Location>
Once more, if I use postman to post to api/post-coins/rupple/1.00 then only one entry will be in the db. When using the service within Angular 6, it is inserting the data twice. I have tried removing the .subscribe, but then nothing is inserted and I have tried to remove the two parameters at the end of the URL, but that results is two empty entries.
Thanks in advance
To answer #Vikas question as to how I implement, the following is the create.component.html:
<div class="panel panel-primary">
<div class="panel-heading">
{{ title }}
</div>
<div class="panel-body">
<form [formGroup]="angForm" novalidate>
<div class="form-group">
<label class="col-md-4">Coin Name</label>
<input type="text" class="form-control" formControlName="name" #name />
</div>
<div *ngIf="angForm.controls['name'].invalid && (angForm.controls['name'].dirty || angForm.controls['name'].touched)" class="alert alert-danger">
<div *ngIf="angForm.controls['name'].errors.required">
Name is required.
</div>
</div>
<div class="form-group">
<label class="col-md-4">Coin Price</label>
<input type="text" class="form-control" formControlName="price" #price/>
</div>
<div *ngIf="angForm.controls['price'].invalid && (angForm.controls['price'].dirty || angForm.controls['price'].touched)" class="alert alert-danger">
<div *ngIf="angForm.controls['price'].errors.required">
Price is required.
</div>
</div>
<div class="form-group">
<button (click)="addCoin(name.value, price.value)" [disabled]="angForm.pristine || angForm.invalid" class="btn btn-primary">Add</button>
</div>
</form>
</div>
</div>
The creat.component.ts:
import { Component, OnInit } from '#angular/core';
import { CoinService } from '../../service/coin.service';
import { FormGroup, FormBuilder, Validators } from '#angular/forms';
#Component({
selector: 'app-create',
templateUrl: './create.component.html',
styleUrls: ['./create.component.css']
})
export class CreateComponent implements OnInit {
title = 'Add Coin';
angForm: FormGroup;
constructor(private coinservice: CoinService, private fb: FormBuilder) {
this.createForm();
}
createForm() {
this.angForm = this.fb.group({
name: ['', Validators.required ],
price: ['', Validators.required ]
});
}
addCoin(name, price) {
this.coinservice.addCoin(name, price);
}
ngOnInit() {
}
}
And the coin.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable()
export class CoinService {
result: any;
constructor(private http: HttpClient) {}
addCoin(name, price) {
const obj = {
name: name,
price: price
};
const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;
this
.http
.post(uri, obj)
.subscribe(res =>
console.log('Done'));
}
getCoins() {
const uri = 'http://localhost/ng5crud/api/get-coins/';
return this
.http
.get(uri);
}
editCoin(id) {
const uri = 'http://localhost/ng5crud/api/get-coins-id/' + id;
return this
.http
.get(uri);
}
updateCoin(name, price, id) {
const uri = 'http://localhost/ng5crud/api/put-coins/' + id;
const obj = {
name: name,
price: price
};
this
.http
.post(uri, obj)
.subscribe(res => console.log('Done'));
}
deleteCoin(id) {
const uri = 'http://localhost/ng5crud/api/delete-coins/' + id;
return this
.http
.get(uri);
}
}
And the routerConfig.ts
import { Routes } from '#angular/router';
import { CreateComponent } from './components/create/create.component';
import { EditComponent } from './components/edit/edit.component';
import { IndexComponent } from './components/index/index.component';
import { DeleteComponent } from './components/delete/delete.component';
export const appRoutes: Routes = [
{ path: 'create',
component: CreateComponent
},
{
path: 'edit/:id',
component: EditComponent
},
{ path: 'index',
component: IndexComponent
},
{ path: 'delete/:id',
component: DeleteComponent
}
];
#Debojyoti, I just saw your response. I ended up creating the following, which returned nothing, but I took a look in network panel - see screen shot below:
import { HttpErrorResponse } from '#angular/common/http';
import { throwError } from 'rxjs';
import { catchError} from 'rxjs/operators';
addCoin(name, price) {
const obj = {
name: name,
price: price
};
const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;
this
.http
.post(uri, obj)
.pipe(
catchError(this.handleError) // then handle the error
)
.subscribe(res =>
console.log('Done'));
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
// return an observable with a user-facing error message
return throwError(
'Something happened; please try again later.');
};
I figured it out and I thank each of you for helping me to step through it over and over again.
Since my PHP API is, for all intensive purposes a "GET":
const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;
Then calling a "POST" function would fire off the API twice - see attached screen shot below:
const obj = {
name: name,
price: price
};
const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;
this
.http
.post(uri, obj)
So, I changed it to a "GET" function and it works perfectly, with only one entry
addCoin(name, price) {
const obj = {
name: name,
price: price
};
const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;
this
.http
.get(uri)
.pipe(
catchError(this.handleError), // then handle the error
map(res => {
console.log(res);
})
)
.subscribe(res =>
console.log('Done'));
}
Through this journey, I discovered from (another stackoverflow post - see #nodirabegimxonoyim 's answer), that map is imported differently in Angular 6 and used differently within the .get method
Instead of importing with
import 'rxjs/add/operator/map';
You use the following:
import { map } from 'rxjs/operators';
Instead of .get().map()
this
.http
.get(uri)
.map(res => {console.log(res)});
You use map, within .pipe
this
.http
.get(uri)
.pipe(
catchError(this.handleError), // then handle the error
map(res => {
console.log(res);
})
)
All together, the following is my new working coin.service.ts:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { HttpErrorResponse } from '#angular/common/http';
import { throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { map } from 'rxjs/operators';
#Injectable()
export class CoinService {
constructor(private http: HttpClient) {}
addCoin(name, price) {
const obj = {
name: name,
price: price
};
const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;
this
.http
.get(uri)
.pipe(
catchError(this.handleError), // then handle the error
map(res => {
console.log(res);
})
)
.subscribe(res =>
console.log('Done'));
}
getCoins() {
const uri = 'http://localhost/ng5crud/api/get-coins/';
return this
.http
.get(uri)
.pipe(
catchError(this.handleError), // then handle the error
map(res => {
console.log(res);
})
);
}
editCoin(id) {
const uri = 'http://localhost/ng5crud/api/get-coins-id/' + id;
return this
.http
.get(uri)
.pipe(
catchError(this.handleError), // then handle the error
map(res => {
console.log(res);
})
);
}
updateCoin(name, price, id) {
const uri = 'http://localhost/ng5crud/api/put-coins/' + id;
const obj = {
name: name,
price: price
};
this
.http
.post(uri, id)
.pipe(
catchError(this.handleError), // then handle the error
map(res => {
console.log(res);
})
)
.subscribe(res => console.log('Done'));
}
deleteCoin(id) {
const uri = 'http://localhost/ng5crud/api/delete-coins/' + id;
return this
.http
.get(uri)
.pipe(
catchError(this.handleError), // then handle the error
map(res => {
console.log(res);
})
);
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
// return an observable with a user-facing error message
return throwError(
'Something happened; please try again later.');
}
}
Seriously, thank you for all your help. This takes me back to the early nineties, when programmers were nice and we would help each other.
It looks like the PHP application and Angular application are running on a separate combination of protocol (http/https), domain, and port. I see the CORS headers have been added in the PHP code.
This leads me to believe 2 requests are being made, one to see if the request is allowed according to CORS (an OPTIONS) request and the normal POST request. Hence, the record being inserted twice. You could detect the request method and return the CORS headers and set the response body to nothing as appropriate on the CORS OPTIONS request and do an insert on a POST request similar to the following (not tested).
<?php
if ($_SERVER['method'] === 'OPTIONS') {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
header("HTTP/1.1 200 OK");
exit;
}
if ($_SERVER['method'] === 'POST') {
header("HTTP/1.1 200 OK");
$path = ltrim($_SERVER['REQUEST_URI'], '/'); // Trim leading slash(es)
$elements = explode('/', $path); // Split path on slashes
global $name, $price;
if (!empty($elements[3])) {
$name = $elements[3];
}
if (!empty($elements[4])) {
$price = $elements[4];
}
global $server;
$server = "localhost";
global $user;
$user = "someU";
global $pwd;
// $pwd = "someP"; // production
$pwd = "someP"; // local
global $db;
$db = "someDb";
//open connection to mysql db
$connection = mysqli_connect($server, $user, $pwd, $db) or die("Error " . mysqli_error($connection));
//fetch table rows from mysql db
$sql = "INSERT into coins (name, price) VALUES('" . $name . "','" . $price . "')";
// echo $sql;
// die();
if ($connection->query($sql) === true) {
// echo "Record updated successfully";
} else {
// echo "Error updating record: " . $connection->error;
}
$connection->close();
exit;
}
header("HTTP/1.1 404 Not Found");
exit;
?>
Make php not to accept the first pre flight request (OPTIONS)
Just modify your php code like
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
if ($_SERVER['REQUEST_METHOD'] != "OPTIONS") {
$path = ltrim($_SERVER['REQUEST_URI'], '/'); // Trim leading slash(es)
$elements = explode('/', $path); // Split path on slashes
global $name, $price;
if (!empty($elements[3])) {
$name = $elements[3];
}
if (!empty($elements[4])) {
$price = $elements[4];
}
global $server;
$server = "localhost";
global $user;
$user = "someU";
global $pwd;
// $pwd = "someP"; // production
$pwd = "someP"; // local
global $db;
$db = "someDb";
//open connection to mysql db
$connection = mysqli_connect($server, $user, $pwd, $db) or die("Error " . mysqli_error($connection));
//fetch table rows from mysql db
$sql = "INSERT into coins (name, price) VALUES('" . $name . "','" . $price . "')";
// echo $sql;
// die();
if ($connection->query($sql) === TRUE) {
// echo "Record updated successfully";
} else {
// echo "Error updating record: " . $connection->error;
}
}
$connection->close();
?>
Related
I'm trying to create an app through NativeScript and Angular which will manage the working hours of the employees for a company.
So, I have to set up a login page and there's my problem: I linked a function on the tap of the LOGIN button and, after clicking on it, I send username and password to a service where I'm trying to connect to and end-point (mypath/api/auth.php).
In this php file I set up the DB connection and a SELECT query which receive username and password as a $_POST function. But, now, when I tap on my LOGIN button I got an alert with [Object Object] even if the credentials are right or wrong.
I'm a beginner in both NativeScript and Angular.
My PHP user verification function:
$username = $_POST["username"];
$password = $_POST["password"];
$conn = getDB();
$hash_pwd = hash('sha256', $password);
$stmt = $conn->prepare("SELECT * FROM dipendenti WHERE cod_fiscale=:username AND password=:password");
$stmt->bindParam("username", $username,PDO::PARAM_STR) ;
$stmt->bindParam("password", $hash_pwd,PDO::PARAM_STR) ;
$stmt->execute();
$count=$stmt->rowCount();
$data=$stmt->fetch(PDO::FETCH_OBJ);
closeDB($conn);
return json_encode($data);
My user.service.ts file:
import { Injectable } from "#angular/core";
import { HttpClient, HttpHeaders, HttpResponse } from "#angular/common/http";
import { Observable, throwError } from "rxjs";
import { catchError, map, tap } from "rxjs/operators";
import { Auth } from "./auth.model";
import { Config } from "../config";
#Injectable()
export class AuthService {
constructor(private http: HttpClient) { }
login( user: Auth) {
if(!user.codFiscale || !user.password) {
return throwError("Devi inserire sia codice fiscale sia la tua password per accedere");
}
return this.http.post(Config.apiUrl + 'api/auth.php',
JSON.stringify({
username: user.codFiscale,
password: user.password
}),
{
headers: this.getCommonHeaders()
}).pipe(
map(response => response),
catchError(this.handleErrors)
);
}
getCommonHeaders() {
return {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
}
}
handleErrors(error: Response) {
console.log(JSON.stringify(error));
return throwError(error);
}
}
My function triggered on the button tap:
submitLogin() {
if(this.isLoggingIn) {
this.authService.login(this.user).subscribe(
() => {
this.router.navigate(["/home"]);
},
(exception) => {
if(exception.error && exception.error.description) {
alert(exception.error.description);
} else {
alert(exception.error);
}
}
);
}
}
Is there something I have forgotten?
i do it in nativescript-vue, maybe you need to adjust for angular.
I use axios plugin for that, it works for ns-angular too, i just don't know how to config it on angular... but the code is this:
async submitLogin() {
const data = {
email: this.user.email,
password: this.user.password
};
try {
const res = (await api.post(this.getApiUrl+"/app/services/login.php", data)).data;
if (res.code === 200){
//handle login success
}
else if (res.code === 500){
//handle login fail
}
}
catch (e) {
console.error("Connection error: ", e);
}
},
where api.post is:
post(url, request, config) {
return axios.post(url, request, config)
.then((response) => Promise.resolve(response))
.catch((error) => Promise.reject(error));
},
Edit: The res.code is a custom response that i send in the response, it's not default!
I want to delete my item using 'srno' in my angular project. I have passed the 'srno' to the URL but it shows some error.
I checked my PHP code using postman, It is successfully worked.
I can't recognize my .ts file syntax error.
Error :
HttpErrorResponse {headers: HttpHeaders, status: 200, statusText: "OK", url: "http://localhost/angular_crud/delete.php?srno=srno", ok: false, …}
delete.component.ts
import { Component, OnInit } from '#angular/core';
import { FormControl } from '#angular/forms';
import { HttpClient, HttpParams } from '#angular/common/http';
import { ActivatedRoute } from '#angular/router';
interface Delete{
srno: String;
}
#Component({
selector: 'app-delete',
templateUrl: './delete.component.html',
styleUrls: ['./delete.component.css']
})
export class DeleteComponent implements OnInit {
delete: Delete[] = [];
srno : String;
myControl1 = new FormControl();
constructor(private http: HttpClient, public route: ActivatedRoute) { }
ngOnInit() {
}
personDelete(){
this.srno = this.myControl1.value;
var url = "http://localhost/angular_crud/delete.php?srno=srno";
this.http.get<Delete[]>(url).subscribe(data => {
this.delete = data;
console.log(data);
})
}
}
This is the delete.component.html
<h1 style="text-align: center">Adding Items here!</h1>
<div>
<p>
<mat-form-field appearance="outline" class="form_field">
<mat-label>Serial Number</mat-label>
<input [formControl]="myControl1" matInput placeholder="Enter the Serial number">
<mat-icon matSuffix>sentiment_very_satisfied</mat-icon>
<mat-hint>ie : 787</mat-hint>
</mat-form-field>
</p>
</div>
<button (click)="personDelete()" mat-raised-button color="warn" class="btn">Delete</button>
This is the delete.php
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET,POST,DELETE');
header("Access-Control-Allow-Header: H-Requested-With");
$con = mysqli_connect("localhost","root", "", "savedata");
$srno = $_GET["srno"];
if($con->connect_error){
die("Connection failed: " . $con->connect_error);
}
$sql = "DELETE FROM savedata WHERE srno='$srno'";
if($con->query($sql) === TRUE){
echo "Record delete successfully";
}
else{
echo "Error deleting record: ". $con->error;
}
$con->close();
?>
Your API doesn't return JSON. Try
this.http
.get(url, {responseType: 'text'})
.subscribe(data => {
console.log(data);
});
I am trying to delete data from the DB server. How do I pass a specific user id into an HTTP delete request so that way I can delete only one user and not all user data? I am using core PHP DB and Ionic 3.
Below is my code:
Home.html
<ion-content padding>
<ion-list>
<ion-item *ngFor="let user of (users | async)?.users" (click)="viewItem(user._id)">
<ion-avatar item-left>
<img src="assets/imgs/logo.png">
</ion-avatar>
<h1>{{user.id}}</h1>
<h2>{{user.name}}</h2>
<p>{{user.bday}}</p>
<ion-icon name='trash' (click)="deleteitem(user._id)" item-end color="secondary"></ion-icon>
</ion-item>
</ion-list>
</ion-content>
home.ts
deleteitem(id: number){
let users = {
userId: id
};
this.restProvider.deleteItem(users)
.subscribe(data => {
this.items = data;
}, err => {
console.error(err);
});
}
provider.ts
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { Headers, RequestOptions } from '#angular/http';
.
.
baseUrl = 'http://url/project_folder';
.
.
deleteItem(user) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return new Promise((resolve, reject) => {
this.http.delete(this.baseUrl+'/delete_info.php'+'/?id=' + '{user.userId}')
.subscribe(res => {
resolve(res);
}, (err) => {
reject(err);
});
});
}
delete.php
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
$id=$_GET['id'];
$servername = "servername";
$username = "username";
$password = "password";
$database = "database";
// Create connection
$conn = new mysqli($servername, $username, $password, $database);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql="delete from tbl_userinfo where id=$id";
if ($conn->query($sql))
{
echo "delete data";
}
else
{
echo "Try again";
}
?>
If i enter like this working:
http://url/project_folder/delete.php/?id=6
When i click on delete button, showing error like this:
core.js:1449 ERROR Error: Uncaught (in promise): [object Object]
at c (polyfills.js:3)
at polyfills.js:3
at SafeSubscriber._error (rest.ts:56)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:242)
at SafeSubscriber.error (Subscriber.js:201)
at Subscriber._error (Subscriber.js:132)
at Subscriber.error (Subscriber.js:106)
at MapSubscriber.Subscriber._error (Subscriber.js:132)
at MapSubscriber.Subscriber.error (Subscriber.js:106)
at FilterSubscriber.Subscriber._error (Subscriber.js:132)
Network Response:
http://url/project_folder/delete_info.php/?id={user.userId}
Attach click to icon not a good idea
provider.ts: ...id=' + '{user.userId}' should be ...id=' + user.userId.
provider.ts: if you want to return Promise, should be return this.http.delete().toPromise(), and you must use 'then' not subscribe at home.ts
provider.ts: if you not want to return promise, return this.http.delete() is ok, then use subscribe at home.ts
php must return json data.
example below:
<ion-button (click)="deleteitem(user)">
<ion-icon name='trash' slot="icon-only"></ion-icon>
</ion-button>
function deleteitem(user) {
this.restProvider.deleteitem(user._id).subscribe(data => {
for(let i = 0, l = this.users.length; i < l; i++)
if (this.users[i]._id == user._id)
this.users.splice(i, 1);
}, err => {
console.error(err);
});
}
function deleteitem(userId) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.delete(`${this.baseUrl}/delete_info.php?id=${userId}`);
}
The form has text input and file-input. I studied the tutorial from here.
This is my add.component.ts file:-
import { AdminPage } from '../../../_models/admin.page.model';
import { AdminPageService } from '../../../_admin_service/admin.page';
import { ImageUploadService } from '../../../_common_service/image.upload';
export class AddComponent implements OnInit, AfterViewInit {
.............
.............
adminPageModel = new AdminPage('', '', '', '','');
constructor(private route: ActivatedRoute,
private router: Router,
private _adminPage: AdminPageService,
private _imageUpload: ImageUploadService,
fb: FormBuilder,
private _flashMessagesService: FlashMessagesService) {
this.addPageFormGroup = fb.group({
'title' : [null, Validators.compose([Validators.required])],
'meta_keyword': [null, Validators.required],
'meta_description': [null, Validators.required],
'image':[],
'desc': [null, Validators.required]
});
}
formImageUpload(event){
this._imageUpload.onFileChange(event,this.addPageFormGroup);
}
submitAddPage(value:any){
this.addPageFormGroup.get('desc').setValue($('.Editor-editor').html());
const adminPageModule = this._imageUpload.prepareSave(this.addPageFormGroup);
this._adminPage.postAdminPageAdd(adminPageModule).subscribe(
data => {
this.responseStatus = data;
if(this.responseStatus.status == 1)
{
this._flashMessagesService.show(this.responseStatus.message, { cssClass: 'alert-success', timeout: 2000 });
}
else
{
this._flashMessagesService.show(this.responseStatus.message, { cssClass: 'alert-danger', timeout: 2000 });
}
},
err => {
console.log(err)
},
() => {}
);
this.status = true;
}
}
This is the image.upload.ts service file, where we are setting the formdata from the form:-
#Injectable()
export class ImageUploadService {
constructor() {}
onFileChange(event, formHasImage:any) {
if(event.target.files.length > 0) {
let file = event.target.files[0];
formHasImage.get('image').setValue(file);
}
}
prepareSave(formHasImage): any {
let input = new FormData();
input.append('image', formHasImage.get('image').value);
input.append('title', formHasImage.get('title').value);
input.append('desc', formHasImage.get('desc').value);
input.append('meta_keyword', formHasImage.get('meta_keyword').value);
input.append('meta_description', formHasImage.get('meta_description').value);
console.log(input);
return input;
}
}
This is the admin.page.ts service file where we are hitting the API. This is made by referring to this answer here.
#Injectable()
export class AdminPageService {
http : Http;
actionUrl : string;
admin_page_add_url: string;
postAdminPageAddData: AdminPage;
adminPageAddResponse:Object= [];
constructor(public _http: Http) {
this.http = _http;
this.admin_page_add_url = 'http://localhost/angproject/phpscript/adminpage2.php';
}
// The form Data is being sent as parameter
postAdminPageAdd(postAdminPageAddFormData: any) {
let headers = new Headers();
headers.append('enctype', 'multipart/form-data');
headers.append('Accept', 'application/json');
this.actionUrl = this.admin_page_add_url;
return this.http.post(this.actionUrl,
{ postAdminPageAddFormData },
{ headers: headers })
.map(res => res.json()).share();
}
}
This is the server side php file where we are sending the data. This is made on the accepted answer here:-
<?php
error_reporting(E_ALL);
header("Access-Control-Allow-Origin: http://localhost:4200");
header("Access-Control-Allow-Headers: Content-Type, enctype");
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
header('Content-Type: application/json; charset=utf-8');
header('enctype: multipart/form-data');
include('connection.php');
$error = array();
if(isset($_FILES['image']))
{
$image = 'Image Exists';
}
else
{
$error[] = "Image was not entered";
$image = '';
}
if(isset($_POST['title']) && !empty($_POST['title']))
$title = $_POST['title'];
else
$error[] = "Title was not entered";
if(empty($error))
{
$response['status'] = 1;
$response['message'] = $image;
$response['error'] = $conn->error;
}
else
{
$response['status'] = 0;
$response['message'] = "Parameter missing";
$response['error'] = $error;
}
$respond = json_encode($response);
echo $respond;
exit;
?>
My issue is, I am always getting this json response:-
{
"status": 0,
"message": "Parameter missing",
"error": [
"Image was not entered",
"Title was not entered"
]
}
It seems like the formdata aren't being sent to the server end. What am I doing wrong here? Mind it, I have other process too, to submit the form. But in that case, I can send data to server successfully by not using formdata and hence, I can't implement file-upload in that method.
Note: When I do console.log(input), I get this:-
You have two problems with your AdminPageService's postAdminPageAdd method.
First, Headers.append() does not mutate the Headers object, it returns a new Headers object with the original headers and the new one. So you need to do something like:
let headers = new Headers();
headers = headers.append('enctype', 'multipart/form-data');
headers = headers.append('Accept', 'application/json');
Second, the FormData object in the post should not be surrounded with curly brackets - it should work if you do:
return this.http.post(
this.actionUrl,
postAdminPageAddFormData,
{ headers: headers }
).map(res => res.json()).share();
Try appending file directly to FormData object.
#Injectable()
export class ImageUploadService {
file: File;
constructor() {}
onFileChange(event, formHasImage:any) {
if(event.target.files.length > 0) {
file = event.target.files[0];
}
}
prepareSave(formHasImage): any {
let input = new FormData();
input.append('image', this.file);
input.append('title', formHasImage.get('title').value);
input.append('desc', formHasImage.get('desc').value);
input.append('meta_keyword', formHasImage.get('meta_keyword').value);
input.append('meta_description', formHasImage.get('meta_description').value);
console.log(input);
return input;
}
}
Every time I clicked on submit button in my login page, the message it return is [Object Object]. I am trying to get users login details from the database using http request but it failed every time I run it.
I have applied to it different approach but I am still getting the same error.
I am still new to ionic and how it works, all I am doing is following some tutorials online which are not that much detailed.
My main issue is getting users details from mysql, accessing it and validate all the imputs.
Below are my Login form details:
Login.html
<ion-content class="login-content" padding>
<ion-row class="logo-row">
<ion-col></ion-col>
<ion-col >
<img src="../assets/imgs/logo.png" class="img-responsive " id="img2">
</ion-col>
<ion-col></ion-col>
</ion-row>
<div class="login-box">
<form (ngSubmit)="login()" #registerForm="ngForm">
<ion-row>
<ion-col>
<ion-list inset>
<ion-item>
<ion-input type="text" placeholder="Email" name="email" [(ngModel)]="data.email" required></ion-input>
</ion-item>
<ion-item>
<ion-input type="password" placeholder="Password" name="password" [(ngModel)]="data.password" required></ion-input>
</ion-item>
</ion-list>
</ion-col>
</ion-row>
<ion-row>
<ion-col class="signup-col">
<div align="center">
<button ion-button class="submit-btn" full type="submit" [disabled]="!registerForm.form.valid">Login</button>
<span class="tell">- or -</span>
<button ion-button class="register-btn" type="button" block clear (click)="createAccount()">Create New Account</button>
</div>
</ion-col>
</ion-row>
</form>
</div>
</ion-content>
Login.ts
import { Component } from '#angular/core';
import { NavController, AlertController, LoadingController, Loading, IonicPage } from 'ionic-angular';
import { Myprovider } from '../../providers/myprovider/myprovider';
import { Storage } from '#ionic/storage';
#IonicPage()
#Component({
selector: 'page-login',
templateUrl: 'login.html',
providers: [Myprovider]
})
export class LoginPage {
loading: Loading;
data: any;
public local : Storage;
constructor(private nav: NavController, private auth: Myprovider, private alertCtrl: AlertController, private loadingCtrl: LoadingController, private service: Myprovider)
{
this.data = {};
this.data.email = "";
this.data.password = "";
//this.local = new Storage();
}
ionViewDidLoad() {
this.createLoader();
}
createLoader(message: string = "Please wait...") { // Optional Parameter
this.loading = this.loadingCtrl.create({
content: message
});
}
public createAccount() {
this.nav.push('RegisterPage');
}
public login() {
this.showLoading()
let email = this.data.email;
let password = this.data.password;
let data = JSON.stringify({email, password});
this.service.login(data);
this.auth.login(this.data).subscribe(allowed => {
if (allowed) {
this.nav.setRoot('DashboardPage');
} else {
this.showError("Access Denied");
}
},
error => {
this.showError(error);
});
}
showLoading() {
this.loading = this.loadingCtrl.create({
content: 'Please wait...',
dismissOnPageChange: true
});
this.loading.present();
}
showError(text) {
this.loading.dismiss();
let alert = this.alertCtrl.create({
title: 'Fail',
subTitle: text,
buttons: ['OK']
});
//alert.present(prompt);
alert.present();
}
}
MyProvider.ts
import { HttpClient } from '#angular/common/http';
import { Http } from '#angular/http';
import { Storage } from '#ionic/storage';
import { Injectable } from '#angular/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
export class User {
name: string;
email: string;
}
#Injectable()
export class Myprovider {
public local : Storage;
mydata: any;
constructor(private http: HttpClient) {
this.http = http;
//this.local = new Storage()
}
currentUser: User;
public login(credentials) {
let link = "http://localhost:90/mySchool/api/securelogin.php";
return this.http.post(link, credentials)
.map(credentials => {
this.mydata = credentials;
console.log("data")
}, error =>{
console.log(error)
})
}
public register(credentials) {
if (credentials.email === null || credentials.password === null) {
return Observable.throw("Please insert credentials");
} else {
// At this point store the credentials to your backend!
return Observable.create(observer => {
observer.next(true);
observer.complete();
});
}
}
public getUserInfo() : User {
return this.currentUser;
}
public logout() {
return Observable.create(observer => {
this.currentUser = null;
observer.next(true);
observer.complete();
});
}
}
Lastly, the php file
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
$conn = new mysqli("localhost", "root", "", "cihmeeting");
//http://stackoverflow.com/questions/18382740/cors-not-working-php
if (isset($_SERVER['HTTP_ORIGIN'])) {
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400'); // cache for 1 day
}
// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
exit(0);
}
//http://stackoverflow.com/questions/15485354/angular-http-post-to-php-and-undefined
$postdata = file_get_contents("php://input");
if (isset($postdata)) {
$request = json_decode($postdata);
$email = $request->email;
$password = $request->password;
$data = array();
if ($password != "" && $email != "") {
$sel="SELECT * FROM users WHERE email='$email' AND password='$password'";
$result=$conn->query($sel);
$numrow=$result->num_rows;
if($numrow == 1){
include 'http://localhost:90/mySchool/api/tokengenerate.php';
$token = generateRandomString();
$update = "update users set token='$token' WHERE email='$email' AND password='$password'";
$qr = $conn->query($update);
if($qr){
$st = "SELECT email, token FROM users WHERE email='$email' AND password='$password'";
$query = $conn->query($st);
while($row = $query->fetch_assoc()){
$data[] = array(
"email" => $row['email'],
"token" => $row['token']
);
echo json_encode($data);
}
}
}
}
else {
header('HTTP/1.1 401 Unauthorized', true, 401);
}
}
else {
echo "Not called properly with email parameter!";
}
?>