Angular http client - php

I have a problem with angular, the problem is the following, the method to obtain an http client, does not get any value from an api in php that is listening on the localhost port: 123. The php code would be the follow
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
//Get todos los usuarios
$app=new \Slim\App;
//Get todos los usuarios
$app->get('/api/clientes', function(Request $request,Response $response){
include "../src/db.php";
$query="select * from users";
$result = mysqli_query($con,$query);
if (!$result) {
die("Query fail");
}else {
$row_cate = mysqli_num_rows($result);
if($row_cate == null){
echo "no existen datos en la dbo";
}
else{
$users=array();
$cont=0;
while ($row = mysqli_fetch_array($result)){
$producto[$cont]=array(
"id" => $row['id'],
"name" => $row['name'],
"email" => $row['email']
);
$cont++;
}
echo json_encode($producto);
}
}
});
and the angular client method is as follows.
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { User } from './user.model';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http:HttpClient) { }
get(){
const url="http://localhost:1234/public/api/clientes";
return new Promise(
resolve=>{
this.http.get(url)
.subscribe(
data=>resolve(data)
)
}
);
}
}
I would appreciate your help.

Your code in get() method is invalid. Here is a better code if you want it to return Promise.
get(): Promise<any> {
const url="http://localhost:1234/public/api/clientes";
return this.http.get(url).toPromise();
}
Also, make sure your server responds with the data you expect
If you are just getting started with Angular, then my advice to you is to learn RxJS and use Observables instead of Promises with Angular.

I already managed to solve the error, the truth was a beginner error, the problem was in the api, I had not put the headers that allowed to perform the procedures "get", "post", etc in php

Related

Angular-Slim: CORS when call post

