0

I am having a hard time trying to get *ngFor to work in a DataList with input.

This works...

        <input 
            type="text" class="form-control" list="tktnum"
            placeholder="Ticket Number..." [(ngModel)]="dbParams.tktNum"
        >
        <datalist id="tktnum"> 
            <option>{{tktVals[0].TicketNo}}</option>
            <option>{{tktVals[1].TicketNo}}</option>
            <option>{{tktVals[2].TicketNo}}</option>
        </datalist>

But this doesn't...

        <input 
            type="text" class="form-control" list="tktnum"
            placeholder="Ticket Number..." [(ngModel)]="dbParams.tktNum"
        >
        <datalist id="tktnum"> 
            <option *ngFor="let a of tktVals">{{ a.TicketNo }}</option>
        </datalist>

The dropdown box remains empty when I use the second block of code.

What I tried

I have tried to create a new angular app, with only this piece of code and that has worked, but when I try to include it in the actual app, *ngFor doesn't work. I am using *ngFor in an HTML table in the actual app, which is working just fine. The problem seems to only be with the DataList and that too in the app that I am working on. I am using VS Code and updated it to the latest version, recompiled the app from the beginning. I am working on a Windows 10 machine.

Here's the typescript code - with unrelated items removed

export class TicketReportComponent implements OnInit {
    tktVals: Array<{TicketNo: string}>;

    ngOnInit(): void {
        this.tktVals = [{"TicketNo": "1"}, {"TicketNo": "2"}];
    }
}
TKtheLazyGuy
  • 168
  • 14
  • I think you should set [value] option – rad11 Dec 06 '20 at 14:34
  • @rad11, this exact code is working when I create a new app. It just doesn't work with existing project, what will the [value] option give? – TKtheLazyGuy Dec 06 '20 at 14:38
  • And, does it works if you initialize your `tktVals`variable like this? `tktVals: Array<{TicketNo: string}> = [{"TicketNo": "1"}, {"TicketNo": "2"}];`. The problem could be related with change detection. – jccampanero Dec 06 '20 at 14:59
  • @jccampanero No, doesn't work that way either... just tried. – TKtheLazyGuy Dec 06 '20 at 15:04
  • Thank you for trying... And, in the browser developer tools, can you please verify if the datalist contains the different `option`s or not? Maybe you can print your array, just to see if the values are there, I mean: `{{ a | json }}`. You get the idea. – jccampanero Dec 06 '20 at 15:51

3 Answers3

1

Check if you are getting any error on your console, the issue that you are having seams similar to this issue, maybe you need to import BrowserModule, or CommonModule on the module where you called this component.

  • No errors on console, I have only root module and BrowserModule is present. – TKtheLazyGuy Dec 06 '20 at 14:56
  • Can you do stackblitz where you can reproduce the bug? – Visar Hyseni Dec 06 '20 at 15:16
  • I played a bit with code on stackblitz and came up with udpated problem. I was able to resolve the initial question, please see the udpate and let me know what you think. As you pointed out there was variable initialization problem. – TKtheLazyGuy Dec 07 '20 at 03:11
0

@Visar Hynei is correct.

In you module.ts of where you have declared this component in the decalrations array . check whether you have added commonModule in the imports array. If not import it Module.ts

@NgModule({
  imports: [BrowserModule, FormsModule,commonModule],

  declarations: [AppComponent],
  bootstrap: [AppComponent]
})

https://angular.io/guide/frequent-ngmodules

  • Please look at the updated problem, I've added the entire code which you can use to recreate the problem, then uncomment the suggest line and fix the problem, but can you tell me the reason why that variable ("reportElements") has got anything to do with "tktVals" – TKtheLazyGuy Dec 07 '20 at 05:31
0

The problem was with initialization of a class property (reportElements) that was used by *ngIf in another html element (table). When that reportElements wasn't initialized, it's length couldn't be determined and javascript threw "undefined" message in console. When I initialized reportElements in "ngOnInit", length became 0 (rather than undefined) and *ngIf started to function properly on the table. This also caused *ngFor in the datalist to start working properly. For reference please see the updated code below...

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);
  }
}

TKtheLazyGuy
  • 168
  • 14