DEV Community

loading...

Dynamically change number of columns in a grid using ngStyle

Jason F
UI developer, distro hopper. Currently running Debian 11.
・2 min read

Today I'll show you how I used ngStyle along with CSS grid to create a resizeable grid.

Alt Text

ngStyle For The Win

ngStyle is a built-in attribute directive that lets you set styles by binding to an expression such as a function.

Here in my card-container.component.html I am binding to my getStyles method.

  <div class="cards-grid" [ngStyle]="getStyles()">
    <app-card
      *ngFor="let band of bands; index as i"
      [bandData]="bands[i]"
    ></app-card>
  </div>
Enter fullscreen mode Exit fullscreen mode

This getStyles in my card-container.component.ts method returns an object with my defined styles. The magic is in the grid-template-columns value. I am using string interpolation to pass in a property called columns.

 public getStyles() {
    return {
      display: 'grid',
      'grid-template-columns': `repeat(${this.columns}, 1fr)`,
      'justify-items': 'center',
    };
  }
Enter fullscreen mode Exit fullscreen mode

If we look at the entire card-container.component.html component, you will see that I'm using an input and this is where the value for the columns property comes from.

<div class="card-container">
  <div class="cards-header">
    <mat-form-field>
      <mat-label>Columns</mat-label>
      <input matInput type="number" min="1" max="5" [(ngModel)]="columns" />
    </mat-form-field>
  </div>
  <div class="cards-grid" [ngStyle]="getStyles()">
    <app-card
      *ngFor="let band of bands; index as i"
      [bandData]="bands[i]"
    ></app-card>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

If we look at the entire card-container.component.ts file you will see that I initialize the columns property to 4.

import { Component, OnInit } from '@angular/core';
import * as bandData from './powermetal.json';

@Component({
  selector: 'app-card-container',
  templateUrl: './card-container.component.html',
  styleUrls: ['./card-container.component.scss'],
})
export class CardContainerComponent implements OnInit {
  public columns: number = 4;
  public bands: any = (bandData as any).default;

  constructor() {}
  ngOnInit(): void {}

  public getStyles() {
    return {
      display: 'grid',
      'grid-template-columns': `repeat(${this.columns}, 1fr)`,
      'justify-items': 'center',
    };
  }
}

Enter fullscreen mode Exit fullscreen mode

Thoughts?

I'd love you hear your thoughts on this. I don't think you would want to use an input like I'm doing here. The number of columns could go in to a settings page, or wherever else it fits in to the application.

Repository

If you want to see the code, you can check it out here.

Discussion (0)