Reputation: 166
Initialization of variable in one element and error in console that I had been ignoring all along, created a problem elsewhere in another element. Why does angular behave this way?
When I do not initialize another variable, which I am using with *ngIf, javascript throws up "undefined" while testing its length (expected). But this also causes *ngFor to not work properly for the dropdown (no data gets loaded - unexpected). Btw I realized, this is not just happening with datalist; *ngFor fails on any component if *ngIf has error in this code.
So, why does *ngFor fail for dropdown (first element) when *ngIf condition can't be validated on table (another element)? Should I think about this in a different way that Angular is a framework and may behave erratically if I don't do a good job in managing errors on its constructs?
Below is the code to reproduce error. Uncomment the suggested line and error will go away...
HTML
<div class="row">
<div class="col">
<input
type="text" class="form-control" list="tktnum"
placeholder="Ticket Number..." [(ngModel)]="tktNum"
>
<datalist id="tktnum">
<option *ngFor="let a of tktVals">{{a.TicketNo}}</option>
</datalist>
</div>
</div>
<br><br>
<div class="row">
<div class="col">
<table class="table table-hover table-striped table-dark table-bordered"
*ngIf="reportElements.length > 0">
<thead>
<tr>
<th scope="col">Ticket Number</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let _ of reportElements">
<td>{{ _.F1 }}</td>
</tr>
</tbody>
</table>
</div>
</div>
Typescript
import { Component, OnInit, VERSION } from "@angular/core";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {
reportElements: [{F1: 3}];
tktVals: Array<{ TicketNo: string }> = [{ TicketNo: "1" }, { TicketNo: "2" }];
tktNum: any;
constructor() {}
ngOnInit(): void {
this.tktVals = [{ TicketNo: "1" }, { TicketNo: "2" }];
//Uncomment the following line of code and it will start working as expected.
//this.reportElements = [{F1: 3}];
console.log(this.reportElements.length);
}
}
Upvotes: 1
Views: 819
Reputation: 385
The problem is that reportElements is undefined initially. You cannot actually use the length of "undefined because it doesn't have a property of length, and you cannot also iterrate on it because undefined is not iterrable. There're multiple ways to solve it:
Give an initial value of an empty array to reportElements. But in this case you need to care about removing/changing its type notation:
reportElements: [{F1: 3}] = [];
Wrap the whole table html into ng-container:
<ng-container *ngIf="reportElements">
<table></table>
</ng-container>
Change the existing *ngIf of the table to the following one:
*ngIf="reportElements && reportElements?.length > 0"
When an error in template expression happens, it makes all other expressions in the same template to fail. That's why both your table and select are broken.
Upvotes: 1