Why is the user not set here? - javascript

I`m having problems understanding why I'm not able to set the user in the app. Register and login work.
Upon refreshing the app the user is lost, but the access token is still there. Also when I try to create a product, the manufacturer(owner) of it is undefined and not listed in the DB.
I've been debugging it and I can see that req.user is not found by the app and stays undefined/null.
I`m attaching the whole github project for easier code check, if someone decides to help me out here.
https://github.com/theBoomstick7/projectOils2
Thanks in advance everyone!
Changed all possible setting of the user, register and logout and login do work, but not the intended way.
I understand the design is not good, will be fixed later
As I understand this is not a good way to ask a question here, let me add some parts of the code.
This is the server controller of the product:
const {getAll,createProduct} = require(`../services/productService`)
const productController = require(`express`).Router()
productController.post(`/create`, async(req,res) => {
const data = req.body
console.log(req.user)
try {
const userId = req?.user?._id
const product = await createProduct(data,userId)
res.status(201).json(product)
} catch (error) {
res.status(400).json({error:error.message})
}
res.end()
})
This is the angular auth service :
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Router } from '#angular/router';
import { tap } from 'rxjs';
import { IUser } from '../interfaces/user';
const AUTH_API_URL = 'http://localhost:3000' // Change this to environment directory later
#Injectable({
providedIn: 'root'
})
export class AuthService {
user: null | IUser | undefined
constructor(private http: HttpClient, private router: Router) { }
get isLogged(): boolean {
if(this.user){
return true
}else
{
return false
}
}
register(data: {}){
return this.http.post<IUser>(`${AUTH_API_URL}/register`,data).pipe(
tap((user) => {
this.user = user
localStorage.setItem(`accessToken`, this.user.accessToken)
})
)
}
login(data: {}){
return this.http.post<IUser>(`${AUTH_API_URL}/login`, data). pipe(
tap((user) => {
this.user = user
localStorage.setItem(`accessToken`, this.user.accessToken)
})
)
}
logout(){
this.user = null
return localStorage.removeItem(`accessToken`)
}
}
This is the way the user register is handled :
export class RegisterComponent {
errors: any;
constructor(private fb: FormBuilder, private userService: AuthService, private router: Router) {}
registerForm = this.fb.group({
email: [``,[Validators.required, Validators.email]],
username: [``, [Validators.required, Validators.minLength(6)]],
password: [``, [Validators.required, Validators.minLength(6)]],
rePass: [``, [Validators.required,passwordValidator]]
})
register(): void{
this.userService.register(this.registerForm.value).subscribe
({
next: () => this.router.navigate([`/`]),
error:(err)=> {
this.errors = err.error?.error
}
})
this.registerForm.reset()
}
}
This is how a product is created
Product Angular service :
export class ProductsService {
constructor(private http : HttpClient, private router : Router) { }
createProduct(data : {}){
return this.http.post<IProduct>(`${API_URL}/create`, data)
}
}
Create product form :
import { Component } from '#angular/core';
import { FormBuilder, Validators } from '#angular/forms';
import { Route, Router } from '#angular/router';
import { ProductsService } from '../products.service'
#Component({
selector: 'app-create-product',
templateUrl: './create-product.component.html',
styleUrls: ['./create-product.component.css']
})
export class CreateProductComponent {
errors: string | undefined = undefined;
constructor(private fb : FormBuilder, private productService: ProductsService, private router : Router){}
createProductForm = this.fb.group({
title : [``, [Validators.required, Validators.maxLength(12)]],
imageUrl: [``, [ Validators.required]],
description: [``, [Validators.required, Validators.minLength(10)]]
})
createProduct(){
this.productService.createProduct(this.createProductForm.value).subscribe({
next: () => this.router.navigate([`/products`]),
error: (err) => {
this.errors = err.error?.error
}
})
this.createProductForm.reset()
}
}
I hope this makes it easier to everyone.
PP, this is my app interceptor :
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HTTP_INTERCEPTORS } from "#angular/common/http";
import { Injectable, Provider } from "#angular/core";
import { mergeMap, Observable, tap } from "rxjs";
#Injectable()
export class AppInterceptor implements HttpInterceptor{
accessToken:any | [] | null = localStorage.getItem(`accessToken`)
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>
{
if(this.accessToken)
{
return next.handle(req.clone({ setHeaders: {'X-Authorization' : this.accessToken}}))
}
else
{
return next.handle(req.clone())
}
}
}
export const AppInterceptorProvider: Provider = {
provide:HTTP_INTERCEPTORS,
useClass: AppInterceptor,
multi:true
}

