Get user data with Angular httpClient - javascript

I want to fetch user data, but I always get null. Here's my route:
router.get('/user', (req,res)=>{
res.send(req.user);
})
Don't want to go into the details, but on http://localhost:4000/auth/user, I have my user data, when I am logged in.
Here's my web service("framework" to all services) get part :
constructor(private http:HttpClient) { }
get(uri:string) {
return this.http.get(`${this.devUri}/${uri}`)
}
and AuthService(whole, because it's short):
import { Injectable } from '#angular/core';
import { WebService } from './web.service';
#Injectable({
providedIn: 'root'
})
export class AuthService {
constructor(private webService: WebService) { }
getUser(){
return this.webService.get('auth/user');
}
}
And component with this data:
import { Component, OnInit } from '#angular/core';
import { AuthService } from 'src/app/services/auth.service';
#Component({
selector: 'app-public',
templateUrl: './public.component.html',
styleUrls: ['./public.component.css']
})
export class PublicComponent implements OnInit {
user: any;
constructor(private authService: AuthService) { }
ngOnInit(): void {
this.authService.getUser().subscribe( user => {
this.user = user;
console.log(user);
})
}
}
I am sure, that there is no problem with addresses or typos, but I suspect, that the problem is connected with asynchronism, but I don't know how to fix it.

I think it's server side code issue try changing that as followed.
router.get('/user', (req,res)=>{
res.status(200).json({
result: true,
user: 'Test result'
});
});
And in you component while onInit method add as followed
import { Component, OnInit } from '#angular/core';
import { AuthService } from 'src/app/services/auth.service';
#Component({
selector: 'app-public',
templateUrl: './public.component.html',
styleUrls: ['./public.component.css']
})
export class PublicComponent implements OnInit {
user: any;
constructor(private authService: AuthService) { }
ngOnInit(): void {
this.authService.getUser().subscribe( result => {
let temp:any = result;
this.user = temp.user;
console.log(this.user);
})
}
}
Hopefully this should work. Happy Coding!

Found the solution:
In server.js
app.use(
cors({
origin: "http://localhost:4200",
credentials: true
})
);
In webService.ts:
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
}),
withCredentials: true
}
get(uri:string) {
return this.http.get(`${this.devUri}/${uri}`, httpOptions)
}
and it's working now.

Related

AngularFire doesn't trigger change detection

I'm using AngularFire and Angular 8 to build an app but I have a silly problem (I believe it is silly actually).
I built a simple service to wrap AngularFireAuth:
import { Injectable } from '#angular/core';
import { AngularFireAuth } from '#angular/fire/auth';
import { User } from 'firebase';
import { Subject } from 'rxjs';
import { MessageService } from 'primeng/api';
#Injectable({
providedIn: 'root'
})
export class AuthService {
private user: Subject<User> = new Subject();
private isLoggedIn: Subject<boolean> = new Subject();
constructor(private afAuth: AngularFireAuth, private messageService: MessageService) {
this.afAuth.auth.onAuthStateChanged(user => {
this.user.next(user);
this.isLoggedIn.next(user !== null);
});
}
isAuthenticated() {
return this.isLoggedIn.asObservable();
}
}
Then, I injected it in my HomeComponent and subscribed to the Observable returned by the isAuthenticated method:
import { Component, OnInit } from "#angular/core"
import { AuthService } from '../auth/auth.service';
#Component({
selector: 'app-homepage',
styleUrls: ['./homepage.component.scss'],
templateUrl: './homepage.component.html'
})
export class HomepageComponent implements OnInit {
isAuthenticated: boolean = false;
constructor(private authService: AuthService) { }
ngOnInit() {
this.authService.isAuthenticated().subscribe((isAuth) => {
this.isAuthenticated = isAuth;
console.log(`User is authenticated? ${this.isAuthenticated}`);
});
}
}
However, when the arrow function passed to the subscribe method is invoked, no re-rendering is executed. But, the console.log call does show "User is authenticated? true" on DevTools.
Some other tests that I've done: if I call setTimeout from within the arrow function passed to subscribe, the result is the same. No re-render and the message on DevTools says "User is authenticated? true".
But, if I invoke setTimeout (in this test with a 10 secs delay) outside subscribe, the component is re-rendered after these 10 seconds:
import { Component, OnInit } from "#angular/core"
import { AuthService } from '../auth/auth.service';
#Component({
selector: 'app-homepage',
styleUrls: ['./homepage.component.scss'],
templateUrl: './homepage.component.html'
})
export class HomepageComponent implements OnInit {
isAuthenticated: boolean = false;
constructor(private authService: AuthService) { }
ngOnInit() {
this.authService.isAuthenticated().subscribe((isAuth) => {
this.isAuthenticated = isAuth;
console.log(`User is authenticated? ${this.isAuthenticated}`);
});
setTimeout(() => {
this.isAuthenticated = true;
console.log(`User is authenticated? ${this.isAuthenticated}`);
}, 10000)
}
}
What am I missing here? What have I misunderstood?
it's because after component init you're calling your authentication
call it in constructor it works
import { Component, OnInit } from "#angular/core"
import { AuthService } from '../auth/auth.service';
#Component({
selector: 'app-homepage',
styleUrls: ['./homepage.component.scss'],
templateUrl: './homepage.component.html'
})
export class HomepageComponent implements OnInit {
isAuthenticated: boolean = false;
constructor(private authService: AuthService) {
this.authService.isAuthenticated().subscribe((isAuth) => {
this.isAuthenticated = isAuth;
console.log(`User is authenticated? ${this.isAuthenticated}`);
});
}
ngOnInit(){}
}

