我正在开发Angular 2+应用程序。我发现在AngularJS中实现一些相对简单的东西非常困难。
我希望我的顶部导航在用户未登录时显示 LOG IN 按钮,并在她登录时显示 LOG OUT 。
我一直在尝试各种各样的事情,但我无法让它正常工作。我希望它在整个应用程序中始终如一地工作,无论是否重新加载(它将isLoggedIn
存储到localStorage
)
我目前的实施根本没有用,但我会在这里分享,所以你可以告诉我,我是否至少在正确的轨道上。
热门-navigation.component.html
<p class="nav-item my-2 my-lg-0" *ngIf="!isLoggedIn | async"><a class="nav-link" routerLink="/login" routerLinkActive="active">Login</a></p>
<p class="nav-item my-2 my-lg-0" *ngIf="isLoggedIn | async"><a class="nav-link" routerLink="//logout" routerLinkActive="active">Logout</a></p>
热门-navigation.component.ts
export class TopNavigationComponent implements OnInit {
@ViewChild('topnav') topnav: ElementRef;
//isLoggedIn: boolean;
isLoggedIn: Observable<Boolean>;
constructor( private authService: AuthService, private logger: LoggerService ) { }
ngOnInit() {
this.isLoggedIn = this.authService.getIsLoggedIn();
}
auth.service.ts
@Injectable()
export class AuthService {
loggedIn$: Subject<Boolean> = new Subject<Boolean>();
constructor(private logger: LoggerService) {
let isLoggedInLocalStore = (localStorage.getItem('isLoggedIn') === 'true');
if (!isLoggedInLocalStore) {
isLoggedInLocalStore = false;
localStorage.setItem('isLoggedIn', isLoggedInLocalStore.toString());
}
}
getIsLoggedIn(): Observable<Boolean> {
//return (localStorage.getItem('isLoggedIn') === 'true');
return this.loggedIn$.asObservable();
}
login(): void {
// TODO
this.logger.log("AuthService | Login clicked...");
localStorage.setItem('isLoggedIn', 'true');
this.loggedIn$.next(true);
}
logout() {
// TODO
localStorage.setItem('isLoggedIn', 'false');
this.loggedIn$.next(false);
}
}
答案 0 :(得分:1)
我不确定我的回答会对你有所帮助。为此,我创建了名为GlobalEventsManager的服务。
import { Injectable } from '@angular/core';
import { BehaviorSubject } from "rxjs/BehaviorSubject";
import { Observable } from "rxjs/Observable";
@Injectable()
export class GlobalEventsManager {
private _showMainMenu: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(null);
public showMainMenuEmitter: Observable<boolean> = this._showMainMenu.asObservable();
constructor() {
this.showMainMenu(Boolean(localStorage.getItem('currentUser')));
}
showMainMenu(ifShow: boolean) {
this._showMainMenu.next(ifShow);
}
}
在此示例中,我显示/隐藏菜单取决于用户登录或注销。 你如何使用它(不是完整的类代码,只是例子):
import { GlobalEventsManager } from "../../core/_helpers/index";
export class ExampleClass implements OnInit {
constructor(private globalEventsManager: GlobalEventsManager) {
}
login(): void {
//Your code
...
//Show main menu for authentificated users
this.globalEventsManager.showMainMenu(true)
}
logout(): void {
//Your code
...
//Hide main menu
this.globalEventsManager.showMainMenu(false)
}
}
如何在组件中使用它(不是完整的代码,只是示例):
import { GlobalEventsManager } from '/_helpers/index';
@Component({
selector: "main-menu",
templateUrl: "main-menu.component.html",
})
export class MainMenuComponent {
showMainMenu: boolean = false;
constructor(private globalEventsManager: GlobalEventsManager) {
this.globalEventsManager.showMainMenuEmitter.subscribe((mode) => {
// mode will be null the first time it is created, so you need to igonore it when null
if (mode !== null) {
this.showMainMenu = mode;
}
});
}
//Other code
...
...
...
}
现在你有布尔showMainMenu变量取决于你的用户。
PS:您也可以将此GlobalEventsManager用于其他目的。例如。管理应该影响您的应用程序的全局事件。
PPS:我在大约1年前在stackoverflow上找到了类似的解决方案。只是我找不到链接。因此试图在这里描述解决方案。
感谢。希望它会对你有所帮助。
答案 1 :(得分:0)
您正在使用正确的方法,但稍作修改:
在你的top-navigation.component.ts中:
isLoggedIn:boolean;
constructor(private cd:ChangeDetectorRef, private authService: AuthService, private logger: LoggerService ) {
this.authService.getIsLoggedIn().subscribe((loggedIn:boolean) => {
this.isLoggedIn = loggedIn;
this.cd.markForCheck();}
}
在您的auth.service.ts中:
getIsLoggedIn(): Subject<Boolean> {
return this.loggedIn$;
}
并删除|来自HTML的异步。
每当用户登录时,您都会发送true,从服务中抛出您的主题,并且当用户退出时,所有订阅者都会收到通知。
答案 2 :(得分:-2)
您正在考虑的是使用中央Shared Service或甚至使用Event Emitters来实现此目的。
您必须将此功能与本地存储结合使用。当用户登录时,您需要将数据保存在共享服务和本地存储中。因此,这将确保如果他注销,您可以将所有数据都存储在本地存储中,并检查用户是否已登录。
当他按下Logout按钮时从本地存储和共享服务中删除本地值。
现在,如何在此处显示“登录”和“注销”按钮,即事件发射器和共享服务将成为他们的魔力。将值添加到共享服务后,它将发出一个Observable,它将由Observing组件和Observing组件使用If和Else来显示按钮。