I hope I understood well your question. If not, let me know. I will edit my answer.
I could debug your App.
You save your accessToken in the local storage, but not the User object. When you refresh the browser, the "accessToken" is there, but the user not because it was removed from the browser's memory.
In this case, your server knows that you are logged in, but your app (frontend) not.
In the auth.service.ts you have to save the user:
localStorage.setItem(`user`, JSON.stringify(this.user));
In the app.component.ts you have to load the user again and set it into the userService instance:
const myUser: string= localStorage.getItem('user') + '';
const loadedUser: IUser = JSON.parse(myUser);
console.log('Loaded User: ' + loadedUser)
this.userService.setLoggedUser(loadedUser);
An alternative solution could be check in the app.component.tsthe presence of the accessToken. If it is there, you can call a new REST method on the server to get the logged user for that token.

Related

Firebase: Keep user logged in angular 7

I use firebase and angularfire2 within an authentication system!
The problem is that after refresh the user needs to log in again! I need to avoid that issue so I found out that firebase gives me that option by using authState
but still not working!
This the code for the authService:
import { Injectable } from '#angular/core';
import { AngularFireAuth } from 'angularfire2/auth';
import { Observable } from 'rxjs/internal/observable';
import { NavController } from '#ionic/angular';
import { ToastMessagesService } from './toast-messages.service';
import * as firebase from 'firebase';
#Injectable({
providedIn: 'root'
})
export class AuthService {
public user: Observable<firebase.User>;
public userDetails: firebase.User = null;
constructor(
private af: AngularFireAuth,
private navCtrl: NavController,
private statusMessage: ToastMessagesService
) {
this.user = af.authState;
this.user.subscribe(
user => this.userDetails = user
)
}
async siginInRegular(username: string, password: string) {
try {
// const credentials = this.af.auth.email
return await this.af.auth.signInWithEmailAndPassword(username, password).then(
user => {
if (user) {
this.navCtrl.navigateForward('/home');
this.statusMessage.message(`Welcome ${user.user.email}`);
}
},
err => {
console.log(err);
}
);
} catch (error) {
console.dir(error);
}
}
async register(username: string, password: string) {
try {
return await this.af.auth.createUserWithEmailAndPassword(username, password).then(
user => {
this.navCtrl.navigateForward('/profile');
this.statusMessage.message(`Welcome ${user.user.email}`);
}
);
} catch (error) {
console.dir(error);
}
}
signOut() {
return this.af.auth.signOut();
}
isLoggedIn(): boolean {
return (this.userDetails != null) ? true : false;
}
}
The guard code:
import { Injectable } from '#angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '#angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';
import { NavController } from '#ionic/angular';
import { AngularFireAuth } from 'angularfire2/auth';
#Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(
private auth: AuthService,
private navCtrl: NavController,
private af: AngularFireAuth
) {
}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
if (this.auth.isLoggedIn()) {
return true
}
console.log('Access denied!');
return false;
}
}
Firebase actually automatically will sign the user in when you reload the page. But since your handling of the sign-in is only in the then() block, it only happens when you explicitly sign them in.
To fix this, you want to use an onAuthState listener as shown in get the currently signed in user:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});
Unlike the then() handler, this onAuthStateChanged handler will be called every time the user's authentication state changes, including when you reload the page.
Since you're using AngularFire2, you can also use af.auth.subscribe as shown here: How to get the firebase.User in AngularFire2

Angular 2 : Access Cookie after Creation

