View {{user.email}} not getting updated after the component variable 'user' in SidebarComponent is updated. It works after manual page refresh. I have split the material design into separate components. The side bar component is as follows
SidebarComponent.ts
import {Component} from 'angular2/core';
import {Router, RouteConfig, ROUTER_DIRECTIVES,CanActivate} from 'angular2/router';
import {HomeComponent} from '../home/HomeComponent'
import {DashboardComponent} from './DashboardComponent'
@Component({
selector: 'app-sidebar',
template: `
<header class="demo-drawer-header">
<img src="../app/assets/images/user.jpg" class="demo-avatar">
<div class="demo-avatar-dropdown">
<span>{{user.email}}</span>
<div class="mdl-layout-spacer"></div>
<button id="accbtn" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon">
<i class="material-icons" role="presentation">arrow_drop_down</i>
<span class="visuallyhidden">Accounts</span>
</button>
<ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect" for="accbtn">
<li class="mdl-menu__item">[email protected]</li>
<li class="mdl-menu__item">[email protected]</li>
<li class="mdl-menu__item"><i class="material-icons">add</i>Add another account...</li>
</ul>
</div>
</header>
<nav class="demo-navigation mdl-navigation mdl-color--blue-grey-800">
<a class="mdl-navigation__link" [routerLink]="['./Dashboard']"><i class="mdl-color-text--blue- grey-400 material-icons" role="presentation">dashboard</i>Dashboard</a>
<a class="mdl-navigation__link" [routerLink]="['./Home']"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">assignment</i>Tasks</a>
<a class="mdl-navigation__link" href=""><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">delete</i>Trash</a>
</nav>
`,
directives: [ROUTER_DIRECTIVES,DashboardComponent]
})
export class SidebarComponent {
user = JSON.parse(localStorage.getItem('profile'));
constructor() {}
}
I have a custom router-outlet to check user authentication which is as follows
import {Directive, DynamicComponentLoader, ElementRef} from "angular2/core";
import {AuthService} from '../../services/AuthService'
import {Router, RouterOutlet, ComponentInstruction} from "angular2/router";
@Directive({
selector: 'auth-router-outlet'
})
export class AuthRouterOutlet extends RouterOutlet {
private _protectedRoutes = {
'app/**': true,
'app/home': true,
'app/dashboard': true,
'app/about': true
};
constructor(_elementRef: ElementRef, _loader: DynamicComponentLoader, private _router: Router, nameAttr: string, private _authService: AuthService) {
super(_elementRef, _loader, _router, nameAttr);
}
activate(nextInstruction: ComponentInstruction): Promise<any> {
if (this._protectedRoutes[nextInstruction.urlPath]) {
if (!this._authService.loggedIn()) {
this._router.navigate(['Login']);
}
}
return super.activate(nextInstruction);
}
}
The aboue outlet uses the following Authservice.ts which sets the Profile object in Localstorage
import {Injectable} from 'angular2/core';
import {ROUTER_DIRECTIVES, Router} from "angular2/router";
import {tokenNotExpired} from 'angular2-jwt';
declare var Auth0Lock: any;
@Injectable()
export class AuthService {
constructor(private router: Router) {}
private useremail;
lock = new Auth0Lock('KEY','URL');
login() {
this.lock.show((error: string, profile: Object, id_token: string) => {
if (error) {
console.log(error);
return false;
}
localStorage.setItem('profile', JSON.stringify(profile));
localStorage.setItem('id_token', id_token);
/*var profiletemp = JSON.parse(localStorage.getItem('profile'));
this.setUserEmail(profiletemp.email);*/
this.router.navigate(['Dashboard']);
});
}
logout() {
localStorage.removeItem('profile');
localStorage.removeItem('id_token');
}
loggedIn() {
return tokenNotExpired();
}
/* setUserEmail(val) { -- not required as profile object is in localstorage
this.useremail = val;
}
getUserEmail() {
return this.useremail;
} */
}
index.html
<html>
<head>
<title>MEAN</title>
<base href="/"/>
<!-- 1. Load libraries -->
<script src="libs/angular2/bundles/angular2-polyfills.js"></script>
<script src="libs/systemjs/dist/system.src.js"></script>
<script src="libs/rxjs/bundles/Rx.js"></script>
<script src="libs/angular2/bundles/angular2.dev.js"></script>
<script src="libs/angular2/bundles/router.dev.js"></script>
<script src="//cdn.auth0.com/js/lock-9.0.min.js"></script>
<script src="libs/angular2/bundles/http.dev.js"></script>
<script src="https://code.getmdl.io/1.1.3/material.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"></ meta>
<meta name="mobile-web-app-capable" content="yes">
<link rel="icon" sizes="192x192" href="app/assets/images/android-desktop.png"></meta>
<!-- Add to homescreen for Safari on iOS -->
<meta name="apple-mobile-web-app-capable" content="yes"></meta>
<meta name="apple-mobile-web-app-status-bar-style" content="black"></meta>
<meta name="apple-mobile-web-app-title" content="Material Design Lite"></meta>
<link rel="apple-touch-icon-precomposed" href="app/assets/images/ios-desktop.png">
<!-- Tile icon for Win8 (144x144 + tile color) -->
<meta name="msapplication-TileImage" content="app/assets/images/touch/ms-touch-icon-144x144-precomposed.png">< /meta>
<meta name="msapplication-TileColor" content="#3372DF"></meta>
<link rel="shortcut icon" href="app/assets/images/favicon.png">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light, bolditalic,black,medium&lang=en">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="https://code.getmdl.io/1.1.3/material.cyan-light_blue.min.css">
<link rel="stylesheet" href="app/assets/styles.css">
<style>
#view-source {
position: fixed;
display: block;
right: 0;
bottom: 0;
margin-right: 40px;
margin-bottom: 40px;
z-index: 900;
}
</style>
<!-- 2. Configure SystemJS -->
<script>
System.config({
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
} ,
map: {
"angular2-jwt": "libs/angular2-jwt/angular2-jwt.js"
}
});
System.import('app/bootstrap')
.then(null, console.error.bind(console));
</script>
</head>
<!-- 3. Display the application..All ExpressJS requests come to this index file and from here Angular routing takes over-->
<body>
<my-app>Loading the application...</my-app>
</body>
</html>
I have the angular2-polyfills.js included in the index. The SidebarComponent view does not update after the corresponding variable in the component is changed.
Any ideas ?
I think that you need to notify the SidebarComponent component that the profile was updated within the local storage with the AuthService shared service. Be sure that this service is configured when bootstrapping your application.
constructor(private router: Router) {}
private useremail;
profileUpdated$:Suject<any> = new Subject(); // <-------
lock = new Auth0Lock('KEY','URL');
login() {
this.lock.show((error: string, profile: Object, id_token: string) => {
if (error) {
console.log(error);
return false;
}
localStorage.setItem('profile', JSON.stringify(profile));
localStorage.setItem('id_token', id_token);
this.profileUpdated$.next(profile); // <-------
this.router.navigate(['Dashboard']);
});
}
logout() {
localStorage.removeItem('profile');
localStorage.removeItem('id_token');
this.profileUpdated$.next(null); // <-------
}
Within the SidebarComponent component you can subscribe on profileUpdated$ to be notified and update the corresponding template:
@Component({
(...)
})
export class SidebarComponent {
user = JSON.parse(localStorage.getItem('profile'));
constructor(private service:AuthService) {
this.profileUpdated$.subscribe(profile => { // <-----
this.user = profile;
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With