angular 2 个订阅值更改未反映在 html
angular 2 subscribe value change not reflecting on html
这让我很困惑。我可能不太了解订阅的运作方式。
Angular 2定稿版
目标:Hide/Show 基于角色的导航菜单
方法:我使用 Facebook 来验证用户。身份验证后,将检索用户角色并用于确定是否应显示管理菜单。使用 true 进行 observable.next 调用,导航栏组件订阅将拾取标志并将 isAdmin 更改为 true。(isAdmin 首先是 false)这将允许显示管理菜单。
问题:true 标志被订阅者正确拾取并且 isAdmin 设置为 true。但是,管理菜单没有显示。
navbar.component.ts
@Component({
selector: 'as-navbar',
templateUrl: 'app/shared/navbar/navbar.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class NavbarComponent {
@Input() brand: string;
public isAdmin:boolean;
constructor(private _securityService:SecurityService){
let self = this;
this._securityService.isAdminObservable.subscribe(function (flag) {
this.isAdmin = flag;
console.log('subscribe received on navbar');
}.bind(this));
}
}
navbar.html
<li class="dropdown" *ngIf="isAdmin">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Admin<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a [routerLink]="['/campaigns']">Campaigns</a></li>
<li><a [routerLink]="['/products']">Products</a></li>
<li><a [routerLink]="['/products']">Reports</a></li>
</ul>
</li>
app.component.ts
constructor(private _http: Http, private _jsonp: Jsonp, private _securityService:SecurityService) {
this.appBrand = CONSTANTS.MAIN.APP.BRAND;
let self = this;
setInterval(function(){
self._securityService.setAdminStatus(true);
console.log('set from app component');
}, 5000)
}
security.service.ts
@Injectable()
export class SecurityService{
public isAdmin:Subject<boolean>=new Subject<boolean>();
public isAdminObservable = this.isAdmin.asObservable();
constructor(){}
setAdminStatus(flag){
this.isAdmin.next(flag);
}
}
这有什么问题吗?或者有更好的方法来实现目标?
任何建议将不胜感激!
谢谢
更新
根据 peeskillet 提供的答案,我从组件中删除了 changeDetection 行并且它起作用了。
但是,当我进一步处理代码时,我会移动
self._securityService.setAdminStatus(isAdmin);
到另一个服务(在本例中为 Facebook 服务)并从应用程序组件调用该服务。 navbar.compoenent.ts 中的订阅确实获取了更改,但没有触发更改检测。我必须手动触发检测才能使其工作。
已更新navbar.component.ts
@Component({
selector: 'as-navbar',
templateUrl: 'app/shared/navbar/navbar.html'
})
export class NavbarComponent {
@Input() brand: string;
public isAdmin:boolean=false;
constructor(private _securityService:SecurityService, private cdr: ChangeDetectorRef){
this._securityService.isAdminObservable.subscribe(function (flag) {
this.isAdmin = flag;
this.cdr.detectChanges();
console.log('subscribe received on navbar');
}.bind(this));
}
}
已更新app.component.ts
@Component({
selector: 'as-main-app',
templateUrl: 'app/app.html'
})
export class AppComponent {
public appBrand: string;
constructor(private _http: Http,
private _facebookService:FacebookService
) {
this.appBrand = CONSTANTS.MAIN.APP.BRAND;
this._facebookService.GetLoginStatus();
}
}
这很有趣。显然,我需要更多地了解 angular 2 变化检测。如果有人知道好的参考,请与我分享。
谢谢!!
这是因为您正在使用 changeDetection: ChangeDetectionStrategy.OnPush
。这意味着仅当 @Input
s 输入更改时才会发生组件的更改检测1.
因此,如果您删除 @Component.changeDetection
,它应该可以工作。
如果您的目标是保持 OnPush
策略,那么一种选择是使用 ChangeDetectorRef
class SomeComponent {
message;
constructor(private service: Service, private cdr: ChangeDetectorRef) {
}
ngOnInit() {
this.service.subscribe(data => {
this.message = data;
this.cdr.detectChanges();
})
}
}
1 - 另见
这让我很困惑。我可能不太了解订阅的运作方式。
Angular 2定稿版
目标:Hide/Show 基于角色的导航菜单 方法:我使用 Facebook 来验证用户。身份验证后,将检索用户角色并用于确定是否应显示管理菜单。使用 true 进行 observable.next 调用,导航栏组件订阅将拾取标志并将 isAdmin 更改为 true。(isAdmin 首先是 false)这将允许显示管理菜单。
问题:true 标志被订阅者正确拾取并且 isAdmin 设置为 true。但是,管理菜单没有显示。
navbar.component.ts
@Component({
selector: 'as-navbar',
templateUrl: 'app/shared/navbar/navbar.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class NavbarComponent {
@Input() brand: string;
public isAdmin:boolean;
constructor(private _securityService:SecurityService){
let self = this;
this._securityService.isAdminObservable.subscribe(function (flag) {
this.isAdmin = flag;
console.log('subscribe received on navbar');
}.bind(this));
}
}
navbar.html
<li class="dropdown" *ngIf="isAdmin">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Admin<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a [routerLink]="['/campaigns']">Campaigns</a></li>
<li><a [routerLink]="['/products']">Products</a></li>
<li><a [routerLink]="['/products']">Reports</a></li>
</ul>
</li>
app.component.ts
constructor(private _http: Http, private _jsonp: Jsonp, private _securityService:SecurityService) {
this.appBrand = CONSTANTS.MAIN.APP.BRAND;
let self = this;
setInterval(function(){
self._securityService.setAdminStatus(true);
console.log('set from app component');
}, 5000)
}
security.service.ts
@Injectable()
export class SecurityService{
public isAdmin:Subject<boolean>=new Subject<boolean>();
public isAdminObservable = this.isAdmin.asObservable();
constructor(){}
setAdminStatus(flag){
this.isAdmin.next(flag);
}
}
这有什么问题吗?或者有更好的方法来实现目标? 任何建议将不胜感激! 谢谢
更新
根据 peeskillet 提供的答案,我从组件中删除了 changeDetection 行并且它起作用了。
但是,当我进一步处理代码时,我会移动
self._securityService.setAdminStatus(isAdmin);
到另一个服务(在本例中为 Facebook 服务)并从应用程序组件调用该服务。 navbar.compoenent.ts 中的订阅确实获取了更改,但没有触发更改检测。我必须手动触发检测才能使其工作。
已更新navbar.component.ts
@Component({
selector: 'as-navbar',
templateUrl: 'app/shared/navbar/navbar.html'
})
export class NavbarComponent {
@Input() brand: string;
public isAdmin:boolean=false;
constructor(private _securityService:SecurityService, private cdr: ChangeDetectorRef){
this._securityService.isAdminObservable.subscribe(function (flag) {
this.isAdmin = flag;
this.cdr.detectChanges();
console.log('subscribe received on navbar');
}.bind(this));
}
}
已更新app.component.ts
@Component({
selector: 'as-main-app',
templateUrl: 'app/app.html'
})
export class AppComponent {
public appBrand: string;
constructor(private _http: Http,
private _facebookService:FacebookService
) {
this.appBrand = CONSTANTS.MAIN.APP.BRAND;
this._facebookService.GetLoginStatus();
}
}
这很有趣。显然,我需要更多地了解 angular 2 变化检测。如果有人知道好的参考,请与我分享。
谢谢!!
这是因为您正在使用 changeDetection: ChangeDetectionStrategy.OnPush
。这意味着仅当 @Input
s 输入更改时才会发生组件的更改检测1.
因此,如果您删除 @Component.changeDetection
,它应该可以工作。
如果您的目标是保持 OnPush
策略,那么一种选择是使用 ChangeDetectorRef
class SomeComponent {
message;
constructor(private service: Service, private cdr: ChangeDetectorRef) {
}
ngOnInit() {
this.service.subscribe(data => {
this.message = data;
this.cdr.detectChanges();
})
}
}
1 - 另见