Evaluating *ngIf inside every *nFor loop in Angular 7











up vote
2
down vote

favorite












I'm trying to use the following statement in my Angular template



<ng-container *ngFor="let sequence of sequences; let i = index">
<div *ngIf="displayNewDate(sequence.start)">
<p>{{ sequence.start | date:'shortDate' }}</p>
</div>
{{ sequence.content }}
</ng-container>


Where as the method displayNewDate(sequence.start) checks if the current date has been displayed, and displays it if not. Therefor I want the *ngIf to vary between true and false.



public displayNewDate(current) {
const currentDate: Date = new Date(current);
if (!this.previousDate) {
this.previousDate = currentDate;
return true;
} else if (this.previousDate.getFullYear() < currentDate.getFullYear()) {
this.previousDate = currentDate;
return true;
} else if (this.previousDate.getFullYear() == currentDate.getFullYear() && this.previousDate.getMonth() < currentDate.getMonth()) {
this.previousDate = currentDate;
return true;
} else {
return false;
}
}


However I get the following in the console:




ERROR Error: "ExpressionChangedAfterItHasBeenCheckedError: Expression
has changed after it was checked. Previous value: 'ngIf: true'.
Current value: 'ngIf: false'."




Is this a limitation to the *ngIf directive? If so, is there an alternative way to get a list of sequences, and everytime a sequence beginning at a date different from the previous sequence, display the new date above the given sequence.










share|improve this question
























  • That is not related to for-if combination. Even more - it is not related to ngIf perse but the way angular binds values to UI (and checks for modifications afterwards)
    – Antoniossss
    Nov 12 at 21:26








  • 1




    Your method is supposed to be idempotent: if nothing else changes in the state of your app, two subsequent calls to the method with the same argument are supposed to return the same value. That's not the case. Don't change the state of your component when evaluating an expression, i.e. calling a getXxx method.
    – JB Nizet
    Nov 12 at 21:27












  • @JBNizet What are the alternatives?
    – PhyCoMath
    Nov 12 at 21:31












  • No, you can't do that.
    – JB Nizet
    Nov 12 at 21:31






  • 1




    Use the actual state to return the correct value. Get the actual previous date from the array, and check if it's different from the current one. Or precompute that once, storing in each sequence if it should display the start or not. This method is called at each change detection, for each sequence. Not just once for each sequence.
    – JB Nizet
    Nov 12 at 21:33

















up vote
2
down vote

favorite












I'm trying to use the following statement in my Angular template



<ng-container *ngFor="let sequence of sequences; let i = index">
<div *ngIf="displayNewDate(sequence.start)">
<p>{{ sequence.start | date:'shortDate' }}</p>
</div>
{{ sequence.content }}
</ng-container>


Where as the method displayNewDate(sequence.start) checks if the current date has been displayed, and displays it if not. Therefor I want the *ngIf to vary between true and false.



public displayNewDate(current) {
const currentDate: Date = new Date(current);
if (!this.previousDate) {
this.previousDate = currentDate;
return true;
} else if (this.previousDate.getFullYear() < currentDate.getFullYear()) {
this.previousDate = currentDate;
return true;
} else if (this.previousDate.getFullYear() == currentDate.getFullYear() && this.previousDate.getMonth() < currentDate.getMonth()) {
this.previousDate = currentDate;
return true;
} else {
return false;
}
}


However I get the following in the console:




ERROR Error: "ExpressionChangedAfterItHasBeenCheckedError: Expression
has changed after it was checked. Previous value: 'ngIf: true'.
Current value: 'ngIf: false'."




Is this a limitation to the *ngIf directive? If so, is there an alternative way to get a list of sequences, and everytime a sequence beginning at a date different from the previous sequence, display the new date above the given sequence.










