ExpressionChangedAfterItHasBeenCheckedError Giải thích


308

Vui lòng giải thích cho tôi tại sao tôi tiếp tục gặp lỗi này: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.

Rõ ràng, tôi chỉ nhận được nó ở chế độ dev, nó không xảy ra trên bản dựng sản xuất của tôi, nhưng nó rất khó chịu và tôi chỉ đơn giản là không hiểu những lợi ích của việc có lỗi trong môi trường dev của tôi sẽ không hiển thị trên prod - -Có thể vì sự thiếu hiểu biết của tôi.

Thông thường, sửa chữa là đủ dễ dàng, tôi chỉ bọc lỗi gây ra mã trong setTimeout như thế này:

setTimeout(()=> {
    this.isLoading = true;
}, 0);

Hoặc buộc phát hiện các thay đổi với hàm tạo như sau constructor(private cd: ChangeDetectorRef) {}::

this.isLoading = true;
this.cd.detectChanges();

Nhưng tại sao tôi liên tục gặp phải lỗi này? Tôi muốn hiểu nó để tôi có thể tránh các bản sửa lỗi này trong tương lai.


Câu trả lời:


121

Tôi đã có một vấn đề tương tự. Nhìn vào tài liệu móc vòng đời , tôi đổi ngAfterViewInitsang ngAfterContentInitvà nó hoạt động.


@PhilipEnc vấn đề của tôi liên quan đến thay đổi được kích hoạt bởi thay đổi DOM. Khi DOM sẽ thay đổi, đối tượng QueryList (xuất phát từ thuộc tính @ContentChildren) sẽ cập nhật và bên trong phương thức mà bản cập nhật gọi nó đã thay đổi thuộc tính ràng buộc hai chiều. Điều này tạo ra vấn đề tôi đang gặp phải. Việc gói mà thay đổi thành hai thuộc tính setTimeoutgiống như bạn hiển thị ở trên đã thực hiện thủ thuật. Cảm ơn!
kbpontius

1
Trong trường hợp của tôi, tôi đã đặt một số mã thay đổi giá trị của mảng lưới Primeng trong ngAfterContentInit, tôi đã đặt mã trong ngOnInit và nó đã hoạt động.
Vibhu

ngAfterContentCheckedhoạt động ở đây trong khi ngAfterContentInitvẫn ném lỗi.
ashubfox

ngAfterContentChecked sử dụng nhưng dự án được tải rất chậm
Ghotekar Rahul

101

Lỗi này cho thấy một vấn đề thực sự trong ứng dụng của bạn, do đó, thật hợp lý khi đưa ra một ngoại lệ.

Trong devModephát hiện thay đổi sẽ thêm một lượt bổ sung sau mỗi lần chạy phát hiện thay đổi thông thường để kiểm tra xem mô hình đã thay đổi chưa.

Nếu mô hình đã thay đổi giữa lượt phát hiện thay đổi thường xuyên và bổ sung, điều này chỉ ra rằng

  • phát hiện thay đổi chính nó đã gây ra một sự thay đổi
  • một phương thức hoặc getter trả về một giá trị khác nhau mỗi lần nó được gọi

cả hai đều xấu, vì không rõ cách tiến hành vì mô hình có thể không bao giờ ổn định.

Nếu Angular chạy phát hiện thay đổi cho đến khi mô hình ổn định, nó có thể chạy mãi mãi. Nếu Angular không chạy phát hiện thay đổi, thì chế độ xem có thể không phản ánh trạng thái hiện tại của mô hình.

Xem thêm Sự khác biệt giữa chế độ sản xuất và phát triển trong Angular2 là gì?


4
Làm thế nào tôi có thể tránh gặp lỗi này trong tương lai? Có cách nào khác tôi cần suy nghĩ về mã của mình để đảm bảo tôi không mắc lỗi tương tự không?
Kevin LeStarge

