简体   繁体   中英

*ngFor directive not working on array of arrays

I have an array of arrays that I want to use as a directory. The point is to sort all the items according to which letter they begin with.

Here is the code of my item list component :

let itemList = ["Plane","Bird","Boat"];
let directory = [];
for (const item of this.itemList) {
    if (this.directory[item.charAt(0).toLowerCase()] == null || undefined) {
        this.directory[item.charAt(0).toLowerCase()] = [];
    }
    this.directory[item.charAt(0).toLowerCase()].push(item);
}

Then I want to display all my items sorted according to their first letter, and I want that first letter to be displayed above the list of items that begin with it, just like a directory. I use the following template in HTML :

<div id="item-list">
  <div *ngFor="let entry of directory ; let i = index">
    <p>{{i}}</p>
    <div *ngFor="let item of entry">
      <p>{{item}}</p>
      <app-item></app-item>
    </div>
  </div>
</div>

However, when I run my app, I see no data displayed in HTML. I tried to print text at several points :

<div id="item-list">
  <p>Hello</p>
  <div *ngFor="let entry of directory ; let i = index">
    <p>Hello again</p>
    <p>{{i}}</p>
    <div *ngFor="let item of entry">
      <p>{{item}}</p>
      <app-item></app-item>
    </div>
  </div>
</div>

The webpage displays"Hello", but no "Hello again" (while I think the latter should be printed twice). However, there is absolutely no error message neither when running ng serve nor loading the page. I've searched on the web for a similar problem, but nobody seems to be facing the same difficulties to dynamically display an array of arrays.

Can you tell me what I am doing wrong? Any help would be greatly appreciated. :)

stackblitz: https://stackblitz.com/edit/angular-tujusv

The directory array is a key:value pair array. You can store the keys in a different array and access them in the html

export class ItemListComponent implements OnInit {
  alphabet: string[];
  directory = [];
  dirArr =[];
  itemList = ["Plane", "Bird", "Boat"];
  constructor() {
    this.alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];

  }


  ngOnInit() {

    this.itemList.sort();
    for (const item of this.itemList) {
      if (this.directory[item.charAt(0).toLowerCase()] == null || undefined) {
        this.directory[item.charAt(0).toLowerCase()] = [];
      }
      this.directory[item.charAt(0).toLowerCase()].push(item);
      console.log(this.directory);
      this.dirArr = Object.keys(this.directory);
      console.log(this.dirArr)

    }

    console.log(this.directory['p']);


  }
}

HTML:

<div id="item-list">
  <p>Hello</p>
  <div *ngFor="let entry of dirArr ; let i = index">
    <p>Hello again</p>
    <p>{{i}}</p>
    <p>{{entry}}</p>
    <p>{{directory[entry]}}</p>
    <div *ngFor="let item of directory[entry]">
      <p>{{item}}</p>
    </div>
  </div>
</div>

make one temp variable and your other code is fine: only change below code:

let itemList = ["Plane","Bird","Boat"];
  let temp = {};
  let directory = []

 for (const item of this.itemList) {

    if (this.temp[item.charAt(0).toLowerCase()] == null || undefined) {
        this.temp[item.charAt(0).toLowerCase()] = [];
    }
    this.temp[item.charAt(0).toLowerCase()].push(item);

  }
   this.directory = Object.values(this.temp)

Keyed and nested structures in JavaScript are constructed using OLN. They support for key:value pairs in the way you are attempting to structure your data.

Your use case data structure seems to be:

{
  b : ["Bird", "Boat"],
  p  : ["Plane"]
}

But you are attempting to construct:

[
  b => [ "Bird", "Boat"], p => ["Plane"]
]

Which is not valid in JavaScript.

Change your declaration of directory from [] to {}

I've done the below changes to accomplish your requirement try it once.

this.items = this.items.sort();
let currentLetter = this.items[0].charAt(0);
let currentLetterLib = [];
for (let item of this.items) {
  if (item.charAt(0).toLowerCase() != currentLetter) {
      this.directory.push({
        "letter": currentLetter,
        "words": currentLetterLib
      });
      currentLetter = item.charAt(0).toLowerCase();
      currentLetterLib = [];
  }
  currentLetterLib.push(item);
}
this.directory.push({
  "letter": currentLetter,
  "words": currentLetterLib
});

<div id="item-list">
  <p>Hello</p>
  <div *ngFor="let entry of directory ;">
    <p>{{entry.letter}}</p>
    <div *ngFor="let item of entry.words">
      <p>{{item}}</p>
    </div>
  </div>
</div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM