I'm trying to implement places auto-complete. So I chose google places. Initially, I was integrating the API with Angular. But got the following error on the console.
XMLHttpRequest cannot load https://maps.googleapis.com/maps/api/place/autocomplete/json?.... No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. core.es5.js:1020 ERROR Response {_body: ProgressEvent, status: 0, ok: false, statusText: "", headers: Headers…}
I found, some experts had some suggestions to make the request from the backend. So I wrote it from backend.
And found something from the Angular documentation.
Angular developers may encounter a cross-origin resource sharing error when making a service request (typically a data service request). to a server other than the application's own host server. Browsers forbid such requests unless the server permits them explicitly.
There isn't anything the client application can do about these errors. The server must be configured to accept the application's requests. Read about how to enable CORS for specific servers at enable-cors.org.
So this is my google.service.ts
import { Injectable } from '@angular/core';
import { HttpModule, JsonpModule, Response, Headers, Http, RequestOptions } from '@angular/http';
import 'rxjs/Rx';
@Injectable()
export class GooglePlaces {
constructor(private http: Http, protected _defaultOptions: RequestOptions) {}
getPlaces(place)
{
return this.http.get("http://backendurl/api/places/"+place, {headers: this.jsonHeaders()}).map(res => res.json());
}
jsonHeaders()
{
let headers: Headers = new Headers();
headers.append("Content-Type", "application/json; charset=utf-8");
headers.append("Access-Control-Allow-Origin", "*");
headers.append("Accept", "application/json");
headers.append("Access-Control-Allow-Methods", "GET");
headers.append("Access-Control-Allow-Headers", "Content-Type");
return headers;
}
}
And my app.component.ts
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
import { GooglePlaces } from './google.service';
import { Place } from './place';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/operator/map';
@Component({
selector: 'search-form',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
stateCtrl: FormControl;
filteredStates: any;
places: Place[] = [];
constructor(private googlePlaces:GooglePlaces) {
this.stateCtrl = new FormControl();
this.filteredStates = this.stateCtrl.valueChanges
.startWith(null)
.map(name => this.filterPlaces(name));
}
ngOnInit() {}
filterPlaces(val: string)
{
var returnPlace = [];
if(val !== null && val !== undefined)
{
const responseplaces = this.googlePlaces.getPlaces(val);
responseplaces.subscribe(
places => this.places = places
);
return this.places;
}
else
{
return returnPlace;
}
}
}
If I use ng serve --prod
or upload the production build of the application. I'm got following error on the browser console.
Uncaught TypeError: Cannot read property 'create' of undefined
I cannot identify the error. I know It is not easy to check the production build js file. Now the entire form is not visible.
It is working on my localhost If I use ng serve
command. But the problem is only for production build.
Please help me to solve this issue. If you have any suggestions or if you found any bad practices on my code please mention it, because I'm new to Angular. That would be really helpful. Thanks in advance.