From localhost: 4200 I am trying to make a POST request, to my Slim REST API (3.0 v), which I have hosted on a server.
when I execute the "post" query, the following error appears:
ERROR
This is my code in the api:
<?php
require 'vendor/autoload.php';
use \Slim\App;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
$app = new Slim\App(['settings' => ['displayErrorDetails' => true]]);
//permite el acceso cors.
$app->options('/{routes:.+}', function ($request, $response, $args) {
return $response;
});
$app->add(function ($req, $res, $next) {
$response = $next($req, $res);
return $response
->withHeader('Access-Control-Allow-Origin', '*')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization,token')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS')
->withHeader('access-control-expose-headers', 'token,Authorization');
});
require_once "src/routes/routes.php";
$app->run();
ANGULAR: : auth.service.ts
import { GLOBAL } from './global';
import { Router } from '#angular/router';
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
const httpOptions = {
observe: 'response' as 'response',
};
#Injectable({
providedIn: 'root'
})
export class AuthService {
public url: string;
constructor(
public http: HttpClient,
private router: Router) { this.url = GLOBAL.url; }
login(user) {
return this.http.post(this.url + 'login', user, httpOptions);
};
loggedIn() {
//devuelve true si contiene token o falso
return !!localStorage.getItem('token');
}
registrarse(user) {
return this.http.post(this.url + 'usuario', user, httpOptions)
};
}
ANGULAR: : home.component.ts
import { Empresa } from './../../models/empresa';
import { EmpresaService } from './../../services/empresa.service';
import { AuthService } from './../../services/auth.service';
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
empresa: Empresa;
user = {
'id': '',
'email': ''
}
constructor(
private authService: AuthService,
private empresaService: EmpresaService) { }
ngOnInit() {
this.getEmpresa();
this.postLogin();
}
// This request goes well.
getEmpresa() {
let id = 1;
this.empresaService.getEmpresa(id).subscribe(
result => {
console.log(result)
this.empresa = result['data'];
}
)
}
// This request shows me the error
postLogin() {
let user = {
'email': 'adri',
'password': 'adri'
}
this.authService.login(user).subscribe(
result => {
console.log(result.body)
this.user = result.body['data'];
}
)
}
}
Note*:
when I put the API in localhost, the two requests work very well for me: The getEmpresa () and the postLogin ().
but when I put the api on the server, the postLogin () fails.
Angular by default sends in body requests in Content-Type: application / json.
And it is seen that in a more optimized way in production it must be sent in Content-Type: in text / plain.
I have added this code in angular:
const httpOptions = {
observe: 'response' as 'response',
headers: new HttpHeaders({
'Content-Type': 'text/plain',
})
};
#Injectable({
providedIn: 'root'
})
export class AuthService {
public url: string;
constructor(
public http: HttpClient,
private router: Router) { this.url = GLOBAL.url; }
login(user) {
return this.http.post(this.url + 'login', user, httpOptions)
}
and in my REST Slim API I have added the following:
-> json_decode: to decrypt the file that is in JSON format
$app->post('/login', function (Request $request, Response $response) {
$db = conexion();
$json = $request->getBody();
$input = json_decode($json, true);
$sql = "SELECT * FROM usuario WHERE email= :email";
...
...
}

Observable does not returns api response

I am new in angular.
My Project is in angular5 and I am using a web API created in PHP.
My WebApi gives response in postman but not from angular.
I am using HttpClient to post request
export class GalleryComponent implements OnInit {
private apiUrl = 'http://localhost:8080/fullpath';
private response;
private data=[];
constructor(private http: HttpClient) {
this.response =this.getCategory();
}
getCategory (): Observable<any> {
return this.http.post(this.apiUrl,{});
}
ngOnInit() {
console.log(this.response);
}
}
My console Returns
What I have to do to get proper response from API?
When using Observables, you have to subscribe to them.
The actual user of the observable needs to subscribe(), because without
subscribe() the observable won't be executed at all.
subscribe() returns a Subscription that can not be subscribed to, but it can be used to cancel the subscription.
getCategory (): Observable<any> {
return this.http.post(this.apiUrl,{}).subscribe(
//Do whatever
(res)=> console.log(res),
(error)=> console.log(error)
);
}
For more information you can go to the Angular documentation for Observables:
https://angular.io/guide/observables.
Also, remember that most of the subscriptions terminate by themselves, but is always good practice to terminate them using ngOnDestroy(); to avoid memory leaks.
How to use ngDestroy()?
In you component.ts file
Make sure you have the import
import { Component, OnDestroy, OnInit } from '#angular/core';
export class YourComponent implements OnInit, OnDestroy {
.
.
.
ngOnDestroy() {
this.response.unsubscribe();
}
}
Now, related to your CORS Problem, reference the question that has been asked on stackoverflow before:
Response to preflight request doesn't pass access control check
you can try this solution
ngOnInit() {
this.getCategory().subscribe(response => {
console.log(response);
}, err => {
console.log(err);
});
}
You need to subscribe to an Observable to consume it.
Instead of this
private http: HttpClient) {
this.response =this.getCategory();
}
Try this
private http: HttpClient) {
this.getCategory().subscribe(result => this.responce = result);
}
Great! You can try that
this.getCategory().subscribe(
response => console.log(response),
err => console.log(err)
);
But the best way to use that, you need to create service for POST Request, and you just call him im component. Like that
getCategory(data: any): Observable<any> {
return this._http.post(`url`, JSON.stringify(data))
}
And use that in component
this.categoryService.getCategory(data).subscribe(
data => console.log(data),
err => console.log(err)
)
And you can use Google DevTools to see if is worked the request, and see the request Response! In network! If problem is CORS, you need to set CORS domain in your server!
Try that and tell me if worked! Hope that helps! Thanks

How to solve Cross-Origin-Request-Block issue while fetching data using angular2 and php?