I have two Component and one Service
Components:
1: LoginComponent
2: HeaderComponent (Shared)
Service:
1: authentication.service
In LoginComponent I use authentication.service to get authenticate and after successful authentication, I add User info into the Cookie and in the end, I automatically navigate to return-URL page, in the returned page I have a Component for the header that must show User info from the saved Cookie, BUT there is nothing in the cookie unless I refresh manually the page with F5 button.
My question is how can I access the cookie without refreshing the page?
Update
this is where I want to get the cookie:
import { Component, OnInit } from '#angular/core';
import { CookieHelper } from '../../_helpers/index';
#Component({
moduleId: module.id,
selector: 'app-header-ichart',
templateUrl: 'header.component.html',
styleUrls: ['header.component.css']
})
export class HeaderComponent implements OnInit {
currentUser = '';
isLogged = false;
constructor(private cookie: CookieHelper) { }
ngOnInit() {
this.isLogged = this.cookie.checkCookie('currentUser');
if (this.isLogged) {
this.currentUser = JSON.parse(this.cookie.getCookie('currentUser'));
}
}
}
Update 2
I used your suggestion technic to achieve my goal but need more help:
I Update my AuthenticationService to serve Observable Variable:
AuthenticationService:
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/map';
import { AppConfig } from '../app.config';
import { CookieHelper } from '../_helpers/index';
#Injectable()
export class AuthenticationService {
cookies: Object;
keys: Array<string>;
user$ = new Subject<any>();
constructor(private http: Http, private config: AppConfig, private cookie: CookieHelper) { }
login(username: string, password: string) {
const headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
let body = `grant_type=${'password'}&username=${username}&password=${password}`;
return this.http.post(
this.config.apiUrl + '/token',
body, { headers: headers })
.map((response: Response) => {
// login successful if there's a jwt token in the response
let user = response.json();
if (user && user.access_token) {
user['username'] = username;
// Observable Variable
this.user$.next(JSON.stringify(user));
// store user details and jwt token in cookie to keep user logged in between page refreshes
this.cookie.addCookie('currentUser', JSON.stringify(user));
}
});
}
getUser(): Observable<any> {
return this.user$.asObservable();
}
logout() {
// remove user from cookie to log user out
this.cookie.removeCookie('currentUser');
// Logout Subscribe
this.user$.next(null);
}
}
HeaderComponent:
export class HeaderComponent implements OnInit {
currentUser = '';
isLogged = false;
constructor(private cookie: CookieHelper, private auth: AuthenticationService) { }
ngOnInit() {
// Get the currentUser from Observable Variable
this.auth.getUser().subscribe(currentUser => { this.currentUser = currentUser; });
console.log(this.currentUser);
this.isLogged = this.cookie.checkCookie('currentUser');
if (this.isLogged) {
this.currentUser = JSON.parse(this.cookie.getCookie('currentUser'));
}
}
}
I suggest to use an Observable to achieve that. So your headerComponent will be notified after the login.
Update your authentication.service so that you have something like
import { Subject } from 'rxjs/Subject';
export class AuthenticationService {
user$: Subject<any>;
login() {
// login stuff
this.user$.next('userDetails');
}
logout() {
this.user$.next(null);
}
}
and then from whatever component you want you can check for the user$ observable.
In template with
{{ (user$ | async)?.username }}
or in code with
user$.subscribe(user => console.log(user.username))

Struggling through AuthGuard in Angular

