【问题标题】:ExpressionChangedAfterItHasBeenCheckedError with Angular 6 and redirectExpressionChangedAfterItHasBeenCheckedError 与 Angular 6 和重定向
【发布时间】:2018-09-21 04:15:34
【问题描述】:

我可以看到有很多关于这个主题的帖子,但大多与异步服务调用有关。我有一个负责登录 Azure AD 的应用程序组件。当用户单击登录时,他们将被重定向到 Azure 的登录页面,并被重定向回名为 AuthCallBack 的组件。 AuthCallBack 将调用 AppComponenet 上的一个方法,该方法简单地设置一个名为 userIsLoggedIn 的布尔值,我在 ngIf 中使用它。我收到以下错误 ExpressionChangedAfterItHasBeenCheckedError。因为它不是某种 http 异步调用,所以我没有订阅选项,怎么办?

<table>
  <tr>
    <td routerLink="/">Login page</td>
    <td routerLink="/dashboard">Dashboard</td>
    <td (click)="login()">Login</td>
    <td (click)="logout()">Logout</td>
    <td><span *ngIf="userIsLoggedIn">Logged in</span></td>

  </tr>
  <tr>
    <td colspan="5">
       <router-outlet></router-outlet>
    </td>
  </tr>
</table>

应用组件

import { Component,OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { AdalService } from 'adal-angular4';
import { environment } from '../environments/environment';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {

  config = {
    tenant: 'xx-a8b0-4555-97b3-70001a6a7448',
    clientId: 'xx-65b4-4914-905c-aecc3e9197f5',
    redirectUri: "http://localhost:4200/authcallback/",
    logOutUri: "http://localhost:4200",
    postLogoutRedirectUri: "http://localhost:4200",
    endpoints: {
      "http://localhost:63126/": "xx-65b4-4914-905c-aecc3e9197f5"
    }};

  userIsLoggedIn: Observable<boolean>;

  constructor(private adalService: AdalService,private router: Router)
  {
    this.adalService.init(this.config); 
  }

  ngOnInit() {     
  }

  handleWindowCallback()
  {    
    this.adalService.handleWindowCallback();
    this.userIsLoggedIn = this.adalService.userInfo.authenticated;

  }

  login()
  {   
    this.adalService.login();
  }

  logout()
  {
    this.adalService.logOut();
  }
}

认证组件

import { Component, OnInit, NgZone } from '@angular/core';
import { AppComponent } from '../app.component';
import { Router } from '@angular/router';
import { AdalService } from 'adal-angular4';

@Component({
  selector: 'app-auth-callback',
  templateUrl: './authcallback.component.html',
  styleUrls: ['./authcallback.component.css']
})
export class AuthCallbackComponent implements OnInit {

  constructor(private appComponent: AppComponent,private router: Router, private adalService: AdalService, private _zone: NgZone) { }

   ngOnInit() {

    this.appComponent.handleWindowCallback();

    //this.adalService.handleWindowCallback();

    setTimeout(() => {
      this._zone.run(
        () => this.router.navigate(['/'])
      );
    }, 200);
  } 
}

【问题讨论】:

    标签: angular


    【解决方案1】:

    父组件(appComponent)已经有CD(变更检测)循环,子组件改变父组件的状态。在开发模式下 - 另一张 CD 来检查之前的 CD 周期没有任何变化(将引发错误)。

    我们有一个技巧:

    -在 setTimeout 中换行,更改将应用​​于新的 CD 周期。

    // AuthComponent
    setTimeout(()=>this.appComponent.handleWindowCallback(), 0);
    

    -在父组件中调用 ChangeDetectorRef.detectChanges

    // AppComponent
    constructor(private changeDetectorRef: ChangeDetectorRef){}
    
    handleWindowCallback(){
      /* some code */
      this.changeDetectorRef.detectChanges();
    }
    

    【讨论】:

    • 谢谢,我会尽快测试。为什么是超时部分?
    • 不客气。但是不要过度使用,因为我们会触发额外的 CD 周期,它会影响性能。
    猜你喜欢
    • 1970-01-01
    • 2018-12-27
    • 1970-01-01
    • 2019-07-03
    • 2020-04-03
    • 2018-11-25
    • 2018-02-03
    • 2017-11-07
    • 2019-11-18
    相关资源
    最近更新 更多