Property '' does not exist on type 'Object'

I was working all day in angular. Everything worked fine all day.
Restarted the server (ng serve). And now suddenly there are alot of errors.
I managed to fix most but I am stuck with this one.
This is the main part of the component .ts file:
import { Component, OnInit } from '#angular/core';
import { HttpService } from '../http.service';
#Component({
selector: 'app-playboard',
templateUrl: './playboard.component.html',
styleUrls: ['./playboard.component.scss']
})
export class PlayboardComponent implements OnInit {
brews: Object;
constructor(private _http: HttpService) { }
ngOnInit() {
this._http.myMethod().subscribe(data => {
this.brews = data;
this.dices = this.brews.myBox;
this.diceSeed = this.brews.boxID;
console.log(this.brews);
});
}
And this is the http.service.ts file:
import { Injectable } from '#angular/core';
import {HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class HttpService {
constructor(private http: HttpClient) { }
myMethod() {
return this.http.get<Object>('https://localhost:44398/api/boggle');
}
myWordMethod(word) {
var url = 'https://localhost:44398/api/wordpoints/' + word;
return this.http.get<Object>(url);
}
}
It was working all day and suddenly these strange errors appear.
Does anyone have a clue of what could be wrong? Thanks alot!
Remove Object from your http calls. Using the generic is optional, especially if you haven't typed out your response.
import { Injectable } from '#angular/core';
import {HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class HttpService {
constructor(private http: HttpClient) { }
myMethod() {
return this.http.get('https://localhost:44398/api/boggle');
}
myWordMethod(word) {
var url = 'https://localhost:44398/api/wordpoints/' + word;
return this.http.get(url);
}
}
On brews, declare it as any:
import { Component, OnInit } from '#angular/core';
import { HttpService } from '../http.service';
#Component({
selector: 'app-playboard',
templateUrl: './playboard.component.html',
styleUrls: ['./playboard.component.scss']
})
export class PlayboardComponent implements OnInit {
brews: any;
constructor(private _http: HttpService) { }
ngOnInit() {
this._http.myMethod().subscribe(data => {
this.brews = data;
this.dices = this.brews.myBox;
this.diceSeed = this.brews.boxID;
console.log(this.brews);
});
}
You can ignore these by simply delcaring them as the any type. For instance;
myWordMethod(word: any) {
..
}
this._http.myMethod().subscribe(data: any => {
..
});
That said declaring the actual type for TypeScript is often preferred. For Instance if your API sends back a common object with particular properties then declare it as such;
interface MyMethodResponse {
someProperty: string;
someNumber: number;
someArray: string[];
}
this._http.myMethod().subscribe((myMethodResponse: MyMethodResponse) => {
// TypeScript now knows that these properties exists on the response object
console.log(myMethodResponse.someArray);
console.log(myMethodResponse.someNumber);
console.log(myMethodResponse.someProperty);
});

How to approach multiple async requests from back-end in Angular 6?

I am new to Angular and having hard time grasping how to deal with async requests.
I have 3 components:
parent - AppComponent
children - LoginComponent,NavbarComponent,DashboardComponent,MainComponent,SidebarComponent
and one AuthService
On pressing "Login" button at the logging component I need to transfer boolean "true" value to all components.
On pressing "Logout" button at the navbar component I need to transfer boolean "false" value to all components and set user=null
if true ->
set token in localStorage with user ID
preform http.get("http://localhost:3000/user/"+id) request to retrieve full user info and inject user info to Dashboard,Main,Sidebar,App and Navbar components.
The problem is that whenever I logout the false/true value updates on all components immediately but the user info does not turn into null unless I refresh the page or send it with router to another component and then return to MainComponent, same thing with new login.
How do I update both user info and status in all components immediately without refreshing the page?
authService:
import { Injectable } from "#angular/core";
import { HttpClient } from "#angular/common/http";
import { Router } from "#angular/router";
import { User } from "../models/User";
#Injectable({ providedIn: "root" })
export class AuthService {
user: User;
private _url = "http://localhost:5000/user/";
constructor(private http: HttpClient, private _router: Router) {}
registerUser(user) {
return this.http.post<any>(this._url + "register", user);
}
loginUser(user) {
return this.http.post<any>(this._url + "login", user);
}
logoutUser() {
localStorage.clear();
this._router.navigate(["/"]);
}
loggedIn() {
return !!localStorage.getItem("token");
}
getToken() {
return localStorage.getItem("token");
}
getCurrentUser() {
return this.http.get<any>("http://localhost:5000/shop/current");
}
}
Main/Sidebar component:
import { Component, OnInit, DoCheck } from "#angular/core";
import { AuthService } from "src/app/services/auth.service";
import { User } from "src/app/models/User";
#Component({
selector: "app-sidebar",
templateUrl: "./sidebar.component.html",
styleUrls: ["./sidebar.component.css"]
})
export class SidebarComponent implements OnInit, DoCheck {
isSidenavOpen: boolean = true;
user: User;
constructor(private _authService: AuthService) {}
ngOnInit() {
if (this._authService.loggedIn()) this._authService.getCurrentUser().subscribe(res => (this.user = res.user));
else this.user = null;
}
ngDoCheck() {
if (!this._authService.loggedIn()) this.user = null;
}
}
login:
constructor(private _authService: AuthService, private _router: Router) {}
// onLoginUser() {
// this._authService.loginUser(this.loginUserData).subscribe(
// res => {
// localStorage.setItem("token", res.token);
// localStorage.setItem("user", res.user._id);
// this._router.navigate(["/"]);
// },
// err => console.log(err)
// );
// }
}
Use event EventEmitter to emit event on login, logout etc and listen in each component, that depends on user data.
In service, where you call logoutUser, loginUser methods of AuthService:
// LoginService
userLoggin: EventEmitter<User> = new EventEmitter();
userLoggout: EventEmitter<any> = new EventEmitter();
constructor(private _authService: AuthService, private _router:
Router) {}
loginUser() {
this._authService.loginUser(this.loginUserData).subscribe(
res => {
localStorage.setItem("token", res.token);
localStorage.setItem("user", res.user._id);
this.userLoggin.emit(res.user);
this._router.navigate(["/"]);
},
err => console.log(err)
);
}
logoutUser() {
this._authService.logoutUser().subscribe(
res => {
this.userLoggout.emit();
},
err => console.log(err)
);
}
}
Then in component:
import { Component, OnInit, DoCheck } from "#angular/core";
import { AuthService } from "src/app/services/auth.service";
import { User } from "src/app/models/User";
import { LoginService } from "src/app/services/login.service";
#Component({
selector: "app-sidebar",
templateUrl: "./sidebar.component.html",
styleUrls: ["./sidebar.component.css"]
})
export class SidebarComponent implements OnInit, DoCheck {
isSidenavOpen: boolean = true;
user: User;
loggin$: Subscription;
logout$: Subscription;
constructor(private _authService: AuthService, private _loginService: LoginService) {
this.loggin$ = this._loginService.userLoggin.subscribe(user => {
this.user = user;
});
this.logout$ = this._loginService.userLoggout.subscribe(user => {
this.user = null;
});
}
ngOnInit() {
}
ngOnDestroy() {
this.loggin$.unsubscribe();
this.logout$.unsubscribe();
}
}

