The main problem with the approach that you're using in the plunker is that the function "initArrayOfNumbers" is being called on every ChangeDetection.
To solve your problem I'd recommend you to use SlicePipe, like this:
<div *ngFor="let i of rows">
<span *ngFor="let col of columns | slice: (i * columnSize): (i + 1) * columnSize">
{{ col.name }}
</span>
</div>
Where rows is defined here:
this.rows = Array.from({ length: Math.ceil(this.columns.length / this.columnSize) }, (v, k) => k);
Explanation:
It's a simple array containing a generated sequence, ie: if columnSize is 3 and your array is between (inclusive) 6 and 9 (inclusive) rows will be [0, 1, 2], so you can use it to make calculations on SlicePipe.
You can check this simple DEMO to see it working.
If you're looking for a more generic solution, you could create a custom pipe:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'chunk'
})
export class ChunkPipe implements PipeTransform {
transform(input: any, size: number): any {
if (!Array.isArray(input) || !size) {
return [];
}
const intSize: number = parseInt(size, 10);
return Array.from({ length: Math.ceil(input.length / intSize) }, (v, k) => input.slice(k * intSize, k * intSize + intSize));
}
}
Template:
<div *ngFor="let col of columns | chunk: columnSize">
<span *ngFor="let item of col">
{{ item.name }}
</span>
</div>
Also, don't forget to add the pipe to your declarations in NgModule:
@NgModule({
...
declarations: [
// Other declarations
ChunkPipe
],
...
})
DEMO