share|improve this question
























  • That is not related to for-if combination. Even more - it is not related to ngIf perse but the way angular binds values to UI (and checks for modifications afterwards)
    – Antoniossss
    Nov 12 at 21:26








  • 1




    Your method is supposed to be idempotent: if nothing else changes in the state of your app, two subsequent calls to the method with the same argument are supposed to return the same value. That's not the case. Don't change the state of your component when evaluating an expression, i.e. calling a getXxx method.
    – JB Nizet
    Nov 12 at 21:27












  • @JBNizet What are the alternatives?
    – PhyCoMath
    Nov 12 at 21:31












  • No, you can't do that.
    – JB Nizet
    Nov 12 at 21:31






  • 1




    Use the actual state to return the correct value. Get the actual previous date from the array, and check if it's different from the current one. Or precompute that once, storing in each sequence if it should display the start or not. This method is called at each change detection, for each sequence. Not just once for each sequence.
    – JB Nizet
    Nov 12 at 21:33















up vote
2
down vote

favorite









up vote
2
down vote

favorite











I'm trying to use the following statement in my Angular template



<ng-container *ngFor="let sequence of sequences; let i = index">
<div *ngIf="displayNewDate(sequence.start)">
<p>{{ sequence.start | date:'shortDate' }}</p>
</div>
{{ sequence.content }}
</ng-container>


Where as the method displayNewDate(sequence.start) checks if the current date has been displayed, and displays it if not. Therefor I want the *ngIf to vary between true and false.



public displayNewDate(current) {
const currentDate: Date = new Date(current);
if (!this.previousDate) {
this.previousDate = currentDate;
return true;
} else if (this.previousDate.getFullYear() < currentDate.getFullYear()) {
this.previousDate = currentDate;
return true;
} else if (this.previousDate.getFullYear() == currentDate.getFullYear() && this.previousDate.getMonth() < currentDate.getMonth()) {
this.previousDate = currentDate;
return true;
} else {
return false;
}
}


However I get the following in the console:




ERROR Error: "ExpressionChangedAfterItHasBeenCheckedError: Expression
has changed after it was checked. Previous value: 'ngIf: true'.
Current value: 'ngIf: false'."




Is this a limitation to the *ngIf directive? If so, is there an alternative way to get a list of sequences, and everytime a sequence beginning at a date different from the previous sequence, display the new date above the given sequence.










share|improve this question















I'm trying to use the following statement in my Angular template



<ng-container *ngFor="let sequence of sequences; let i = index">
<div *ngIf="displayNewDate(sequence.start)">
<p>{{ sequence.start | date:'shortDate' }}</p>
</div>
{{ sequence.content }}
</ng-container>


Where as the method displayNewDate(sequence.start) checks if the current date has been displayed, and displays it if not. Therefor I want the *ngIf to vary between true and false.



public displayNewDate(current) {
const currentDate: Date = new Date(current);
if (!this.previousDate) {
this.previousDate = currentDate;
return true;
} else if (this.previousDate.getFullYear() < currentDate.getFullYear()) {
this.previousDate = currentDate;
return true;
} else if (this.previousDate.getFullYear() == currentDate.getFullYear() && this.previousDate.getMonth() < currentDate.getMonth()) {
this.previousDate = currentDate;
return true;
} else {
return false;
}
}


However I get the following in the console:




ERROR Error: "ExpressionChangedAfterItHasBeenCheckedError: Expression
has changed after it was checked. Previous value: 'ngIf: true'.
Current value: 'ngIf: false'."




Is this a limitation to the *ngIf directive? If so, is there an alternative way to get a list of sequences, and everytime a sequence beginning at a date different from the previous sequence, display the new date above the given sequence.







angular ngfor angular-ng-if angular7






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 15 at 13:48









Goncalo Peres

9011311




9011311










asked Nov 12 at 21:22









PhyCoMath

2181826




