角度2 ngIf是否可观察到? [英] angular 2 ngIf with observable?
问题描述
我有一个非常简单的服务,它的工作是从api/authenticate url获取200或401.
I have a very simple service and its job is to get either 200 or 401 from api/authenticate url.
auth.service.ts
auth.service.ts
@Injectable()
export class AuthService {
constructor(private http: Http) {
}
authenticateUser(): Observable<any> {
return this.http.get(AppSettings.authenitcationEnpoint)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(response: Response) {
let body = response;
return body || {};
}
private handleError(error: Response) {
let errMsg: string;
if (error instanceof Response) {
errMsg = `${error.status} - ${error.statusText || ''}`;
} else {
errMsg = error.toString();
}
return Observable.throw(errMsg);
}
}
现在我想在html中使用它,我知道我可以创建一个订阅服务器,并根据响应或错误代码设置一个变量,但是我的问题是我将不得不在各处重复代码.我想要很简单
now I want to use this in my html I know I can create a subscriber and based on response or error code set a variable but my problem is I will have to duplicate the code all over the place. I want very simple
<div *ngIf="authService.AuthenticateUser()">my content</div>
如果它的401来自handleError,则将其隐藏,否则显示div.
If its 401 which is coming from handleError then hide otherwise show the div.
这就像从Observable获取布尔值一样.我也有AuthGuard.
Its like getting boolean value from Observable. I also have AuthGuard.
authguard.ts
authguard.ts
@Injectable()
export class AuthGuard implements CanActivate {
private isActive: boolean = true;
constructor(private authService: AuthService, private router: Router) {
}
canActivate(): boolean {
this.authService.authenticateUser()
.subscribe(() => {},
error => {
if (error.indexOf("401") >= 0) {
let link = ['contactus'];
this.router.navigate(link);
this.isActive = false;
}
});
return this.isActive;
}
}
我不能同时在ngIf中使用authGuard.canActive().有没有更简单的方法可以做到这一点而又无需重复代码.我很确定AuthGuard不能正常工作,因为每次订阅都必须花费时间,因此每次必须返回true.
I cannot use authGuard.canActive() as well in ngIf. Is there any easier way to do it without duplicating code. I am pretty sure AuthGuard is not working as it must return true everytime because subscribe will take time.
app.component.ts
app.component.ts
export class AppComponent {
private isAuthenticated: boolean = false;
constructor(private authService: AuthService,private authGuard: AuthGuard) {
this.authService.authenticateUser()
.subscribe(response => {
if (response.status == 200)
this.isAuthenticated = true;
},
error => {
if (error.indexOf("401") >= 0)
this.isAuthenticated = false;
});
}
}
home.component.ts
home.component.ts
export class HomeComponent implements OnInit {
constructor(private http: Http, private authService: AuthService, private utilityService: UtilityService, private homeService: HomeService, private factoryService: FactoryService, private supplierService: SupplierService, private businessAreaService: BusinessAreaService, private router: Router) {
this.authService.authenticateUser()
.subscribe(response => {
if (response.status == 200)
this.isAuthenticated = true;
},
error => {
if (error.indexOf("401") >= 0)
this.isAuthenticated = false;
});
this.customData = new CustomData(http);
}
}
您会看到很多重复的代码.我正在努力避免重复.
As you can see alot of duplicated code. I am trying to avoid duplication.
当我调用我的api时,会出现一个弹出窗口,用于输入Windows身份验证的Windows用户名/密码.在取消取消弹出窗口之前,我不会得到401.所以我想隐藏菜单+ home组件.
When I call my api a pop up appears to enter windows username/password for windows Authentication. I dont get 401 until I cancel that pop up. so I want to hide my menu + home component.
在我的服务中,我收到了地图中的回复:200 和未经授权:在 catch 阻止
In my service I get response:200 in map and unauthorized:401 in catch block
推荐答案
在这里,您返回的是可观察值,而不是值:
Here, you are returning an observable and not the value:
authenticateUser(): Observable<any> {
return this.http.get(AppSettings.authenitcationEnpoint)
.map(this.extractData)
.catch(this.handleError);
}
您应该做的是在服务中创建一个属性,然后在html中使用该属性,而不是预订可观察对象的函数.像这样:
What you should do is create a property in your service and then use this property in your html and not the function that subscribes to the observable. Something like:
@Injectable()
export class AuthService {
isAuthenticated: boolean = false; //The variable
constructor(private http: Http) {
}
authenticateUser(): Observable<any> {
return this.http.get(AppSettings.authenitcationEnpoint)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(response: Response) {
let body = response;
this.isAuthenticated = body.isAuthenticated; //here you assign a value to variable
return body || {};
}
private handleError(error: Response) {
let errMsg: string;
if (error instanceof Response) {
errMsg = `${error.status} - ${error.statusText || ''}`;
} else {
errMsg = error.toString();
}
return Observable.throw(errMsg);
}
}
然后,在您的html中,只需使用:
And then, in your html, just use:
<div *ngIf="authService.isAuthenticated">my content</div>
执行此操作的另一种方法是使用async
管道.因此,视图将在生成摘要层之前等待观察返回.像这样:
Another way of doing this is using the async
pipe. So, the view will wait the observation to return before make digest cicle. Something like:
<div *ngIf="authService.AuthenticateUser() | async">my content</div> // Here you use the async pipe
这篇关于角度2 ngIf是否可观察到?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!