25
Thông thường, điều này được gây ra bởi một số cuộc gọi lại vòng đời như ngOnInithoặc ngOnChangesđể sửa đổi mô hình (một số cuộc gọi lại vòng đời cho phép sửa đổi mô hình mà người khác không làm, tôi không nhớ chính xác cái nào làm hay không làm). Không liên kết với các phương thức hoặc hàm trong dạng xem, thay vào đó hãy liên kết với các trường và cập nhật các trường trong trình xử lý sự kiện. Nếu bạn phải liên kết với các phương thức, hãy đảm bảo rằng chúng luôn trả về cùng thể hiện giá trị miễn là thực sự không có thay đổi. Phát hiện thay đổi sẽ gọi các phương thức này rất nhiều.
Günter Zöchbauer

Đối với bất kỳ ai đến đây gặp lỗi này khi sử dụng thư viện ngx-toaster, đây là báo cáo lỗi: github.com/scttcper/ngx-toastr/issues/160
rmcsharry

2
Nó không nhất thiết là một vấn đề với ứng dụng. Thực tế rằng gọi changeRef.detectChanges()là một giải pháp / khắc phục lỗi, là bằng chứng của điều này. Nó giống như sửa đổi trạng thái bên trong $scope.$watch()trong Angular 1.
Kevin Beal

1
Tôi không biết Angular 1 quá rõ nhưng thay đổi phát hiện trong Angular 2 hoạt động hoàn toàn khác. Bạn đúng rằng nó không nhất thiết là một vấn đề, nhưng thường cdRef.detectChanges()chỉ cần thiết trong một số trường hợp cạnh kỳ lạ và bạn nên xem xét cẩn thận khi bạn cần nó mà bạn hiểu đúng tại sao.
Günter Zöchbauer

83

Rất nhiều sự hiểu biết đã đến khi tôi hiểu được Vòng đời Angular và mối quan hệ của chúng với phát hiện thay đổi.

Tôi đã cố gắng để Angular cập nhật một lá cờ toàn cầu ràng buộc với *ngIfmột yếu tố và tôi đã cố gắng thay đổi lá cờ đó bên trong ngOnInit()móc vòng đời của một thành phần khác.

Theo tài liệu, phương pháp này được gọi sau khi Angular đã phát hiện ra các thay đổi:

Được gọi một lần, sau ngOnChanges () đầu tiên.

Vì vậy, cập nhật cờ bên trong ngOnChanges()sẽ không bắt đầu phát hiện thay đổi. Sau đó, khi phát hiện thay đổi tự nhiên được kích hoạt lại, giá trị của cờ đã thay đổi và lỗi được đưa ra.

Trong trường hợp của tôi, tôi đã thay đổi điều này:

constructor(private globalEventsService: GlobalEventsService) {

}

ngOnInit() {
    this.globalEventsService.showCheckoutHeader = true;
}

Về điều này:

constructor(private globalEventsService: GlobalEventsService) {
    this.globalEventsService.showCheckoutHeader = true;
}

ngOnInit() {

}

và nó đã khắc phục vấn đề :)


3
Vấn đề của tôi là tương tự. Rằng tôi đã làm sai sau nhiều giờ và xác định một biến bên ngoài hàm ngOnInit và hàm tạo. Điều này nhận được các thay đổi dữ liệu từ một quan sát, được đặt trong chức năng initalization. Đã làm điều tương tự như bạn để sửa lỗi.
ravo10

1
Rất giống nhau xung quanh, nhưng tôi đã cố cuộn ( router.navigate) khi tải đến một đoạn nếu có trong URL. Mã này ban đầu được đặt ở AfterViewInitnơi tôi nhận được lỗi, sau đó tôi di chuyển khi bạn nói với nhà xây dựng nhưng nó không tôn trọng đoạn. Di chuyển đến ngOnInitgiải quyết :) cảm ơn!
Joel Balmer

Điều gì sẽ xảy ra nếu html của tôi bị ràng buộc với thời gian trả về getter là "HH: MM" thông qua get ClockValue () {return DateTime.TimeAMPM (ngày mới ())} cuối cùng nó sẽ ngắt khi phút thay đổi trong khi phát hiện đang chạy, làm sao tôi có thể sửa lỗi này?
Meryan

