Search code examples
typescriptnativescriptngfornativescript-angularng-container

Issues with *ngFor and GridLayout in Nativescript


I have a problem with the grid layout. My code is this one:

    <GridLayout padding="10%"columns="auto, auto, auto, auto, auto, auto, auto" rows="*">
      <ng-container *ngFor="let item of items">
        <label [text]="item.codice" col="0",[row]="{{item.row}}"fontSize="24px"></label>
        <label [text]="item.prodotto" col="1",[row]="{{item.row}}"fontSize="24px"></label>
        <label [text]="item.lottoData" col="2",[row]="{{item.row}}"fontSize="24px"></label>
        <label [text]="item.codiceCont" col="3",[row]="{{item.row}}"fontSize="24px"></label>
        <label [text]="item.qtyUntPri" col="4",[row]="{{item.row}}"fontSize="24px"></label>
        <label [text]="item.studioCieco" col="5",[row]="{{item.row}}"fontSize="24px"></label>
        <label [text]="item.qty" col="6",[row]="{{item.row}}"fontSize="24px"></label>
      </ng-container>
    </GridLayout> 

I'm expecting to see those columns and a row for each item, but I have something like you can see in the image below:

enter image description here

If you need to see the typescript

  ngOnInit(): void {
    var usefulData = this.data["param"]["response"];
    var firstTable = usefulData[0];
    var secondTable = usefulData[1];
    this.studyCode = firstTable[0]["StudyCode"];
    this.nameFile = firstTable[0]["NameFile"];
    var row = 1;
    for (var i in secondTable){
      if(secondTable[i] != undefined){
        this.items.push({
        codice:secondTable[i]["Codice"],
        prodotto:secondTable[i]["Product"],
        lottoData:secondTable[i]["LottoData"],
        codiceCont:secondTable[i]["CodiceCont"],
        qtyUntPri:secondTable[i]["QtyUntPri"],
        studioCieco:secondTable[i]["StudioCieco"],
        qty:secondTable[i]["Qty"],
        row:row
      });
      row+=1;
      }
    }
  }

Solution

  • You declared the GridLayout with rows="*", which means that you have only one row:

    <GridLayout padding="10%"columns="auto, auto, auto, auto, auto, auto, auto" rows="*">
    

    This is why you're seeing the overlapping condensed text in the screenshot you provided.

    Reminder: The rows and columns of {N} GridLayout take either:

    • An absolute number: Indicates a fixed size.
    • auto: Makes the column as wide as its widest child or makes the row as tall as its tallest child.
    • *: Takes as much space as available after filling all auto and fixed-size columns or rows.

    To fix this, you need to set the rows property to reflect the number of rows that should be available on your GridLayout. For example, if you have an item with [row]="{{item.row}}", and the maximum item.row = 5, then your GridLayout should be declared like below:

    <GridLayout
        padding="10%"
        columns="auto, auto, auto, auto, auto, auto, auto"
        rows="auto, auto, auto, auto, auto" <-- note the 5 rows
    >
        <!-- child elements ... -->
    </GridLayout>
    

    In your example it looks like you have to calculate the number of rows and bind this to the rows property of the Gridlayout, like so:

        public gridRows: string;
    
    
        ngOnInit(): void {
            var usefulData = this.data['param']['response'];
            var firstTable = usefulData[0];
            var secondTable = usefulData[1];
            this.studyCode = firstTable[0]['StudyCode'];
            this.nameFile = firstTable[0]['NameFile'];
            var row = 1;
            for (var i in secondTable) {
                if (secondTable[i] != undefined) {
                    this.items.push({
                        codice: secondTable[i]['Codice'],
                        prodotto: secondTable[i]['Product'],
                        lottoData: secondTable[i]['LottoData'],
                        codiceCont: secondTable[i]['CodiceCont'],
                        qtyUntPri: secondTable[i]['QtyUntPri'],
                        studioCieco: secondTable[i]['StudioCieco'],
                        qty: secondTable[i]['Qty'],
                        row: row,
                    });
                    row += 1;
                }
            }
    
            const rowsCount = row;
            this.gridRows = Array.from({ length: rowsCount }, (_, idx) => `auto`).toString();
        }
    
    <GridLayout
        padding="10%"
        columns="auto, auto, auto, auto, auto, auto, auto"
        [rows]="gridRows"
    >
          <ng-container *ngFor="let item of items">
            <label [text]="item.codice" col="0" [row]="item.row" fontSize="24px"></label>
            <label [text]="item.prodotto" col="1" [row]="item.row" fontSize="24px"></label>
            <label [text]="item.lottoData" col="2" [row]="item.row" fontSize="24px"></label>
            <label [text]="item.codiceCont" col="3" [row]="item.row" fontSize="24px"></label>
            <label [text]="item.qtyUntPri" col="4" [row]="item.row" fontSize="24px"></label>
            <label [text]="item.studioCieco" col="5" [row]="item.row" fontSize="24px"></label>
            <label [text]="item.qty" col="6" [row]="item.row" fontSize="24px"></label>
          </ng-container>
        </GridLayout> 
    

    Note: Either use string extrapolation {{ expression }} or binding using square brackets [], but not both, and of course, no need for the comma after col="x" inside the <label> property.