I'm following this tutorial: https://www.youtube.com/watch?v=KhzGSHNhnbI&t=527s
And at 51:41 he uses map. But my code doesn't work. Why I can't use it? I get
Property map does not exists on Observable <Response>
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable({
providedIn: 'root'
})
export class DataService {
constructor(public http:Http) {
console.log("Data service connected...");
}
getPosts() {
this.http.get('https://jsonplaceholder.typicode.com/posts').map(res => res.json());
}
}
Service code you provide is using angular 6 which has dependency of rxjs 6.
So from rxjs 6 onwards you have to use pipeable operators and import paths are modified. so please change the code as follows
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class DataService {
constructor(public http:HttpClient) {
console.log("Data service connected...");
}
getPosts() {
this.http
.get('https://jsonplaceholder.typicode.com/posts')
.pipe(
map(res => res.json())
);
}
}
And one more recommendation please start using HttpClient Module instead of Http Module. So even you dont need to use map to get json response
Please check this link for httpClient Module
Related
This is a follow-up of my previous post. I've been debugging this issue for quite a while now and even though I haven't fixed it, I made some discoveries so maybe someone will be able to help.
Here's the whole setup:
app-config.json (/src/assets/):
{
"apiUrl": "localhost:8080"
}
app-config.service.ts (/src/app/):
import {Injectable, Injector} from '#angular/core';
import {HttpClient} from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class AppConfigService {
private appConfig: any;
constructor (private injector: Injector) { }
loadAppConfig() {
let http = this.injector.get(HttpClient);
return http.get('/assets/app-config.json')
.toPromise()
.then(data => {
this.appConfig = data;
})
}
get config() {
return this.appConfig;
}
}
app.module.ts (/src/app/):
import {APP_INITIALIZER, NgModule} from '#angular/core';
import {HttpClientModule} from '#angular/common/http';
import {AppConfigService} from './app-config.service';
import {CometdService} from './cometd/cometd.service';
const appInitializerFn = (appConfig: AppConfigService) => {
return () => {
return appConfig.loadAppConfig();
}
};
#NgModule({
...
providers: [HttpClientModule,
AppConfigService,
{
provide: APP_INITIALIZER,
useFactory: appInitializerFn,
multi: true,
deps: [AppConfigService]
}]
})
export class AppModule {
constructor(cometdService: CometdService) {}
}
cometd.service.ts (/src/app/cometd/):
import {Injectable, OnDestroy} from '#angular/core';
import {Store} from '#ngrx/store';
import * as fromRoot from '../reducers';
import {AppConfigService} from '../app-config.service';
export interface CometDExtended extends cometlib.CometD {
websocketEnabled: boolean;
}
#Injectable({
providedIn: 'root'
})
export class CometdService implements OnDestroy {
protected cometd: CometDExtended = new cometlib.CometD() as CometDExtended;
private subscriptions: cometlib.SubscriptionHandle[] = [];
constructor(private environment: AppConfigService, private store: Store<fromRoot.State>) {
let config = environment.config;
let apiUrl = environment.config.apiUrl;
this.cometd.configure('http://localhost:8080/cometd');
this.startConnection();
}
...
}
The issue happens for various services. CometD is only an example.
The data in app-config.service.ts itself is fetched properly, i.e. loadAppConfig() returns { "apiUrl": "localhost:8080" }.
Injected environment (AppConfigService) is defined, i.e. it's of type Object.
environment.config is undefined, so environment.config.apiUrl returns an error: "TypeError: Cannot read properties of undefined (reading 'apiUrl')".
AppConfigService is not needed in providers array because providedIn: 'root' already make it available.
If you provide the service in different ways you may have multiple instances : one will be loaded, others would not.
If it still does not work, put a breakpoint to check if other services are created before the init completion. I recommand to move the calls out of the CometdService constructor, so you can perform the async call in a clean way
Welp, just minutes after posting the question I happened to find a solution. It seems like since loadAppConfig() is asynchronous, the environment.config might've been accessed before the promise was resolved. Changing the constructor to:
this.environment.loadAppConfig().then(() => {
let config = environment.config
...
});
fixed the issue.
hi it is always my question and worries about
is ionic application secured? is that possible to crack the ionic app and get the inside code or sth like this for example if my code is like this(add a service to my app)
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class EncryptionService {
url = 'https://api.amnas....com';
api-key='......'
constructor(private http: HttpClient) { }
newcheck(checkid: string ,cost: string,toname: string,tocode: string,passcode: string,date: string,checkfor: string,back: string): {
return this.http.get(`${this.url}?key=${this.api-key}&checkid=${encodeURI(checkid)}&cost=${encodeURI(cost)}&toname=${encodeURI(toname)}&tocode=${encodeURI(tocode)}&passcode=${encodeURI(passcode)}&date=${encodeURI(date)}&checkfor=${encodeURI(checkfor)}&back=${encodeURI(back)}`);
}
}
is that possible for anyone to crack my export app(apk) and extract api-key?
No matter how you build your application, any security keys, tokens, etc., are accessible to the client. You cannot rely on anything in your build remaining secret.
I am trying to get data from mongodb, for which I have written a service. But I am getting an error like error TS2339: Property 'map' does not exist on type 'Observable<Response>'
Please help me to resolve this error...
import { Injectable } from '#angular/core';
import { Http, Headers, RequestOptions } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class DataService {
result:any;
constructor(private _http: Http) { }
getUsers() {
return this._http.get("/api/users")
.map(result => this.result = result.json().data);
}
}
You have to import and use the map operator differently:
Change
import 'rxjs/add/operator/map';
to
import { map } from 'rxjs/operators';
Then, do
return this._http.get("/api/users")
.pipe(map(result => this.result = result.json().data));
Addiontal suggestion from Vikas
Migrate from the Http service to the HttpClient. see migration guide
To update to HttpClient, you’ll need to replace HttpModule with
HttpClientModule from #angular/common/http in each of your modules,
inject the HttpClient service, and remove any map(res => res.json())
calls, which are no longer needed.
I am trying to use Nodejs/Express as my back end for producing data from a database. I currently have an api route setup so that a database query will result in its directory. So if I visit localhost:3000/api currently I will see the following:
{"status":200,"data":[{"Issuer_Id":1,"Data_Id":2,"Data_Name":"Name 1"},{"Issuer_Id":2,"Data_Id":14,"Data_Name":"Name 2"},{"Issuer_Id":2,"Data_Id":1,"Data_Name":"Name 3"}],"message":null}
This leads me to believe I have everything setup correctly on the back end.
Now how do I get this data to display on my Angular front end?
I have been through hours of tutorials and this is what I have come up with:
nav.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from '../../data.service';
import { Series } from '../../data.service';
import {Observable} from 'rxjs/Rx';
#Component({
selector: 'app-fixed-nav',
templateUrl: './fixed-nav.component.html',
styleUrls: ['./fixed-nav.component.css']
})
export class FixedNavComponent implements OnInit{
serieses: Series[] ;
constructor(private dataService: DataService) {}
ngOnInit() {
this.dataService.getSeries().subscribe((serieses: Series[]) => this.serieses = serieses);
}
}
data.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from'#angular/common/http';
import { Http, Headers, RequestOptions, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/toPromise';
export class Series {
Issuer_Id: number;
Data_Id: number;
Data_Name: string;
}
#Injectable()
export class DataService {
constructor(private _http: Http) {}
getSeries(): Observable<Series[]> {
return this._http.get("http://localhost:3000/api/")
.map((res: Response) => res.json());
}
}
app.module.ts
import { Form1Module } from './modules/form1/form1.module';
import { FixedNavModule } from './modules/fixed-nav/fixed-nav.module';
import { HeaderModule } from './modules/header/header.module';
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
import { AppComponent } from './app.component';
import { HttpClientModule } from '#angular/common/http';
import { HttpModule } from '#angular/http';
import { DataService } from './data.service';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpModule,
HttpClientModule,
HeaderModule,
FixedNavModule,
Form1Module,
NgbModule.forRoot()
],
providers: [DataService],
bootstrap: [AppComponent]
})
export class AppModule { }
What do I need to enter in the nav.component.html to see the results?
Also note that when I refresh my angular page on lcoalhost:4200 I can see that the GET request is hitting the /apiu/ on the 3000 express server.
I am trying to help with best practices which might help get the intended result. I will amend this answer as we troubleshoot and hopefully arrive at the right answer.
So in your dataServices service I wanted to point out a couple things. Angular recommends we use the httpClient and not http and warn that http will soon be depreciated. I am fairly new to angular myself and have only ever used httpClient and have gotten great results so I recommend using that. I think this means that the promise that you are returned is changed too. Namely, you pust use a .pipe method inorder to use rxjs operators like map on the result. So this is what your dataService file would look like:
import { Injectable } from '#angular/core';
import { HttpClient } from'#angular/common/http';
import { Http, Headers, RequestOptions, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { map } from 'rxjs/operators';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/toPromise';
export class Series {
Issuer_Id: number;
Data_Id: number;
Data_Name: string;
}
#Injectable()
export class DataService {
constructor(private _http: HttpClient) {}
getSeries(): Observable<Series[]> {
return this._http.get<Series[]>("http://localhost:3000/api/")
.pipe(
map((res) => {
console.log(res);
return <Series[]> res
})
)
}
}
Note that I have imported map in a different rxjs/operators.
In actuality you dont even need to pipe or map the return since you have already declared the type of return in the get method of _http. HttpClient will cast the return into a Series[] for you so this one liner: return this._http.get("http://localhost:3000/api/") would work. I've written the code how it is however to console.log the return that your getting.
In the comments, could you tell me what is logged?
I am unable to correct your code I am providing my own setup Works for Me
In server.js
module.exports.SimpleMessage = 'Hello world';
Now in App.js
var backend = require('./server.js');
console.log(backend.SimpleMessage);
var data = backend.simpleMessage
In index html include App.js
<script src = '/App.js'></script>
alert(simpleMessage)
And you should get 'hello world'
I have a developed a small library (js code) that I want to integrate with angular. the problem is that this library at a certain moment should make request ( ajax ) to push some results to the back-end. How can I make that in angular ? should I develop directives to support binding ?
Sorry I have small knowlege in angular but whats the best way to send data collected by the front end to backend.
thanks
The best way to interact with backend is to use services. For example (the example is for the latest Angular version, previous versions doesn't support HttpClient, it's just Http. I also use toPromise, it's optional, you can deal with observable if you want):
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class YourService {
constructor(
private _http: HttpClient
) { }
public sendDataToServer(data: any): Promise<any> {
return this._http.post(http://fakehost/fakeurl, data)
.toPromise()
.catch(err => console.error(err));
}
And inside your component:
import { Component } from '#angular/core';
import { YourService } from '../../core/your-service.service';
#Component({
selector: 'your-component',
templateUrl: './your-component.component.html',
styles: [``]
})
export class SignUpComponent {
constructor(private _yourService: YourService) {
this.ApiCall();
}
public ApiCall(): void {
this._yourService.sendDataToServer("any data here")
.then(response => {
console.log("Response:", response);
})
.catch(err => console.error(err));
}
}