Tương tự ở đây. Cũng tìm thấy rằng gói vào setInterval()công trình cũng nếu nó cần phải bắn sau mã sự kiện trọn đời khác.
Rick Strahl

39

Cập nhật

Tôi thực sự khuyên bạn nên bắt đầu với phản hồi tự của OP trước tiên: suy nghĩ đúng đắn về những gì có thể được thực hiện trong constructorso với những gì nên được thực hiện ngOnChanges().

Nguyên

Đây là một ghi chú bên cạnh hơn là một câu trả lời, nhưng nó có thể giúp đỡ một ai đó. Tôi đã vấp phải vấn đề này khi cố gắng làm cho sự hiện diện của một nút phụ thuộc vào trạng thái của biểu mẫu:

<button *ngIf="form.pristine">Yo</button>

Theo tôi biết, cú pháp này dẫn đến nút được thêm và xóa khỏi DOM dựa trên điều kiện. Mà lần lượt dẫn đến ExpressionChangedAfterItHasBeenCheckedError.

Cách khắc phục trong trường hợp của tôi (mặc dù tôi không yêu cầu nắm bắt toàn bộ ý nghĩa của sự khác biệt), là sử dụng display: nonethay thế:

<button [style.display]="form.pristine ? 'inline' : 'none'">Yo</button>

6
Sự hiểu biết của tôi về sự khác biệt giữa ng If so với kiểu là ngNếu không bao gồm HTML trong trang cho đến khi điều kiện là đúng, do đó giảm "trọng lượng trang" một chút trong khi kỹ thuật kiểu khiến HTML luôn luôn trong trang và chỉ đơn giản là ẩn hoặc hiển thị dựa trên giá trị của form.pristine.
dùng3785010

4
Bạn cũng có thể sử dụng [hidden]thay vì phần rất dài dòng [style.display]. :)
Philipp Meissner

2
Tại sao không. Mặc dù, như được đề cập bởi @Simon_Weaver trong một bình luận khác trên trang này, [hidden] không phải lúc nào cũng có hành vi tương tự nhưdisplay: none
Arnaud P

1
Tôi đã hiển thị hai nút khác nhau (đăng xuất / đăng nhập) với * ngNếu trong mỗi nút và điều này gây ra sự cố.
GoTo

nhà xây dựng là nơi thích hợp cho tôi, ra mắt một quán ăn nhẹ nguyên liệu
austin

31

Có những câu trả lời thú vị nhưng dường như tôi không tìm thấy câu trả lời nào phù hợp với nhu cầu của mình, gần nhất là từ @ chittrang-mishra, chỉ đề cập đến một chức năng cụ thể chứ không phải một vài chức năng như trong ứng dụng của tôi.

Tôi không muốn sử dụng [hidden]để lợi dụng *ngIfthậm chí không phải là một phần của DOM vì vậy tôi đã tìm ra giải pháp sau đây có thể không phải là tốt nhất cho tất cả vì nó khắc phục lỗi thay vì sửa nó, nhưng trong trường hợp của tôi, tôi biết kết quả cuối cùng là chính xác, có vẻ như ok cho ứng dụng của tôi.

Những gì tôi đã làm là thực hiện AfterViewChecked, thêm constructor(private changeDetector : ChangeDetectorRef ) {}và sau đó

ngAfterViewChecked(){
  this.changeDetector.detectChanges();
}

Tôi hy vọng điều này sẽ giúp người khác như nhiều người khác đã giúp tôi.


3
Điều này sẽ không kích hoạt một vòng lặp phát hiện thay đổi vô hạn? ý tôi là, bạn đang phát hiện những thay đổi sau khi bạn kiểm tra.
Manuel Azar

@ManuelAzar Rõ ràng là không. Đây là giải pháp DUY NHẤT làm việc cho tôi. AT LAST một chút im lặng trong bảng điều khiển của tôi. Tôi đã quá mệt mỏi với tất cả những "lỗi" phát hiện thay đổi không liên quan này.
Jeremy Thille

