구성 요소 속성이 현재 날짜/시간에 따라 달라지는 경우 Angular2 "체크된 후 식이 변경되었습니다" 예외를 관리하는 방법
내 구성 요소의 스타일은 현재 날짜/시간에 따라 다릅니다.내 컴포넌트에는 다음과 같은 기능이 있습니다.
private fontColor( dto : Dto ) : string {
// date d'exécution du dto
let dtoDate : Date = new Date( dto.LastExecution );
(...)
let color = "hsl( " + hue + ", 80%, " + (maxLigness - lightnessAmp) + "%)";
return color;
}
lightnessAmp
는 현재 날짜/시간에서 계산됩니다.이 변하다, 변하다, 변하다, .dtoDate
24일
정확한 오류는 다음과 같습니다.
선택한 후 식이 변경되었습니다.이전 값: 'hsl(123, 80%, 49%)'현재 값: 'hsl(123, 80%, 48%)'
값이 확인되는 순간에만 개발 모드에서 예외가 나타나는 것을 알고 있습니다.선택한 값이 업데이트된 값과 다를 경우 예외가 느려집니다.
그래서 예외를 방지하기 위해 다음 후크 방식으로 각 라이프사이클에서 현재 날짜/시간을 업데이트하려고 했습니다.
ngAfterViewChecked()
{
console.log( "! changement de la date du composant !" );
this.dateNow = new Date();
}
...하지만 성공하지 못했다.
변경 후 변경 검출을 명시적으로 실행합니다.
import { ChangeDetectorRef } from '@angular/core';
constructor(private cdRef:ChangeDetectorRef) {}
ngAfterViewChecked()
{
console.log( "! changement de la date du composant !" );
this.dateNow = new Date();
this.cdRef.detectChanges();
}
TL;DR
ngAfterViewInit() {
setTimeout(() => {
this.dateNow = new Date();
});
}
이것은 회피책이지만, 이 문제를 더 나은 방법으로 해결하는 것이 매우 어려울 수 있습니다.이 방법을 사용하고 있다면, 자신을 비난하지 말아 주세요.괜찮아요.
예:첫 번째 문제 [link], 해결 방법setTimeout()
[링크]
회피 방법
으로 이 에서도) 합니다.ngAfterViewInit
첫 은 스스로에게 - 는 '없어도 살 수 ?'ngAfterViewInit
어디론가 ngAfterViewChecked
대안이 될 수 있습니다.)
예: [link]
또한.
인 것도 요.ngAfterViewInit
을 사용하다, 하다, 하다, 하다, 하다를 통해서도 할 수 있습니다.setTimeout
'어느 정도'를 추가해 .delay(0)
다음 중 하나:
ngAfterViewInit() {
this.foo$
.pipe(delay(0)) //"delay" here is an alternative to setTimeout()
.subscribe();
}
예: [link]
좋은 읽을거리
이 디버깅 방법 및 발생 원인에 대한 좋은 문서: link
여기 두 가지 해결책이 있습니다!
1. Change Detection Strategy를 On Push로 변경합니다.
이 솔루션에서는 기본적으로 각도가 다음과 같습니다.
변경사항 확인 중지.필요하다고 판단될 때만 변경사항 확인
' 수정'을 해서 '성분 수정'을 하면 .ChangeDetectionStrategy.OnPush
음음음같 뭇매하다
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent implements OnInit {
// ...
}
이것 때문에 일이 더 이상 안 되는 것 같아요.이 '앵글'을 ''이라고 부르도록 하겠습니다.detectChanges()
수동으로 조작할 수 있습니다.
this.cdr.detectChanges();
관심있으시면 이 기사를 확인해주세요.그 덕분에 제가 어떻게ChangeDetectionStrategy
2. Expression Changed After It Has Been Checked Error에 대해서
이 문제에 관한 비디오를 확인해 주세요(좋습니다!).또, 이 에러의 원인에 관한 이 기사의 작은 발췌를 소개합니다.이것을 이해하는 데 도움이 되는 부분만을 포함하려고 했습니다.
전문은 여기에 표시된 모든 포인트에 대한 실제 코드 예를 보여 줍니다.
근본 원인은 각도 라이프 사이클입니다.
각 작업 후 Angular는 작업을 수행하는 데 사용된 값을 기억합니다.컴포넌트 뷰의 oldValues 속성에 저장됩니다.
모든 구성 요소에 대한 검사가 수행된 후 Angular가 다음 다이제스트 사이클을 시작하지만 작업을 수행하는 대신 현재 값을 이전 다이제스트 사이클에서 기억하는 값과 비교합니다.
다이제스트 사이클에 따라 다음 작업이 확인되고 있습니다.
하위 구성요소로 전달되는 값이 현재 이러한 구성요소의 속성을 업데이트하는 데 사용되는 값과 동일한지 확인합니다.
DOM 요소 업데이트에 사용되는 값이 현재 이러한 요소 업데이트에 사용되는 값과 동일한지 확인합니다.
모든 하위 구성 요소 확인
따라서 비교된 값이 다르면 오류가 발생합니다.라고 블로거 Max Koretskyi는 말했다.
범인은 항상 하위 구성 요소 또는 지시문입니다.
마지막으로 이 에러의 원인이 되는 실제 샘플은 다음과 같습니다.
제 경우 동적 컴포넌트의 인스턴스화가 문제였습니다.
으로 볼 때, 저는 에게 '아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아.setTimeout
, 제 , "루프 않은)가 했습니다.
다른 컴포넌트의 값을 변경할 때마다 영향을 받을 수 있도록 Angular 라이프 사이클을 항상 염두에 두는 것이 좋습니다.이 오류와 함께 Angular는 다음과 같이 알려줍니다.
잘못하고 있는 것 같은데, 정말 맞는 거야?
같은 블로그에서도 다음과 같이 말하고 있습니다.
대부분의 경우 올바른 변경 감지 후크를 사용하여 동적 구성 요소를 만드는 것이 수정 사항입니다.
간단한 가이드는 코딩 중에 최소한 다음 사항을 고려하는 것입니다.
(시간이 지남에 따라 보완하도록 하겠습니다)
- 대신 하위 구성 요소에서 상위 구성 요소 값을 수정하지 마십시오. 상위 구성 요소에서 값을 수정하십시오.
- 「 」를 사용하는
@Input
★★★★★★★★★★★★★★★★★」@Output
디렉티브는 컴포넌트가 완전히 초기화되지 않는 한 라이프 사이클 변경을 트리거하지 않도록 합니다. - 한 은 피한다.
this.cdr.detectChanges();
데이터를 때 할 수 . - 「 」를 하는
this.cdr.detectChanges();
입니다. 변수)가 있는지 합니다.★★★★★★★★★★★★★★★★」@Input, @Output, etc
하고 있는 는의 검출 훅 「 」 )으로채워지거나 됩니다.OnInit, OnChanges, AfterView, etc
) - 가능한 경우 숨기지 말고 제거합니다. 이는 점 3 및 4와 관련이 있습니다(앵글러다트에 대한 동일한 인용문).
- 에 어떤 .
setters
'어느 정도'라는 주석이 붙어 .@Input
는 setters에 앞서ngAfterViewInit
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★♪필요가 그 논리를 면田, 그田, 그田, 그田, 그田, 에 넣는 것이 좋습니다.ngOnChanges
★★★★★★ 。
또한.
Angular Life Hook에 대해 자세히 알고 싶다면 다음 공식 문서를 참조하십시오.https://angular.io/guide/lifecycle-hooks
github 문제에 대해 @leocaseiro에서 언급한 바와 같이.
간단한 수정을 원하는 분들을 위해 3가지 솔루션을 찾았습니다.
에서 이동 1) 서서 1 1 1
ngAfterViewInit
로로 합니다.ngAfterContentInit
2) 이동
ngAfterViewChecked
combined와ChangeDetectorRef
snowledge48snow48(snowledge48(snowledge48)에 와 같이하되 3) ngOnInit()로 합니다.
ChangeDetectorRef.detectChanges()
사용하실 수 있습니다.
이 경우 component에 changeDetection을 추가하고 ngAfterContentChecked의 detectChanges()를 호출하여 다음과 같은 코드를 수정했습니다.
@Component({
selector: 'app-spinner',
templateUrl: './spinner.component.html',
styleUrls: ['./spinner.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SpinnerComponent implements OnInit, OnDestroy, AfterContentChecked {
show = false;
private subscription: Subscription;
constructor(private spinnerService: SpinnerService, private changeDedectionRef: ChangeDetectorRef) { }
ngOnInit() {
this.subscription = this.spinnerService.spinnerState
.subscribe((state: SpinnerState) => {
this.show = state.show;
});
}
ngAfterContentChecked(): void {
this.changeDedectionRef.detectChanges();
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
여러 번 사용하던 작은 작품
Promise.resolve(data).then(() => {
console.log( "! changement de la date du composant !" );
this.dateNow = new Date();
this.cdRef.detectChanges();
});
를 ★★★★★★★★★★★★★★★★★★★★★★★ngAfterViewInit
로로 합니다.ngAfterContentInit
.
및 내용 뒤에 됩니다.ngAfterViewInit()
'이렇게 하다'라고 .ngAfterContentInit()
오류를 방지하려면 기본 양식 값을 사용하십시오.
'적용'이라는을 사용하는 '적용'을 사용합니다.detectChanges()
ngAfterViewInit()
(그 결과 오류도 해결되었습니다) 대신 동적 필수 폼 필드에 기본값을 저장하기로 결정했습니다.이것에 의해, 나중에 폼이 갱신되었을 때에, 유저가 새로운 필수 필드를 기동하는 폼의 옵션을 변경해도, 유효성은 변경되지 않습니다(및 송신 버튼이 무효가 됩니다).
이것에 의해, 제 컴포넌트에 약간의 코드가 보존되어, 제 경우는 에러가 전혀 발생하지 않게 되었습니다.
저는 여러분이 상상할 수 있는 가장 좋고 깨끗한 솔루션은 다음과 같다고 생각합니다.
@Component( {
selector: 'app-my-component',
template: `<p>{{ myData?.anyfield }}</p>`,
styles: [ '' ]
} )
export class MyComponent implements OnInit {
private myData;
constructor( private myService: MyService ) { }
ngOnInit( ) {
/*
async .. await
clears the ExpressionChangedAfterItHasBeenCheckedError exception.
*/
this.myService.myObservable.subscribe(
async (data) => { this.myData = await data }
);
}
}
Angular 5.2.9로 테스트 완료
이미 많은 답변이 있고 변화 검출에 관한 매우 좋은 기사로 연결되는 링크도 있지만, 저는 여기서 제 의견을 말하고 싶습니다.에 대해 해 본 은 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★BehaviourSubject
이치노그래서 저는 해결책을 위해 이렇게 했습니다.
- 서드파티제의 컴포넌트(풀캘린더)를 사용하고 있습니다만, Angular Material도 사용하고 있기 때문에 스타일링을 위해 새로운 플러그인을 작성했습니다만, 캘린더 헤더의 커스터마이즈는 레포킹과 롤링이 없으면 할 수 없기 때문에 모양과 느낌이 조금 어색합니다.
그래서 기본 JavaScript 클래스를 얻었고 컴포넌트용 캘린더 헤더를 초기화해야 합니다. 위해서는 「」가 합니다.
ViewChild
한 값을 에워싸고 있습니다.BehaviourSubject<View>(null)
:calendarView$ = new BehaviorSubject<View>(null);
다음,되면 그 을 '', '보다', '보다', '보다', '보다', '보다'의합니다.@ViewChild
ngAfterViewInit(): void {
// ViewChild is available here, so get the JS API
this.calendarApi = this.calendar.getApi();
}
ngAfterViewChecked(): void {
// The view has been checked and I know that the View object from
// fullcalendar is available, so emit it.
this.calendarView$.next(this.calendarApi.view);
}
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★async
파이프. 해킹이나 변경 감지, 오류 없이 원활하게 작동합니다.
더 자세한 정보가 필요하시면 주저 말고 말씀해 주세요.
를 선언하고 싶었기 에 이 했습니다.
값을 바꿨어요ngAfterViewInit
export class SomeComponent {
header: string;
}
고치기 위해
ngAfterViewInit() {
// change variable value here...
}
로.
ngAfterContentInit() {
// change variable value here...
}
지금까지의 솔루션은 모두 나에게 효과가 없었습니다.실제로 효과가 있었던 것은 이것뿐입니다.
오류 메시지의 예:
AppComponent.html:1 오류: ExpressionChangedAfterItHasBeenCheckedError: 식이 체크된 후 변경되었습니다.이전 값: 'ngIf: true'입니다.현재 값: 'ngIf: false'입니다.expressionChangedAfterItHasBeenCheckedError(core.js:20440)의 viewDebugError(core.js:20428)에서...
해결 방법 ChangeDetectorRef, AfterContentChecked 후 추가 :
ngAfterContentChecked(): void {
this.changeDetector.detectChanges();
}
예
import { Component, OnInit, ChangeDetectorRef, AfterContentChecked } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { environment } from '@env/environment';
import { LayoutService } from '@app/core/layout/layout.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: []
})
export class AppComponent implements OnInit, AfterContentChecked {
env = environment;
title = this.env.appName;
partials: any = {};
public constructor(
private titleService: Title,
public layout: LayoutService,
private changeDetector: ChangeDetectorRef,
) {}
ngOnInit() {
this.titleService.setTitle(this.env.appName);
this.layout.getLayout().subscribe(partials => {
this.partials = partials;
});
}
ngAfterContentChecked(): void {
this.changeDetector.detectChanges();
}
}
내 것이 아니다: 다음은 소스 https://gist.github.com/vades/a225170304f34f88a7a5d48bf4b1f58c입니다.
- 을 "javascript"로할 수 .
setTimeout()
. - , 이 " "를 사용합니다.
detectChanges()
충분할 거예요.이유는 .
이 에러가 발생하는 모든 이유와 이 에러의 모든 해결 방법에 대해서는, 다음의 문서를 참조해 주세요.https://blog.simplified.courses/angular-expression-changed-after-it-has-been-checked-error/
언급URL : https://stackoverflow.com/questions/39787038/how-to-manage-angular2-expression-has-changed-after-it-was-checked-exception-w
'programing' 카테고리의 다른 글
Joda DateTime을 ISO 8601 형식으로 자동 포맷 (0) | 2023.03.10 |
---|---|
주문 에이잭스에 수수료를 추가하는 woocommerce 커스텀 체크아웃 필드 (0) | 2023.03.10 |
Xmlhttp 요청 리디렉션 방지 (0) | 2023.03.10 |
온라인/오프라인 상태 변화 감지 방법 (0) | 2023.03.10 |
뷰 계층에 연결되지 않은 경우 WKWebKit javascript 실행 (0) | 2023.03.10 |