我正在用Angular 8编写Web应用程序。
我有标题和登录页面。我想在登录后更新标题,以显示有关当前登录用户的信息。我正在使用BehaviourSubject来执行此操作,但这不起作用。
这是我的身份验证服务,位于BehaviorSubject
@Injectable()
export class AuthService {
private readonly GRANT_TYPE = 'password';
logged: BehaviorSubject<UserDataModel> = new BehaviorSubject<UserDataModel>(null);
//private auth$: Observable<Auth>;
constructor(private httpClient: HttpClient, private router: Router) { }
login(credentials: CredentialsModel) {
this.httpClient.post('http://localhost:8080/api/oauth/token',
this.prepareParams(credentials),
{ headers: this.prepareHeaders() })
.subscribe(token => {
let userData = new UserDataModel();
userData.token = token['access_token'];
this.getUserInfo(userData);
});
//this.saveAuth();
}
autoLogin() {
const userData = JSON.parse(localStorage.getItem('user'));
if (!userData) {
return;
}
if (userData.token) {
this.logged.next(userData);
}
}
private prepareHeaders(): HttpHeaders {
let headers = new HttpHeaders();
headers = headers.append('Authorization', 'Basic ' + btoa('frontendClientId:frontendClientSecret'));
headers = headers.append('Content-Type', 'application/x-www-form-urlencoded');
return headers;
}
private prepareParams(credentials: CredentialsModel) {
let params = new HttpParams();
params = params.append('username', credentials.username);
params = params.append('password', credentials.password);
params = params.append('grant_type', this.GRANT_TYPE);
return params;
}
private getUserInfo(userData: UserDataModel) {
this.httpClient.get('http://localhost:8080/api/user/user/current',
{headers: new HttpHeaders().append('Authorization', 'Bearer ' + userData.token)})
.subscribe(data => {
userData.email = data['name'];
userData.role = data['authorities'][0]['authority'];
this.saveUser(userData);
this.logged.next(userData);
this.router.navigate(['../']);
})
}
private saveUser(userData: UserDataModel) {
localStorage.setItem('user', JSON.stringify(userData))
}
}
我的标头组件是我从身份验证服务中订阅BehaviorSubject的
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit, OnDestroy, DoCheck {
loggedIn: boolean = false;
username: string ='';
private subscriptions: Subscription[] = [];
constructor(private authService: AuthService) { }
ngOnInit() {
this.subscriptions.push(this.authService.logged.subscribe(this.onLogged));
}
ngDoCheck(): void {
this.authService.autoLogin();
}
onLogout() {
this.loggedIn = false;
}
onLogged(userData: UserDataModel) {
if(userData) {
this.loggedIn = true;
this.username = userData.email;
}
}
ngOnDestroy(): void {
this.subscriptions.forEach(sub => sub.unsubscribe());
}
}
一些HTML代码在登录后不会更新:
<div class="header-actions" *ngIf="!loggedIn">
<a routerLink="/login" class="nav-link nav-icon-text">
<clr-icon shape="user"></clr-icon>
<span class="nav-text">Zaloguj się</span>
</a>
<a href="" class="nav-link nav-icon-text">
<clr-icon shape="plus"></clr-icon>
<span class="nav-text">Zarejestruj się</span>
</a>
</div>
<div class="header-actions" *ngIf="loggedIn">
<clr-dropdown>
<button class="nav-text" clrDropdownTrigger>
{{username}}
<clr-icon shape="caret down"></clr-icon>
</button>
<clr-dropdown-menu *clrIfOpen clrPosition="bottom-right">
<a routerLink="#" clrDropdownItem>Profil</a>
<a routerLink="#" clrDropdownItem (click)="onLogout()">Wyloguj</a>
</clr-dropdown-menu>
</clr-dropdown>
</div>
在登录组件中,我从auth.service调用方法“ login”,并且可以正常运行,它可以正确导航到仪表板,但没有更新的标题。
你知道我在做什么错吗?
答案 0 :(得分:0)
我认为预订“ this.onLogged”的以下行存在问题:
ngOnInit() {
this.subscriptions.push(this.authService.logged.subscribe(this.onLogged));
}
此处,当观察者方法-this.onLogged
-被注册为可观察时,它将释放方法范围(即this
上下文)。因此,Observable无法调用this.isLogged
方法。将其更改为以下内容,它必须可以工作:
ngOnInit() {
this.subscriptions.push(this.authService.logged.subscribe((value) => {
this.onLogged(value);
}));
}