31

Angular chạy phát hiện thay đổi và khi phát hiện ra rằng một số giá trị được truyền cho thành phần con đã bị thay đổi, Angular đưa ra lỗi:

ExpressionChangedAfterItHasBeenCheckedError bấm vào để biết thêm

Để sửa lỗi này, chúng ta có thể sử dụng AfterContentCheckedmóc vòng đời và

import { ChangeDetectorRef, AfterContentChecked} from '@angular/core';

  constructor(
  private cdref: ChangeDetectorRef) { }

  ngAfterContentChecked() {

    this.cdref.detectChanges();

  }

Mặc dù điều này có thể khắc phục vấn đề, nhưng điều này có quá rộng rãi và quá mức cho CD không?
Nicky

Tôi nghĩ rằng đây là câu trả lời duy nhất giải quyết lỗi này do việc truyền (các) giá trị cho một đứa trẻ. Cảm ơn!
java-nghiện602

@Nicky Có. Mỗi khi bạn chạm vào màn hình, bất cứ nơi nào, ngAfterContentChecked () được gọi
Mert Mertce

25

Trong trường hợp của tôi, tôi đã gặp vấn đề này trong tệp spec của mình, trong khi chạy thử nghiệm.

Tôi phải đổi ngIf sang [hidden]

<app-loading *ngIf="isLoading"></app-loading>

đến

<app-loading [hidden]="!isLoading"></app-loading>


2
Sự khác biệt ở đây là *ngIfthay đổi DOM, thêm và xóa phần tử khỏi trang, trong khi [hidden]thay đổi mức độ hiển thị của mục trong khi không xóa nó khỏi DOM.
Grungondola

5
Nhưng, điều này không thực sự khắc phục vấn đề thực sự ...?
ravo10

23

Thực hiện theo các bước dưới đây:

1. Sử dụng 'ChangeDetectorRef' bằng cách nhập nó từ @ angular / core như sau:

import{ ChangeDetectorRef } from '@angular/core';

2. Triển khai nó trong constructor () như sau:

constructor(   private cdRef : ChangeDetectorRef  ) {}

3. Thêm phương thức sau vào chức năng của bạn mà bạn đang gọi trong một sự kiện như nhấp vào nút. Nó trông như thế này:

functionName() {   
    yourCode;  
    //add this line to get rid of the error  
    this.cdRef.detectChanges();     
}

23

Tôi đã sử dụng ng2-carouselamos (Angular 8 & Bootstrap 4)

Dưới đây đã khắc phục vấn đề của tôi:

Tôi đã làm gì:

1. implement AfterViewChecked,  
2. add constructor(private changeDetector : ChangeDetectorRef ) {} and then 
3. ngAfterViewChecked(){ this.changeDetector.detectChanges(); }

Nó đã giúp đỡ. Kinh ngạc!!
Pathik Vejani

Bạn đã cứu ngày của tôi ... Cảm ơn!
omostan

19

Tôi đã phải đối mặt với cùng một vấn đề vì giá trị đã thay đổi ở một trong các mảng trong thành phần của tôi. Nhưng thay vì phát hiện các thay đổi về thay đổi giá trị, tôi đã thay đổi chiến lược phát hiện thay đổi thành phần thành onPush(sẽ phát hiện các thay đổi khi thay đổi đối tượng và không thay đổi giá trị).

import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';

@Component({
    changeDetection: ChangeDetectionStrategy.OnPush
    selector: -
    ......
})

Điều này dường như hoạt động để thêm / xóa khỏi các điều khiển một cách linh hoạt .. có bất kỳ nhược điểm nào không?
Ricardo Saracino

Hoạt động như một cơ duyên trong tình huống tôi có trong tay, cảm ơn! Một thành phần được liên kết với một đối tượng "toàn cầu" đã bị thay đổi ở nơi khác và gây ra Lỗi xảy ra. Thành phần này đã có trình xử lý cập nhật khi đối tượng bị ràng buộc được cập nhật, trình xử lý sự kiện này bây giờ gọi changeDetectorRef.detectChanges () kết hợp với ChangeDetectionStrargety.OnPush điều này hoạt động như mong muốn mà không gặp lỗi.
Bernoulli IT