Tried to follow AuthGuard example available here:
http://www.sparkbit.pl/angular-2-route-guards-real-life-example/
Unfortunately, while trying to implement the ActivationGuard.ts file, I'm receiving few errors.
ERROR in C:/Users/app/src/app/ActivationGuard.ts (6,24): Cannot find name 'ActivatedRouteSna
pshot'.)
C:/Users/app/src/app/ActivationGuard.ts (6,55): Cannot find name 'RouterStateSnapshot'.)
C:/Users/app/src/app/ActivationGuard.ts (13,62): Cannot find name 'CurrentUserService'.)
C:/Users/app/src/app/ActivationGuard.ts (15,31): Cannot find name 'ActivatedRouteSnapshot'.)
C:/Users/app/src/app/ActivationGuard.ts (15,62): Cannot find name 'RouterStateSnapshot'.)
Which basically means that the elements inside the CanActivate interface and inside constructors are not defined.
routing file:
import { WorksheetAccessGuard } from "./ActivationGuard";
const appRoutes: Routes = [
{ path: '', component: LoginComponent },
{ path: 'app', component: AppComponent, canActivate: [WorksheetAccessGuard] },
{ path: '**', redirectTo: '' }
];
My question: From where could I get these missing elements?
Provided image of my IDE: (the red words are the missing ones)
EDIT
I have made a custom service. I'm not sure if its fine or not:
import {Injectable} from '#angular/core';
import {Http} from '#angular/http';
#Injectable()
export class UserAuthenticationService {
isUserAuthenticated: boolean = false;
username: string;
constructor(private http: Http) {
}
authentication() {
this.http.get(`http://localhost/api/auth/isLogged/${this.username}`)
.subscribe(res => {
this.isUserAuthenticated = res.json();
},
err => {
console.error('An error occured.' + err);
});
}
}
Now I'm receiving some error inside the AuthGuard file:
ERROR PIC
**My main goal is checking with every component change (when user navigates over the page) if he is logged or not. If not - return him to the login page.
EDIT2
Can I just post all logic from the service in the AuthGuard file? It will look like:
import {Injectable} from '#angular/core';
import {Router, RouterStateSnapshot, ActivatedRouteSnapshot} from '#angular/router';
import {Observable} from 'rxjs/Observable';
import {UserAuthenticationService} from './UserAuthenticationService';
import {Http} from '#angular/http';
interface CanActivate {
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>|Promise<boolean>|boolean
}
#Injectable()
export class WorksheetAccessGuard implements CanActivate {
private static username: string;
isUserAuthenticated: boolean = false;
constructor(private router: Router, private userService: UserAuthenticationService, private http: Http) {
}
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
this.http.get(`http://localhost/api/auth/isLogged/${this.username}`)
.subscribe(res => {
this.isUserAuthenticated = res.json();
},
err => {
console.error('An error occured.' + err);
});
if (!this.isUserAuthenticated) {
this.router.navigate(['/']);
return false;
}
return true;
}
}
RouterStateSnapshot and ActivatedRouteSnapshot are imported from #angular/router, while the currentUser Service is supposed to be your own where you should store the authenticated state of your User (with a boolean for example).
You retrieve an instance of it through Dependency Injection in your guard's constructor like so :
import { CurrentUserService } from './path/to/your/service/file';
import { RouterStateSnapshot, ActivatedRouteSnapshot } from '#angular/router';
constructor(private userService: CurrentUserService)
{}
Your service needs to be provided in your module, (as well as your guard), and you need to have a property like this in your CurrentUserService :
CurrentUserService :
isAuthenticated: boolean = false;
That way, when you log in from your Login Component (I assume you have one), you can set the service property to true :
LoginComponent :
import { CurrentUserService } from './path/to/your/service/file';
constructor(private userService: CurrentUserService)
{}
login() {
... // Your existing code where you login on form submit or anything
this.userService.isAuthenticated = true;
}
EDIT :
Check out my example, it should fit for yours.
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
if (!this.authService.isAuthenticated) {
// Deny navigation and redirect to login
this.router.navigate(['/path/to/login']);
return false;
}
// Allow navigation (be careful that the guard always resolve a value)
return true;
}

Understanding Why This String Interpolation of an Imported Variable is Working in my Angular 2 App