Angular 5 component expecting an argument

Im trying a simple profile app, and all the sudden Im getting error TS2554
ERROR in /app/components/profile/profile.component.ts(25,3): error TS2554: Expected 1 arguments, but got 0.
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../../services/auth.service';
import { FlashMessagesService } from 'angular2-flash-messages';
import { Router } from '#angular/router';
#Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
user: Object;
constructor(
private auth: AuthService,
private flashMsg: FlashMessagesService,
private router: Router
) {
}
ngOnInit() {
this.auth.getProfile().subscribe( profile => {
this.user = profile.user;
},
err => {
return false;
});
}
}
auth.service.ts
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import 'rxjs/add/operator/map';
import { tokenNotExpired } from 'angular2-jwt';
#Injectable()
export class AuthService {
authToken: any;
user: any;
constructor(
private http: Http
) {
}
getProfile(user) {
let headers = new Headers();
this.loadToken();
headers.append('Authorization', this.authToken);
headers.append('Content-Type','application/json');
return this.http.get('http://localhost:3000/users/profile', {headers:headers})
.map(res => res.json());
}
loadToken() {
const token = localStorage.getItem('id_token');
this.authToken = token;
}
}
Your getProfile is expecting an argument named user but you are not passing it from the component
You need to pass an argument as follows,
this.auth.getProfile(user).subscribe( profile => {
this.user = profile.user;
},
err => {
return false;
});
or if you don't need an argument , remove it from your service method.