@RicardoSaracino bạn có thấy nhược điểm nào không? Tôi đã tự hỏi điều tương tự. Tôi biết cách phát hiện thay đổi OnPush hoạt động, nhưng tự hỏi liệu có một Gotcha mà có lẽ tôi đang thiếu. Tôi không muốn phải quay lại.
mtpultz

@RicardoSaracino, Vâng, nó có một số nhược điểm, bạn có thể tham khảo liên kết chi tiết này blog.angular-university.io/onpush-change-detection-how-it-works
Dheeraj

@BernoulliIT Cảm ơn, tôi rất vui vì nó hiệu quả với bạn.
Dheeraj

17

Tham khảo bài viết https://blog.angularindepth.com/everything-you-need-to-ledge-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4

Vì vậy, các cơ chế đằng sau phát hiện thay đổi thực sự hoạt động theo cách mà cả hai quá trình phát hiện và xác minh thay đổi được thực hiện đồng bộ. Điều đó có nghĩa là, nếu chúng tôi cập nhật các thuộc tính không đồng bộ, các giá trị sẽ không được cập nhật khi vòng xác minh đang chạy và chúng tôi sẽ không gặp ExpressionChanged...lỗi. Lý do chúng tôi nhận được lỗi này là, trong quá trình xác minh, Angular thấy các giá trị khác nhau sau đó là những gì nó đã ghi lại trong giai đoạn phát hiện thay đổi. Vì vậy, để tránh điều đó ....

1) Sử dụng thay đổiDetectorRef

2) sử dụng setTimeOut. Điều này sẽ thực thi mã của bạn trong một VM khác dưới dạng một tác vụ macro. Angular sẽ không thấy những thay đổi này trong quá trình xác minh và bạn sẽ không gặp phải lỗi đó.

 setTimeout(() => {
        this.isLoading = true;
    });

3) Nếu bạn thực sự muốn thực thi mã của mình trên cùng một VM, hãy sử dụng như

Promise.resolve(null).then(() => this.isLoading = true);

Điều này sẽ tạo ra một nhiệm vụ vi mô. Hàng đợi tác vụ vi mô được xử lý sau khi mã đồng bộ hiện tại đã thực hiện xong do đó việc cập nhật lên thuộc tính sẽ xảy ra sau bước xác minh.


Bạn có thể sử dụng tùy chọn # 3 với biểu thức kiểu không? Tôi có một biểu thức kiểu cho chiều cao nên được đánh giá sau cùng, bởi vì nó dựa trên nội dung được tiêm.
N-ate

1
Xin lỗi chỉ cần xem bình luận của bạn, yea tôi không thấy lý do tại sao không. Vì vậy, nên làm việc với sự thay đổi phong cách là tốt.
ATHER

4

@HostBinding có thể là một nguồn gây nhầm lẫn của lỗi này.

Ví dụ: giả sử bạn có ràng buộc máy chủ sau trong một thành phần

// image-carousel.component.ts
@HostBinding('style.background') 
style_groupBG: string;

Để đơn giản, giả sử thuộc tính này được cập nhật thông qua thuộc tính đầu vào sau:

@Input('carouselConfig')
public set carouselConfig(carouselConfig: string) 
{
    this.style_groupBG = carouselConfig.bgColor;   
}

Trong thành phần cha, bạn đang lập trình cài đặt nó trong ngAfterViewInit

@ViewChild(ImageCarousel) carousel: ImageCarousel;

ngAfterViewInit()
{
    this.carousel.carouselConfig = { bgColor: 'red' };
}