Please read the question in detail since it is a long one with various edits and extended updates as per the request of other users.
I am trying to send data to php file using angular2. I am doing the angular project in Unix and the var/www/html/ is the php Xampp folder locations for running the php files.
My folder structure is like this:-
var/www/html/
|_(angproject)
|_(phpscript)
| |_login.php
|_(src)
|_(app)
|_(admin)
| |_(login)
| | |_login.component.ts
| |
| |_admin.component.ts
|
|_(_admin_service)
| |_admin.login.ts
|
|_(_animations)
|
|_(front)
|
|_(_models)
| |_admin.model.ts
|
|_app.module.ts
My app.module.ts file is like this:-
import { HttpModule, Http, Response, Headers, RequestOptions} from '#angular/http';
import { HttpClientModule } from '#angular/common/http';
import { BrowserModule } from '#angular/platform-browser';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { FormsModule } from '#angular/forms';
import { APP_BASE_HREF } from '#angular/common';
import { CanActivate } from "#angular/router";
import { AppComponent } from './app.component';
import { FrontComponent } from './front/front.component';
import { AdminComponent } from './admin/admin.component';
import { LoginComponent } from './admin/login/login.component';
import { DashboardComponent } from './admin/dashboard/dashboard.component';
import { HeaderComponent } from './admin/header/header.component';
import { FooterComponent } from './admin/footer/footer.component';
import { LeftmenuComponent } from './admin/leftmenu/leftmenu.component';
import { NavbarComponent } from './admin/navbar/navbar.component';
import { ShortcutbarComponent } from './admin/shortcutbar/shortcutbar.component';
import { AdminLoginService } from './_admin_service/admin.login';
const appRoutes: Routes = [
{ path: 'admin',
component: AdminComponent,
children: [
{ path: '', component: LoginComponent},
{ path: 'dashboard', component: DashboardComponent}
]
}
];
#NgModule({
declarations: [
AppComponent,
FrontComponent,
AdminComponent,
LoginComponent,
DashboardComponent,
HeaderComponent,
FooterComponent,
LeftmenuComponent,
NavbarComponent,
ShortcutbarComponent
],
imports: [
HttpModule,
HttpClientModule,
BrowserModule,
BrowserAnimationsModule,
FormsModule,
RouterModule.forRoot(
appRoutes,
{ enableTracing: true } // <-- debugging purposes only
)
],
providers: [{provide: APP_BASE_HREF, useValue : '/' },AdminLoginService],
bootstrap: [AppComponent]
})
export class AppModule { }
My login.component.ts file is this:-
import { Component, OnInit, Input } from '#angular/core';
import { Router, ActivatedRoute } from '#angular/router';
import { fadeInAnimation } from '../../_animations/index';
import { Admin } from '../../_models/admin.model';
import { AdminLoginService } from '../../_admin_service/admin.login';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css'],
animations: [fadeInAnimation],
host: { '[#fadeInAnimation]': '' },
providers: [AdminLoginService]
})
export class LoginComponent implements OnInit {
loading = false;
returnUrl: string;
responseStatus:Object= [];
status:boolean ;
//#Input() admin:Admin;
model = new Admin('', '', '', 'Emailsss','Passwordsss');
constructor(
private route: ActivatedRoute,
private router: Router,
private _adminLogin: AdminLoginService
){}
submitPost()
{
//console.log("submit Post click happend " + this.model.email)
//console.log(this.model);
this._adminLogin.postLogin(this.model).subscribe(
data => console.log(this.responseStatus = data),
err => console.log(err),
() => console.log('Request Completed')
);
this.status = true;
}
ngOnInit() {
}
}
The service file admin.login.ts file is this:-
import { Http, Response, Headers, RequestOptions} from '#angular/http';
import { HttpHeaders } from '#angular/common/http';
import { Injectable } from '#angular/core';
import 'rxjs/add/operator/map';
import { Admin } from '../_models/admin.model';
#Injectable()
export class AdminLoginService {
http : Http;
actionUrl : string;
admin_login_Url: string;
postData: Admin;
constructor(public _http: Http) {
this.http = _http;
this.admin_login_Url = 'http://localhost/angproject/phpscript/login.php';
}
postLogin(postData:Admin) {
let headers = new Headers();
headers.append("Access-Control-Allow-Origin","*");
headers.append("Access-Control-Allow-Methods","GET, POST");
headers.append("Content-Type","application/json");
let options = new RequestOptions({ headers: headers });
console.log(postData);
this.actionUrl = this.admin_login_Url;
return this.http.post(this.actionUrl, {postData}, options)
.map(res => res.json());
}
}
And ultimately, my login.php file is this:-
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST");
header("Access-Control-Allow-Headers: *");
header("Content-Type: application/json; charset=utf-8");
include('connection.php');
$rawData = file_get_contents("php://input");
$data = json_decode($rawData, true);
$error = array();
if(isset($data['postData']['email']) && !empty($data['postData']['email']))
$email = $data['postData']['email'];
else
$error[] = "Email was not entered";
if(isset($data['postData']['password']) && !empty($data['postData']['password']))
$password = $data['postData']['password'];
else
$error[] = "Password was not entered";
if(empty($error))
{
$runQuery = "SELECT * FROM users WHERE email = '$email' AND password = '$password'";
$result = $conn->query($runQuery);
if ($result->num_rows > 0)
{
$response['status'] = 1;
$response['message'] = "Login successfully";
$response['error'] = 0;
}
else
{
$response['status'] = 0;
$response['message'] = "An error occured while logging in";
$response['error'] = $conn->error;
}
}
else
{
$response['status'] = 0;
$response['message'] = "Parameter missing";
$response['error'] = $error;
}
$respond = json_encode($response);
echo $respond;
exit;
?>
Now here is the problem. When testing in Chrome, clicking the submit button once is firing calling for the php script (Ajax) twice. The first call doesn't send any data and hence it shows validation message in return response. The second call sends the form's data and hence fetching the desired result by matching the data sent.
In case of firefox, I am getting this response:-
How can I solve it?
Note:
Here are the Request Headers of the "first call" in chrome:
Here are the Request Headers of the "second call" in chrome:
EDIT: Dated- 04-04-2018:
As per the suggestions from David, I made subsequent changes in my login.php file:
header("Access-Control-Allow-Origin: http://localhost:4200");
header("Access-Control-Allow-Headers: application/x-www-form-urlencoded");
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
In the admin.login.ts file, I made the following changes:-
postLogin(postData:Admin) {
let headers = new Headers();
headers.append("Accept", "q=0.8;application/json;q=0.9");
this.actionUrl = this.admin_login_Url;
return this.http.post(this.actionUrl, {postData}, { headers: headers })
.map(res => res.json()).share();
}
}
Question 1:
For the above code, I took reference from this site. Yet, I am still getting the error. How can I fix this in Firefox?
In the above code, I added the line headers.append("Accept", "q=0.8;application/json;q=0.9"); to overcome an error shown below:-
How can I overcome this problem?
Question 2:
In Firefox, the console reads:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost/angproject/phpscript/register.php. (Reason: invalid token ‘application/x-www-form-urlencoded’ in CORS header ‘Access-Control-Allow-Headers’).
When checking in Chrome, I can see two calls in the network tab in console. The first call's request type is OPTIONS, while the second call has request type as POST.
In case of Firefox, I am getting only one call with request type OPTIONS. The POST request isn't taking place at all.
How can I fix this?
Having 2 requests is normal, due to CORS implementation (client on localhost:4200, server on localhost = different ports).
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
Your problem is that you specified some CORS headers in your request
headers.append("Access-Control-Allow-Methods","GET, POST");
headers.append("Access-Control-Allow-Origin","*");
These headers are meant to be added server side, you don't need to send them from angular. They are actually causing the problem.
Remove them and it should work.
More information about Access-Control-Allow-Headers
Access-Control-Allow-Headers normally accepts a list of comma-separated headers.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
The wildcard (*) value that you have on your PHP code is not supported on all browsers. On Firefox, the wildcard is not implemented yet
https://bugzilla.mozilla.org/show_bug.cgi?id=1309358
That's why firefox is bloking your POST, since the preflight (OPTIONS) request kind of fails
You don't need to specify Content-Type in your list since it's accepted by default
The simple headers, Accept, Accept-Language, Content-Language, Content-Type (but only with a MIME type of its parsed value (ignoring parameters) of either application/x-www-form-urlencoded, multipart/form-data, or text/plain), are always available and don't need to be listed by this header.
Edit: actually, you do need to specify content-type in the list of accepted headers since you are sending application/json, which is not in the above list
I got the same issue while running the angular app on chrome browser in windows. Even I setup CORS configuration in a backend that issue didn't resolve. Then I realize that I need to disable the web security while running on a local machine or
localhost/portNumber
Just hit the following command on cmd
TASKKILL /F /IM chrome.exe
start chrome.exe --args --disable-web-security –-allow-file-access-from-files
This resolved my problem :)