Can't Get Response From Http in Angular

i need help in getting a response from http during ngOnInit(). I put an alert("hello") and it's not alerting anything. Is there something wrong in my code?
import { Component, OnInit } from '#angular/core';
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import 'rxjs/Rx';
#Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css']
})
#Injectable()
export class DashboardComponent implements OnInit {
constructor(private http: Http) { }
ngOnInit() {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
let authToken = localStorage.getItem('auth_token');
headers.append('Authorization', `Bearer ${authToken}`);
return this.http
.get('http://sampeleposts', { headers })
.map(
response => {
console.log(response);
alert("hello");
},
error => {
alert(error.text());
console.log(error.text());
}
);
}
}
Looks like you are missing .subscribe()
return this.http
.get('http://sampeleposts', { headers })
.subscribe(
response => {
console.log(response);
alert("hello");
},
error => {
alert(error.text());
console.log(error.text());
}
);
That is how observables works. If you won't subscribe it won't executed
UPDATE:
Here is "how to http" taking from How to make post request from angular to node server:
import { Component } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
user = { id : 1, name : 'Hello'};
constructor(private http: HttpClient) { }
callServer() {
const headers = new HttpHeaders()
.set('Authorization', 'my-auth-token')
.set('Content-Type', 'application/json');
this.http.post('http://127.0.0.1:3000/ping', JSON.stringify(this.user), {
headers: headers
})
.subscribe(data => {
console.log(data);
});
}
}
The example above is using the new '#angular/common/http' shipped in
Angular 4.3+ so as you mentioned in comments you are already using
one of these versions so I would recommend to switch to HttpClient
then.

Categories

Resources