I want to create grid template from nested array. This method works if elements naturally have same height, but when value is too long, some of elements have different height
<div id="container" [style.grid-template-columns]="'repeat(outerArray.length, 1fr)'" [style.columnGap.rem]="1" *ngIf="outerArray.length != 0">
<div class="outerArray" *ngFor="let inner of outerArray">
<div *ngFor="let item of inner">
{{item}}
</div>
</div>
</div>
resulted item should be placed like this:
inner1value1 inner2value1 inner3value1
inner1value2 inner2value2 inner3value2
inner1value3
With grid look like this: (array with 8 inner arrays)
I want to keep same width for each element in a column (but columns can have different width), and same height in a row.
Table worked quite fine, but values from one inner array populate row, not column, and, in my opinion, table semantically doesn't fit to my need.
<table *ngIf="outerArray.length != 0">
<tbody>
<tr *ngFor="let inner of outerArray">
<td *ngFor="let item of inner;">
{item}}
</td>
</tr>
</tbody>
</table>
Arrays have different size (at the beginning longer, then rest have one item less)
Sample array may look like this:
let outerArray = [
[
"short",
"bit longer",
"example value"
],
[
"not so long, but longer string",
"short words",
"bitLonger twoWords"
],
[
"shorter array",
"different lengths of strings"
],
[
"another shorter array",
"string"
]
]
Amount and length of array may be various, sometimes there is one array with 8 elements, but there can be also 8 array with 2 elements. Strings have one or two words, but words sometimes have up to 15 characters, so when there is few inner arrays, strings need two lines to fit on sceen width
My perfect solution is to create divs without nesting and place them corectly using css styling
We need to have only one set of inner divs. You have a nested div structure so it's messing up the layout. I am using ng-container
for the inner for loop; the speciality of ng-container
is that it does not create an element in the HTML, so we can just use it to run both the for loops and create a single set of divs.
Also when you create the property [style.grid-template-columns]="'repeat('+outerArray.length+', 1fr)'"
make sure that you have a clear distinction between strings and JavaScript variables.
The previous code would render only repeat(outerArray.length, 1fr)
as a string, instead of inserting the outerArray length, so I changed the code to
'repeat('
(string) + outerArray.length
(number) + ', 1fr)'(string)
Also we need [style.grid-template-rows]
which has the same config as columns.
If you want all the rows as same height, use the commented CSS provided, it will add an ellipsis to the element and make all the cells same height.
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule],
styles: [`
#container {
display: grid;
}
/* .same-height {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
} */
`],
template: `
<div id="container" [style.grid-template-columns]="'repeat('+outerArray.length+', 1fr)'" [style.grid-template-rows]="'repeat('+outerArray.length+', 1fr)'" [style.columnGap.rem]="1" *ngIf="outerArray.length != 0">
<ng-container class="outerArray" *ngFor="let inner of outerArray">
<div *ngFor="let item of inner" style="background-color: red;color: white; margin-bottom:2px;" class="same-height">
{{item}}
</div>
</ng-container>
</div>
`,
})
export class App {
outerArray = [
['short', 'bit longer', 'example value'],
['not so long, but longer string', 'short words', 'bitLonger twoWords'],
['shorter array', 'different lengths of strings'],
['another shorter array', 'string'],
];
}
bootstrapApplication(App);