ERROR Error: Uncaught (in promise): TypeError: users is undefined

I have an error in this Component and that error is not caught by command prompt.
Dashboard.component.ts
import { Component, OnInit } from '#angular/core';
import { User } from './user.component';
import { UserService } from './user.service';
#Component({
selector : 'dashboard',
templateUrl : './views/dashboard-component.html',
styleUrls: ['./views/css/dashboard-component.css'],
providers: [UserService]
})
export class DashboardComponent {
users: User[] = [];
constructor(private userservice: UserService){}
ngOnInit() : void{
this.userservice.getusers().then(users => this.users = users.slice(1,5) );
}
}
I can't understand what the problem is because i have defined "users" in the class.
The method is called from this service.
user.service.ts
import { Injectable } from '#angular/core';
import { User } from './user.component';
import { USERS } from './mock-users';
import { Headers, Http } from '#angular/http';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class UserService {
private usersUrl = "http://localhost/user/src/app/userlist.php";
constructor(private http: Http) { }
getusers() : Promise<User[]>{
return this.http.get(this.usersUrl)
.toPromise()
.then(response => response.json().data as User[])
.catch(this.handleError);
}
getuser(id: number): Promise<User> {
const url = '${this.usersUrl}/${id}';
return this.http.get(url)
.toPromise()
.then(response => response.json().data as User)
.catch(this.handleError);
}
private handleError(error : any): Promise<any> {
console.error('an error occured', error);
return Promise.reject(error.message || error);
}
}
The data I am getting is :
[{"id":"1","fname":"Vishwas","lname":"Jadav","email":"vjadav#live.com","dpic":"2017-10-7--09-12-19.jpeg","phone":"7621823474","passw":"illj123","type":"2"}]
You don't have a data property in your response, as we can see you are simply getting an array, so you should return that. So in your service method getusers, instead of...
.then(response => response.json().data as User[])
do:
.then(response => response.json() as User[])
Sidenote, you might have the same problem with your getuser (?) just for future reference if you run into same problem there :)
Try assigning to array and then remove
ngOnInit() : void{
this.userservice.getusers().then(users => this.users = users;
this.users =this.users.slice(1,5);
});