Đây là những gì xảy ra:

  • Thành phần cha mẹ của bạn được tạo
  • Thành phần ImageCarousel được tạo và được gán cho carousel(thông qua ViewChild)
  • Chúng tôi không thể truy cập carouselcho đến khi ngAfterViewInit()(nó sẽ là null)
  • Chúng tôi chỉ định cấu hình, bộ nào style_groupBG = 'red'
  • Điều này lần lượt đặt background: redtrên thành phần ImageCarousel của máy chủ
  • Thành phần này được 'sở hữu' bởi thành phần chính của bạn, vì vậy khi kiểm tra các thay đổi, nó sẽ tìm thấy một sự thay đổi carousel.style.backgroundvà không đủ thông minh để biết rằng đây không phải là vấn đề nên nó ném ngoại lệ.

Một giải pháp là giới thiệu một trình bao bọc div khác là ImageCarousel và đặt màu nền cho nó, nhưng sau đó bạn không nhận được một số lợi ích của việc sử dụng HostBinding(chẳng hạn như cho phép cha mẹ kiểm soát toàn bộ giới hạn của đối tượng).

Giải pháp tốt hơn, trong thành phần cha mẹ là thêm DetChanges () sau khi thiết lập cấu hình.

ngAfterViewInit()
{
    this.carousel.carouselConfig = { ... };
    this.cdr.detectChanges();
}

Điều này có thể trông khá rõ ràng được đặt ra như thế này, và rất giống với các câu trả lời khác nhưng có một sự khác biệt tinh tế.

Hãy xem xét trường hợp bạn không thêm @HostBindingvào sau này trong quá trình phát triển. Đột nhiên bạn nhận được lỗi này và nó dường như không có ý nghĩa gì.


2

Đây là suy nghĩ của tôi về những gì đang xảy ra. Tôi chưa đọc tài liệu nhưng chắc chắn đây là một phần lý do tại sao lỗi được hiển thị.

*ngIf="isProcessing()" 

Khi sử dụng * ngNếu, nó sẽ thay đổi vật lý DOM bằng cách thêm hoặc xóa phần tử mỗi khi điều kiện thay đổi. Vì vậy, nếu điều kiện thay đổi trước khi nó được hiển thị cho chế độ xem (rất có thể xảy ra trong thế giới của Angular), lỗi sẽ bị ném. Xem giải thích ở đây giữa chế độ phát triển và sản xuất.

[hidden]="isProcessing()"

Khi sử dụng, [hidden]nó không thay đổi về mặt vật lý DOMmà chỉ che giấu elementkhỏi tầm nhìn, rất có thể là sử dụng CSSở phía sau. Phần tử vẫn còn trong DOM nhưng không hiển thị tùy thuộc vào giá trị của điều kiện. Đó là lý do tại sao lỗi sẽ không xảy ra khi sử dụng [hidden].


Nếu isProcessing()đang làm việc này, bạn phải sử dụng !isProcessing()cho[hidden]
Matthieu Charbonnier

hiddenkhông "sử dụng CSS ở phía sau", đó là một thuộc tính HTML thông thường. developer.mozilla.org/en-US/docs/Web/HTML/Global_attribut/
triệt

1

Đối với vấn đề của tôi, tôi đã đọc github - "ExpressionChangedAfterItHasBeenCheckedError khi thay đổi giá trị thành phần 'không phải mô hình' trong afterViewInit" và quyết định thêm ngModel

<input type="hidden" ngModel #clientName />

Nó đã khắc phục vấn đề của tôi, tôi hy vọng nó sẽ giúp được ai đó.


1
Nơi nào trên trang web đó nó nói để thêm ngModel. Và bạn có thể vui lòng giải thích tại sao điều này sẽ hữu ích?
Peter Wippermann

Khi tôi đang theo dõi vấn đề này, nó đã dẫn tôi điều tra liên kết. Sau khi đọc bài viết tôi đã thêm thuộc tính và nó đã khắc phục vấn đề của tôi. Nó rất hữu ích nếu ai đó gặp phải vấn đề tương tự.
Demodave

1

Mẹo gỡ lỗi