2181826












  • That is not related to for-if combination. Even more - it is not related to ngIf perse but the way angular binds values to UI (and checks for modifications afterwards)
    – Antoniossss
    Nov 12 at 21:26








  • 1




    Your method is supposed to be idempotent: if nothing else changes in the state of your app, two subsequent calls to the method with the same argument are supposed to return the same value. That's not the case. Don't change the state of your component when evaluating an expression, i.e. calling a getXxx method.
    – JB Nizet
    Nov 12 at 21:27












  • @JBNizet What are the alternatives?
    – PhyCoMath
    Nov 12 at 21:31












  • No, you can't do that.
    – JB Nizet
    Nov 12 at 21:31






  • 1




    Use the actual state to return the correct value. Get the actual previous date from the array, and check if it's different from the current one. Or precompute that once, storing in each sequence if it should display the start or not. This method is called at each change detection, for each sequence. Not just once for each sequence.
    – JB Nizet
    Nov 12 at 21:33




















  • That is not related to for-if combination. Even more - it is not related to ngIf perse but the way angular binds values to UI (and checks for modifications afterwards)
    – Antoniossss
    Nov 12 at 21:26








  • 1




    Your method is supposed to be idempotent: if nothing else changes in the state of your app, two subsequent calls to the method with the same argument are supposed to return the same value. That's not the case. Don't change the state of your component when evaluating an expression, i.e. calling a getXxx method.
    – JB Nizet
    Nov 12 at 21:27












  • @JBNizet What are the alternatives?
    – PhyCoMath
    Nov 12 at 21:31












  • No, you can't do that.
    – JB Nizet
    Nov 12 at 21:31






  • 1




    Use the actual state to return the correct value. Get the actual previous date from the array, and check if it's different from the current one. Or precompute that once, storing in each sequence if it should display the start or not. This method is called at each change detection, for each sequence. Not just once for each sequence.
    – JB Nizet
    Nov 12 at 21:33


















That is not related to for-if combination. Even more - it is not related to ngIf perse but the way angular binds values to UI (and checks for modifications afterwards)
– Antoniossss
Nov 12 at 21:26






That is not related to for-if combination. Even more - it is not related to ngIf perse but the way angular binds values to UI (and checks for modifications afterwards)
– Antoniossss
Nov 12 at 21:26






1




1




Your method is supposed to be idempotent: if nothing else changes in the state of your app, two subsequent calls to the method with the same argument are supposed to return the same value. That's not the case. Don't change the state of your component when evaluating an expression, i.e. calling a getXxx method.
– JB Nizet
Nov 12 at 21:27






Your method is supposed to be idempotent: if nothing else changes in the state of your app, two subsequent calls to the method with the same argument are supposed to return the same value. That's not the case. Don't change the state of your component when evaluating an expression, i.e. calling a getXxx method.
– JB Nizet
Nov 12 at 21:27














@JBNizet What are the alternatives?
– PhyCoMath
Nov 12 at 21:31






@JBNizet What are the alternatives?
– PhyCoMath
Nov 12 at 21:31














No, you can't do that.
– JB Nizet
Nov 12 at 21:31




No, you can't do that.
– JB Nizet
Nov 12 at 21:31




1




1




Use the actual state to return the correct value. Get the actual previous date from the array, and check if it's different from the current one. Or precompute that once, storing in each sequence if it should display the start or not. This method is called at each change detection, for each sequence. Not just once for each sequence.
– JB Nizet
Nov 12 at 21:33






Use the actual state to return the correct value. Get the actual previous date from the array, and check if it's different from the current one. Or precompute that once, storing in each sequence if it should display the start or not. This method is called at each change detection, for each sequence. Not just once for each sequence.
– JB Nizet
Nov 12 at 21:33



















active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53270307%2fevaluating-ngif-inside-every-nfor-loop-in-angular-7%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown






























active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes
















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53270307%2fevaluating-ngif-inside-every-nfor-loop-in-angular-7%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

ComboBox Display Member on multiple fields

Is it possible to collect Nectar points via Trainline?