角度 2 订阅值更改未反映在 html 上

Posted

技术标签:

【中文标题】角度 2 订阅值更改未反映在 html 上【英文标题】:angular 2 subscribe value change not reflecting on html 【发布时间】:2017-02-17 00:27:06 【问题描述】:

这让我很困惑。我可能对订阅的工作原理没有深入了解。

Angular 2 最终版

目标:根据角色隐藏/显示导航菜单 方法:我使用 Facebook 来验证用户。身份验证后,将检索用户角色并用于确定是否应显示管理菜单。使用 true 进行 observable.next 调用,导航栏组件订阅将拾取标志并将 isAdmin 更改为 true。(开始时 isAdmin 为 false)这将允许显示 Admin 菜单。

问题:订阅者正确选择了 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();
    

这很有趣。显然,我需要了解更多关于角度 2 变化检测的信息。如果有人知道好的参考,请与我分享。

谢谢!!

【问题讨论】:

【参考方案1】:

这是因为您使用的是changeDetection: ChangeDetectionStrategy.OnPush。这意味着仅当 @Inputs 的输入发生更改时才会对组件进行更改检测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 - 另见ChangeDetectionStrategy.OnPush and Observable.subscribe in Angular 2

【讨论】:

这太棒了!感谢您的回答。我删除了 changeDetection: ChangeDetectionStrategy.OnPush 并且代码有效!有趣的是。我将逻辑移到另一个服务中。(Facebook 服务)当 Facebook 返回用户信息时,我从数据库中获取角色,然后是 next() 标志。订阅者选择了它,但未检测到更改。我仍然必须手动触发 changeDetection 才能让它工作。我想知道为什么。我已经更新了代码。 是的,我不确定。 关于您在帖子底部的评论,here's a great reference subscribe() 块中的Angular 9 下,我还必须使用detectChanges() 方法调用来触发更改检测并刷新视图。

以上是关于角度 2 订阅值更改未反映在 html 上的主要内容,如果未能解决你的问题,请参考以下文章

角度内插值未在订阅时更新

订阅角度时无法在 ngoninit 中获得价值

订阅的角度限制发射

未捕获淘汰订阅功能关闭

更改现有定期付款的 woocommerce 订阅率

通量控制器视图未订阅商店中的事件更改