Lỗi này có thể khá khó hiểu và thật dễ dàng để đưa ra một giả định sai về chính xác khi nó xảy ra. Tôi thấy hữu ích khi thêm rất nhiều câu lệnh gỡ lỗi như thế này trong suốt các thành phần bị ảnh hưởng ở những nơi thích hợp. Điều này giúp hiểu được dòng chảy.

Trong phần cha mẹ đặt các câu lệnh như thế này (chuỗi chính xác 'EXPRESSIONCHANGED' là quan trọng), nhưng ngoài ra đây chỉ là những ví dụ:

    console.log('EXPRESSIONCHANGED - HomePageComponent: constructor');
    console.log('EXPRESSIONCHANGED - HomePageComponent: setting config', newConfig);
    console.log('EXPRESSIONCHANGED - HomePageComponent: setting config ok');
    console.log('EXPRESSIONCHANGED - HomePageComponent: running detectchanges');

Trong cuộc gọi lại con / dịch vụ / hẹn giờ:

    console.log('EXPRESSIONCHANGED - ChildComponent: setting config');
    console.log('EXPRESSIONCHANGED - ChildComponent: setting config ok');

Nếu bạn chạy detectChangesthủ công thêm đăng nhập cho điều đó quá:

    console.log('EXPRESSIONCHANGED - ChildComponent: running detectchanges');
    this.cdr.detectChanges();

Sau đó, trong trình gỡ lỗi Chrome, chỉ cần lọc theo 'EXPRESSIONCHANGES'. Điều này sẽ cho bạn thấy chính xác dòng chảy và thứ tự của tất cả mọi thứ được thiết lập, và cũng chính xác tại điểm mà Angular ném lỗi.

nhập mô tả hình ảnh ở đây

Bạn cũng có thể nhấp vào các liên kết màu xám để đặt điểm dừng.

Một điều khác để xem nếu bạn có các thuộc tính được đặt tên tương tự trong ứng dụng của mình (chẳng hạn như style.background), hãy đảm bảo bạn đang gỡ lỗi cho thuộc tính bạn nghĩ - bằng cách đặt nó thành giá trị màu tối nghĩa.


1

Trong trường hợp của tôi, tôi đã có một thuộc tính không đồng bộ LoadingServicevới một BehavioralSubjectisLoading

Sử dụng mô hình [hidden] hoạt động, nhưng * ngNếu thất bại

    <h1 [hidden]="!(loaderService.isLoading | async)">
        THIS WORKS FINE
        (Loading Data)
    </h1>

    <h1 *ngIf="!(loaderService.isLoading | async)">
        THIS THROWS ERROR
        (Loading Data)
    </h1>

1

Một giải pháp hiệu quả với tôi khi sử dụng rxjs

import { startWith, tap, delay } from 'rxjs/operators';

// Data field used to populate on the html
dataSource: any;

....

ngAfterViewInit() {
  this.yourAsyncData.
      .pipe(
          startWith(null),
          delay(0),
          tap((res) => this.dataSource = res)
      ).subscribe();
}

mã có vấn đề là gì? giải pháp ở đây là gì?
mkb

Xin chào @mkb, sự cố đã ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.xảy ra khi thay đổi giá trị được kích hoạt khi DOM thay đổi
Sandeep K Nair

