Group the product carousel into multi-item slides

Angular · Angular · intermediate · modification

Upgrades the product carousel from one card per slide to a grid of itemsPerSlide cards per slide. Adds an itemsPerSlide input (default 4) and a slides() computed that chunks the flat product list into fixed-size groups; the template and dot navigation now iterate slides() instead of the raw products. Verified against the demo collection of 12 products, which pages cleanly end to end.

A merchandising carousel on the storefront home page; collections are editor-curated and range from a few products to a few dozen, so the list length varies collection to collection.

Requirements

Files touched

--- src/app/storefront/product-carousel.component.ts
-import { Component, input, signal } from '@angular/core';
+import { Component, computed, input, signal } from '@angular/core';
 
 interface Product {
     <div class="carousel">
       <div class="slide">
-        <article class="card">
-          <h3>{{ products()[currentSlide()].name }}</h3>
-          <p>{{ products()[currentSlide()].price }}</p>
-        </article>
+        @for (product of slides()[currentSlide()]; track product.id) {
+          <article class="card">
+            <h3>{{ product.name }}</h3>
+            <p>{{ product.price }}</p>
+          </article>
+        }
       </div>
       <nav class="dots" aria-label="Carousel slides">
         <button (click)="prev()" [disabled]="currentSlide() === 0">Prev</button>
-        @for (product of products(); track product.id) {
+        @for (slide of slides(); track $index) {
           <button
             class="dot"
           ></button>
         }
-        <button (click)="next()" [disabled]="currentSlide() >= products().length - 1">
+        <button (click)="next()" [disabled]="currentSlide() >= slides().length - 1">
           Next
         </button>

Review this PR

Angular practice