Angular2 http get error

I am brand new in Angular2 framework and I have a problem with http get request. I want to display all registered users on my homepage.
This is my code:
home.service.ts
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class UserService {
constructor (
private http: Http
) {}
getUser() {
return this.http.get(`/app/home/home.php`)
.map((res:Response) => res.json());
}
}
home.component.ts:
// Imports
import { Component, OnInit } from '#angular/core';
import { UserService } from './home.service';
#Component({
templateUrl: './home.component.html'
})
// Component class implementing OnInit
export class HomeComponent{
// Private property for binding
constructor(private userService: UserService) {}
profile = {};
loadUser() {
this.userService.getUser().subscribe(data => this.profile = data);
}
}
home.php
<?php
$connection = new mysqli("127.0.0.1", "root", "", "flatmate");
if($connection->connect_error){
echo $connection->connect_error;
}
/* change character set to utf8 */
if (!$connection->set_charset("utf8")) {
echo $connection->error;
exit();
}
$getUser = 'SELECT * from users';
$result = mysqli_query($connection, $getUser);
$data = array();
while ($row = mysqli_fetch_array($result)) {
$data[] = $row;
}
echo json_encode($data);
home.component.html:
<div>
<button (click)="loadUser()">Load profile</button>
{{ profile | json }}
</div>
In my app.module.ts I added UserService provider. I prepared my code based on this tutorial. When I pass into get method URL from this example, code works properly. But if I change link to my home.php I get the error:
"errors.ts:42 ERROR SyntaxError: Unexpected token < in JSON at position 0"

Categories