While making some edits to my Angular 2 app, I was able to get something working BEFORE I assumed it should be working. In other words, I'm a little perplexed as to why it's working in it's current configuration. Specifically, I have an authentication.service that handles my login auth. And I have both a login component and a chat component, both of which have a private instance of the authentication.service in their respective constructors. What I wanted to do was be able to pass the username from the login functionality down to the chat view, so I could display the logged-in user's username in the chatbox. I've got that working, but, strangely enough, I got it working by adding "this.authenticationService.username = this.model.username;" in the login.component, rather than in the authentication.service. So I'm perplexed as to how/why the chat.component even has access to that info. If I remove that one line of code from my login.component, the username will not be passed through to the chat.component. But I never actually import the login component into the chat component, so how is it working as is? Curious to see if someone can help me understand this. Here are the files in question. First, my authentication.service file:
import { ContextMenu } from './../ui/context-menu.component';
import { Router, RouterLinkActive } from '#angular/router';
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
#Injectable()
export class AuthenticationService {
username;
constructor(private http: Http) {}
login(username: string, password: string) {
return this.http.post('/api/authenticate', JSON.stringify({ username: username, password: password }))
.map((response: Response) => {
// login successful if there's a jwt token in the response
let user = response.json();
if (user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
});
}
isAuthenticated() {
if (localStorage.getItem('currentUser')) {
//console.log('User successfully authenticated...');
return true;
} else {
// console.log('User is not authenticated...');
return false;
}
}
logout() {
// remove user from local storage to log user out
localStorage.removeItem('currentUser');
console.log('User successfully logged out');
}
}
And here's my login.component file:
import { UserService } from './../../data/user.service';
import { AuthenticationService } from './../../data/authentication.service';
import { AlertService } from './../../data/alert.service';
import { Component, OnInit, Input } from '#angular/core';
import { Router } from '#angular/router';
#Component({
selector: 'app-login',
templateUrl: 'app/views/login/login.component.html',
styleUrls: ['app/views/login/login.component.css']
})
export class LoginComponent implements OnInit {
model: any = {};
loading = false;
username;
password;
constructor(
private router: Router,
private authenticationService: AuthenticationService,
private alertService: AlertService,
private userService: UserService) { }
ngOnInit() {
// reset login status
this.authenticationService.logout();
}
login() {
this.loading = true;
this.authenticationService.login(this.model.username, this.model.password)
.subscribe(
data => {
this.router.navigate(['/']);
console.log('User logged in as: ' + this.model.username);
},
error => {
this.alertService.error(error);
this.loading = false;
});
this.authenticationService.username = this.model.username;
}
}
Here's my chat.component file:
import { AuthenticationService } from './../../data/authentication.service';
import { Router, ActivatedRoute } from '#angular/router';
import { ChatService } from './chat.service';
import { Component, OnInit, OnDestroy } from '#angular/core';
import { TabPage } from '../../ui/tab-navigation/tab-page';
#Component({
templateUrl: './chat.component.html',
styleUrls: ['./chat.component.less'],
})
export class ChatComponent extends TabPage implements OnInit, OnDestroy {
messages = [];
users = [];
routes;
connection;
userbase;
route;
message;
user;
constructor(private chatService:ChatService,
router: Router,
route: ActivatedRoute,
private authenticationService: AuthenticationService) {
super(router, route);
this._title = 'Chat Room';
this.addEventListener('paramsChange', function(params) {
this._title = 'Chat Room';
}.bind(this));
}
sendMessage() {
this.chatService.sendMessage(this.message);
this.message = '';
}
sendUser() {
this.chatService.sendUser(this.user);
this.user = '';
}
trackUser() {
this.chatService.trackUser(this.route);
console.log('A user just navigated to ' + this.route);
}
// For when user clicks "enter/return" to send message
eventHandler(event: KeyboardEvent): void {
if (event.key === 'Enter') {
this.chatService.sendMessage(this.message);
this.message = '';
}
}
ngOnInit() {
this.connection = this.chatService.getMessages().subscribe(message => {
this.messages.push(message);
});
this.userbase = this.chatService.getUsers().subscribe(user => {
this.users.push(user);
});
this.routes = this.chatService.getRoutes().subscribe(route => {
this.routes.push(route);
});
}
ngOnDestroy() {
this.connection.unsubscribe();
this.userbase.unsubscribe();
}
public getTabId(params): string {
return 'Chat Room';
}
}
Lastly, my chat.component.html file looks like this (this is where I'm actually using the string interpolation to display the username in the chat):
<div class="centered-display" align="center">
<h3>User: {{authenticationService.username}}</h3>
<div *ngFor="let message of messages" class="message">
{{authenticationService.username}}: {{message.text}}
</div>
<input class="form-group" [(ngModel)]="message" (keypress)="eventHandler($event)">
<div class="spacing">
<button class="submit-btn" md-button (click)="sendMessage()">SEND</button>
</div>
</div>
Can someone help me understand why this is working as is? The one line that makes this work is the last line in my login.component login function: "this.authenticationService.username = this.model.username;". But, again, my chat component doesn't have access to my login component (as as I understand). So why is this working?
Your chat component and login component may not directly relate to each other, but they do both have access to the authenticationService. Specifically, they both have a reference to the same instance of that service injected.
This means that when you do this.authenticationService.username = this.model.username in your login component, you are setting the username property on the same authenticationService object that you are accessing with your interpolation in the chat component view ({{authenticationService.username}}).

Angular2: Passing Value from One Component to Another

I have successfully implemented a login service for my Angular 2 app. What I want to do now is provide the username of the logged-in user from that component to a separate component - specifically the chat component.That way I can display the user's name when they are chatting with another user. I'm still a little hazy on how you pass values like this from one component to another in Angular 2. Here is the code from my login component:
import { AuthenticationService } from './../../data/authentication.service';
import { AlertService } from './../../data/alert.service';
import { Component, OnInit, Output } from '#angular/core';
import { Router } from '#angular/router';
#Component({
selector: 'app-login',
templateUrl: 'app/views/login/login.component.html',
styleUrls: ['app/views/login/login.component.css']
})
export class LoginComponent implements OnInit {
//#Output() username;
model: any = {};
loading = false;
constructor(
private router: Router,
private authenticationService: AuthenticationService,
private alertService: AlertService) { }
ngOnInit() {
// reset login status
this.authenticationService.logout();
}
login() {
this.loading = true;
this.authenticationService.login(this.model.username, this.model.password)
.subscribe(
data => {
this.router.navigate(['/']);
console.log('User logged in as: ' + this.model.username);
},
error => {
this.alertService.error(error);
this.loading = false;
});
}
reqPasswordReset() {
let popup = document.getElementById('myPopup');
popup.classList.toggle('show');
}
}
This component make use of an authentication service, which looks like this:
import { LoginComponent } from './../views/login/login.component';
import { ContextMenu } from './../ui/context-menu.component';
import { Router, RouterLinkActive } from '#angular/router';
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
#Injectable()
export class AuthenticationService {
constructor(private http: Http) {}
login(username: string, password: string) {
return this.http.post('/api/authenticate', JSON.stringify({ username: username, password: password }))
.map((response: Response) => {
// login successful if there's a jwt token in the response
let user = response.json();
if (user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
});
}
isAuthenticated() {
if (localStorage.getItem('currentUser')) {
//console.log('User successfully authenticated...');
return true;
} else {
// console.log('User is not authenticated...');
return false;
}
}
logout() {
// remove user from local storage to log user out
localStorage.removeItem('currentUser');
console.log('User successfully logged out');
}
}
I'm able to successfully log to the console the username, so I know I'm capturing that value. What I'd like to do is now pass that value from "this.model.username" to my room component, which currently looks like this:
import { ChatService } from './../chat/chat.service';
import { User } from './../../views/user/user';
import { Component, OnInit, Input } from '#angular/core';
import { AuthenticationService } from './../../data/authentication.service';
import { Http, Headers, Response } from '#angular/http';
import { Router } from '#angular/router';
#Component({
selector: 'app-room',
templateUrl: './room.component.html',
styleUrls: ['./room.component.less']
})
export class RoomComponent implements OnInit {
otherImg = 'app/img/photo-ph.png';
// otherImg = 'app/img/portrait-place-holder.svg';
model: any;
loading = false;
others = [
{ id: 1, name: 'John Smith', avatar: 'app/img/photo-ph.png' },
{ id: 2, name: 'Javier Sanchez', avatar: 'app/img/photo-ph.png' }
];
user;
token;
name;
nickname;
constructor(private authenticationService: AuthenticationService,
private router: Router,
private http: Http,
private chatService: ChatService) { }
isLoggedIn() {
this.loading = true;
if (this.authenticationService.isAuthenticated()) {
return true;
}
}
gotoChat() {
this.chatService.gotoChat(this.user);
}
ngOnInit() {
}
}
The view for this component is looping through users (others) and displaying an icon for each "other" user. Here is that code:
<div *ngIf="isLoggedIn()" class="others">
<span *ngFor="let other of others"><i [ngClass]="'material-icons'" (click)="gotoChat()" [routerLink]="['/chat']">person</i></span>
<a [routerLink]="['/login']">Logout</a>
</div>
The ultimate goal here is for people to see others that are logged in, and be able to initiate a chat with them.
Where I'm stuck is in how to pass the value (this.model.username) that I'm capturing in the login component, down to the room component.
In the login method of your AuthenticationService you're storing the user object in local storage, you should also store it in the authentication service so that when it is injected into the component, you are able to access the user object.
You will need to add another method called getUsername to the AuthenticationService to get the username.
It will look something like this:
#Injectable()
export class AuthenticationService {
private username: string;
constructor(private http: Http) {}
login(username: string, password: string) {
return this.http.post('/api/authenticate', JSON.stringify({ username: username, password: password }))
.map((response: Response) => {
// login successful if there's a jwt token in the response
let user = response.json();
if (user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
// store username
this.username = user.username;
}
});
}
getUsername(): string {
return this.username;
}
make use of #input tag in angular2 this will help you pass information between components
Look at this link for ref
http://www.thoughtdelimited.org/thoughts/post.cfm/learning-angular-2-tour-of-heroes-tutorial-lesson-5

Categories