Sharing an object from cone component to another Angular 2 - javascript

I want to share an object from my first component to the second. I am able to log the 'strVal'(string) defined in the Login Component, in my Home Component but I am unable to log the value of 'abc'(Object) from the Login Component, in the HomeComponent. I am confused why one value from Login Component gets available to Home Component and other does not! The code for Login Component in below
Login.Component.ts
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { AuthenticationService } from '../_services/index';
import { User } from '../contract';
#Component({
moduleId: module.id,
templateUrl: 'login.component.html'
})
export class LoginComponent implements OnInit {
model: any = {};
loading = false;
error = '';
us: User[];
abc: any[];
strVal: string = "Rehan";
current: any;
constructor(
private router: Router,
private authenticationService: AuthenticationService) { }
ngOnInit() {
// reset login status
this.authenticationService.logout();
this.getUs();
}
login() {
this.loading = true;
this.authenticationService.login(this.model.username, this.model.password)
.subscribe(result => {
if (result) {
this.router.navigate(['/']);
}
else {
alert('Username and Password Incorrect');
this.loading = false;
this.model = [];
this.router.navigate(['/login']);
}
});
}
getUs() {
this.authenticationService.getUsers().subscribe(
res => this.us = res
);
}
chek() {
this.abc = this.us.filter(a => a.Login === this.model.username);
console.log(this.abc);
}
}
Home.Component.ts
import { Component, OnInit, Input } from '#angular/core';
import { AuthenticationService } from '../_services/index';
import { LoginComponent } from '../login/index';
import { User } from '../contract';
#Component({
moduleId: module.id,
templateUrl: 'home.component.html',
providers: [LoginComponent]})
export class HomeComponent implements OnInit {
users: User[];
constructor(private userService: AuthenticationService, private Log: LoginComponent) { }
ngOnInit() {
this.userService.getUsers().subscribe(
res => this.users = res
);
console.log(this.Log.strVal);
console.log(this.Log.abc);
}
}
Any hint or help will be appreciated. Thanks!

Related

Image User Firebase

I have created an interface called user with an email property, password and photo url. When I load it in the ngOnInit() the value user (object) photo url says src = (unknown). I want to show the associated image (storage - when I register / create the user) on the header
//user.class.ts
export class User {
email: string;
password: string;
photoUrl: string;
}
//header.component.ts
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { AngularFireAuth } from '#angular/fire/auth';
import { AuthService } from 'src/app/service/auth.service';
import { User } from 'src/app/share/user.class';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss'],
})
export class HeaderComponent implements OnInit {
user: User = new User();
constructor(
private router: Router,
private auth:AngularFireAuth,
private authSvc:AuthService
) { }
ngOnInit() {
this.authSvc.isAuth().subscribe(user => {
if(user) {
this.user.photoUrl = user.photoUrl;
console.log(this.user.photoUrl);
}
})
}
//auth.service.ts
isAuth(user: User) {
return this.auth.authState.pipe(map(user => user));
}
//header.html
<ion-avatar>
<img src="{{user.photoUrl}}" />
</ion-avatar>
I have made a web app with angular and firebase.
fUser is the user from firebase, and User is my interface
import { Component, OnInit } from '#angular/core'
import { AngularFireAuth } from '#angular/fire/auth'
import { Observable } from 'rxjs'
import { first } from 'rxjs/operators'
import { User as fUser } from 'firebase'
import { User } from '#models/User'
#Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {
public user$: Observable<fUser> = this.auth.user
public currentUser: User
constructor(
private auth: AngularFireAuth
) { }
ngOnInit() {
this.user$.pipe(first()).toPromise().then(user => {
this.currentUser = user as User
})
}
}

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(){}
}

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.

Accessing Variable of Bootstrapped Service

I am trying to learn how service injection works in Angular 2. I have created an app and a service. My service is as follows:
import {Injectable} from 'angular2/core';
#Injectable()
export class UserService {
logged: boolean;
users: Array<any>;
constructor () {
this.logged = false;
this.users = [
{username: 'david', password: 'password'}
]
}
checkLogin (username, password) {
this.users.forEach((user) => {
if (user.username == username && user.password == password) {
this.logged = true;
return true;
} else {
this.logged = false;
return false;
}
})
}
logOut () {
this.logged = false;
}
}
I am injecting this into the bootstrap so that I can access it throughout the application as follows:
import {bootstrap} from 'angular2/platform/browser'
import {AppComponent} from './components/app.component'
import {ROUTER_PROVIDERS} from 'angular2/router';
import {UserService} from './services/user.service';
bootstrap(AppComponent, [ROUTER_PROVIDERS, UserService]);
I have then tried to access this in one of my components views but cannot do so. I have tried to access it like this:
import {Component} from 'angular2/core';
import {ROUTER_DIRECTIVES} from "angular2/router";
#Component({
selector: 'navbar',
template: '<li><a>{{UserService.logged}}</a></li>',
directives: [ROUTER_DIRECTIVES],
})
export class NavbarComponent {
}
It does not allow me to access the variable, why is this?
You need to import the service in your component. In bootstrap you initialized/constructed it (made a singleton - meaning one instance for all components), but you have to import and assign it to the component property to be able to use it. Component's template only has access to component's properties and methods...
import {Component} from 'angular2/core';
import {ROUTER_DIRECTIVES} from "angular2/router";
import {UserService} from './services/user.service';
#Component({
selector: 'navbar',
template: '<li><a>{{userService.logged}}</a></li>',
directives: [ROUTER_DIRECTIVES],
})
export class NavbarComponent {
// this way you let TS declare it
constructor(public userService: UserService) {}
// this is same as:
// userService;
// constructor(userService: UserService) {
// this.userService = userService;
// }
}
Here is an alternative to Sasxa's answer. I use this approach when I need to do some other login or logout related actions.
UserService:
import {Injectable, EventEmitter} from 'angular2/core';
#Injectable()
export class UserService {
public doLoginUpdate: EventEmitter<boolean> = new EventEmitter();
logged: boolean;
users: Array<any>;
constructor () {
this.logged = false;
this.users = [
{username: 'david', password: 'password'}
]
}
checkLogin (username, password) {
this.users.forEach((user) => {
if (user.username == username && user.password == password) {
this.logged = true;
return true;
} else {
this.logged = false;
return false;
}
})
this.doLoginUpdate.emit(this.logged);
}
logOut () {
this.logged = false;
this.doLoginUpdate.emit(this.logged);
}
}
NavbarComponent:
import {Component} from 'angular2/core';
import {ROUTER_DIRECTIVES} from "angular2/router";
import {UserService} from './services/user.service';
#Component({
selector: 'navbar',
template: '<li><a>{{logged}}</a></li>',
directives: [ROUTER_DIRECTIVES],
})
export class NavbarComponent {
logged: boolean = false;
constructor(
private userService: UserService) {
this.userService.doLoginUpdate.subscribe((logged)=>{
this.logged = logged;
//do something important related to logging in or logging out
});;
}
}

Categories

Resources