Xin chào, ý tôi là bạn đã làm gì ở đây để khắc phục vấn đề. Bạn hoàn toàn không sử dụng rxjs hoặc thêm delay () hoặc thêm startWith ()? Tôi đã sử dụng rxjs với các phương thức rxjs khác nhau nhưng vẫn gặp lỗi, tôi hy vọng sẽ giải quyết được lỗi lầm :(
mkb

Việc thêm vào delaylàm cho lỗi đi. Nó hoạt động tương tự như setTimeout.
Lazar Ljubenović

1

Tôi đã có loại lỗi này trong Ionic3 (sử dụng Angular 4 như một phần của ngăn xếp công nghệ của nó).

Đối với tôi nó đã làm điều này:

<ion-icon [name]="getFavIconName()"></ion-icon>

Vì vậy, tôi đã cố gắng thay đổi một cách có điều kiện loại biểu tượng ion từ a pinsang a remove-circle, trên một chế độ mà màn hình đang hoạt động.

Tôi đoán tôi sẽ phải thêm một *ngIfthay thế.


1

Vấn đề của tôi là rõ ràng khi tôi thêm *ngIfnhưng đó không phải là nguyên nhân. Lỗi xảy ra do thay đổi mô hình trong {{}}các thẻ sau đó cố gắng hiển thị mô hình đã thay đổi trong *ngIfcâu lệnh sau này. Đây là một ví dụ:

<div>{{changeMyModelValue()}}</div> <!--don't do this!  or you could get error: ExpressionChangedAfterItHasBeenCheckedError-->
....
<div *ngIf="true">{{myModel.value}}</div>

Để khắc phục vấn đề, tôi đã thay đổi nơi tôi gọi changeMyModelValue()đến một nơi có ý nghĩa hơn.

Trong tình huống của tôi, tôi muốn changeMyModelValue()gọi bất cứ khi nào một thành phần con thay đổi dữ liệu. Điều này yêu cầu tôi tạo và phát ra một sự kiện trong thành phần con để phụ huynh có thể xử lý nó (bằng cách gọi changeMyModelValue(). Xem https://angular.io/guide/component-interaction#parent-listens-for-child-event


0

Tôi hy vọng điều này sẽ giúp ai đó đến đây: Chúng tôi thực hiện các cuộc gọi dịch vụ ngOnInittheo cách sau và sử dụng một biến displayMainđể điều khiển Gắn các phần tử vào DOM.

thành phần

  displayMain: boolean;
  ngOnInit() {
    this.displayMain = false;
    // Service Calls go here
    // Service Call 1
    // Service Call 2
    // ...
    this.displayMain = true;
  }

và thành phần.html

<div *ngIf="displayMain"> <!-- This is the Root Element -->
 <!-- All the HTML Goes here -->
</div>

0

Tôi đã gặp lỗi này vì tôi đang sử dụng một biến trong thành phần.html không được khai báo trong thành phần. Khi tôi xóa phần trong HTML, lỗi này đã biến mất.


0

Tôi đã gặp lỗi này vì tôi đã gửi các hành động redux theo phương thức và phương thức không được mở tại thời điểm đó. Tôi đã gửi các hành động thành phần phương thức nhận được đầu vào. Vì vậy, tôi đặt setTimeout ở đó để đảm bảo rằng chế độ được mở và sau đó các hành động được nhúng.


0

Để bất cứ ai đấu tranh với điều này. Đây là một cách để gỡ lỗi chính xác lỗi này: https://blog.angular-university.io/angular-debugging/

Trong trường hợp của tôi, thực sự tôi đã thoát khỏi lỗi này bằng cách sử dụng bản hack [hidden] này thay vì * ng If ...

Nhưng liên kết tôi cung cấp cho phép tôi tìm HƯỚNG DẪN * ngNếu :)

Thưởng thức.


Sử dụng hiddenthay vì ngIfkhông phải là hack, cũng không giải quyết được cốt lõi của vấn đề. Bạn chỉ đang che giấu vấn đề đi.
Lazar Ljubenović

-2

Giải pháp ... dịch vụ và rxjs ... trình phát sự kiện và ràng buộc thuộc tính đều sử dụng rxjs..bạn nên tự mình thực hiện nó, kiểm soát nhiều hơn, dễ gỡ lỗi hơn. Hãy nhớ rằng các trình phát sự kiện đang sử dụng rxjs. Đơn giản, tạo một dịch vụ và trong phạm vi có thể quan sát, yêu cầu từng thành phần đăng ký vào người quan sát và chuyển giá trị mới hoặc giá trị cosume khi cần


1
Không chỉ điều này không trả lời câu hỏi, đó cũng là lời khuyên khủng khiếp. Các bạn, xin đừng tự mình thực hiện lại rxjs chỉ vì bạn đang gặp phải lỗi CD của Angular. :)
Lazar Ljubenović
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.