Skip to content

Loops

Listen und Arrays mit wm:for rendern.

Syntax

html
<div wm:for="item in items">
  {{item.name}}
</div>

Mit Index:

html
<div wm:for="item, index in items">
  {{index}}: {{item.name}}
</div>

Grundlagen

Einfache Liste

component.html:

html
<ul>
  <li wm:for="product in items">
    {{product.name}} - ${{product.price}}
  </li>
</ul>

Beispiel-Daten:

json
{
  "items": [
    { "name": "Product A", "price": 29.99 },
    { "name": "Product B", "price": 39.99 }
  ]
}

Ergebnis:

html
<ul>
  <li>Product A - $29.99</li>
  <li>Product B - $39.99</li>
</ul>

Mit Index

Index beginnt bei 0:

html
<div wm:for="item, index in items">
  <span>{{index}}</span>: {{item.name}}
</div>

Ergebnis:

html
<div>
  <span>0</span>: Product A
</div>
<div>
  <span>1</span>: Product B
</div>

Index für Styling

html
<div wm:for="item, index in items" class="item-{{index}}">
  {{item.name}}
</div>

Beispiele

Feature Liste

json
{
  "props": {
    "features": {
      "type": "array",
      "default": [
        { "title": "Fast", "description": "Lightning fast performance" },
        { "title": "Secure", "description": "Enterprise-grade security" },
        { "title": "Scalable", "description": "Grows with your business" }
      ]
    }
  }
}
html
<div class="features-grid">
  <div wm:for="feature in features" class="feature-card">
    <h3 class="text-xl font-bold">{{feature.title}}</h3>
    <p class="text-gray-600">{{feature.description}}</p>
  </div>
</div>

Team Members

json
{
  "props": {
    "team": {
      "type": "array",
      "default": [
        {
          "name": "Alice Johnson",
          "role": "CEO",
          "image": "/team/alice.jpg"
        },
        {
          "name": "Bob Smith",
          "role": "CTO",
          "image": "/team/bob.jpg"
        }
      ]
    }
  }
}
html
<div class="team-grid grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
  <div wm:for="member in team" class="team-member">
    <img src="{{member.image}}" alt="{{member.name}}" class="w-24 h-24 rounded-full mx-auto">
    <h3 class="text-lg font-semibold mt-4">{{member.name}}</h3>
    <p class="text-sm text-gray-500">{{member.role}}</p>
  </div>
</div>

Testimonials mit Rating

json
{
  "props": {
    "testimonials": {
      "type": "array",
      "default": [
        {
          "author": "John Doe",
          "company": "Acme Inc",
          "text": "Great product!",
          "rating": 5
        }
      ]
    }
  }
}
html
<div class="testimonials">
  <div wm:for="testimonial in testimonials" class="testimonial-card p-6 bg-white rounded-lg shadow">
    <p class="text-gray-700 mb-4">"{{testimonial.text}}"</p>

    <!-- Rating Stars -->
    <div class="rating">
      <!-- Zeige rating Stars (vereinfacht) -->
      <span class="text-yellow-400">★★★★★</span>
    </div>

    <div class="author mt-4">
      <p class="font-semibold">{{testimonial.author}}</p>
      <p class="text-sm text-gray-500">{{testimonial.company}}</p>
    </div>
  </div>
</div>

Pricing Tiers

json
{
  "props": {
    "tiers": {
      "type": "array",
      "default": [
        {
          "name": "Basic",
          "price": 9,
          "features": ["Feature A", "Feature B"]
        },
        {
          "name": "Pro",
          "price": 29,
          "features": ["Feature A", "Feature B", "Feature C"]
        }
      ]
    }
  }
}
html
<div class="pricing-grid">
  <div wm:for="tier in tiers" class="tier-card">
    <h3>{{tier.name}}</h3>
    <p class="price">${{tier.price}}/month</p>

    <!-- Nested Loop für Features -->
    <ul>
      <li wm:for="feature in tier.features">
        {{feature}}
      </li>
    </ul>

    <button class="btn">Choose {{tier.name}}</button>
  </div>
</div>

Auto-Created Props

Props werden automatisch erstellt wenn du wm:for verwendest:

html
<!-- Props werden automatisch über wm dev verwaltet -->
<div wm:for="item in products">
  {{item.name}}
</div>

Automatisch erstellt:

json
{
  "props": {
    "products": {
      "type": "array",
      "label": "products",
      "items": { "type": "object" }
    }
  }
}

TIP

Props können über wm dev mit besserer Struktur konfiguriert werden.

Kombinationen

Loop mit Conditional

html
<div wm:for="item in items">
  <h3>{{item.name}}</h3>

  <!-- Nur anzeigen wenn verfügbar -->
  <span wm:if="item.inStock" class="badge-success">In Stock</span>
  <span wm:if="!item.inStock" class="badge-danger">Out of Stock</span>
</div>

Nested Loops

html
<div wm:for="category in categories">
  <h2>{{category.name}}</h2>

  <!-- Produkte in Kategorie -->
  <div wm:for="product in category.products">
    <p>{{product.name}}</p>
  </div>
</div>

Best Practices

1. Beschreibende Variablennamen

html
<!-- ✓ Klar -->
<div wm:for="product in products">

<!-- ✗ Generisch -->
<div wm:for="item in items">

2. Semantisches HTML

html
<!-- ✓ Korrekt -->
<ul>
  <li wm:for="item in items">{{item.name}}</li>
</ul>

<!-- ✗ Falsch (div in ul) -->
<ul>
  <div wm:for="item in items">{{item.name}}</div>
</ul>

3. Grid Layouts mit Tailwind

html
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
  <div wm:for="item in items" class="col-span-1">
    {{item.name}}
  </div>
</div>

4. Unique Keys (via Index)

Für Animationen oder dynamische Updates:

html
<div wm:for="item, index in items" data-key="{{index}}">
  {{item.name}}
</div>

Häufige Patterns

Blog Posts

json
{
  "props": {
    "posts": {
      "type": "array",
      "default": [
        {
          "title": "First Post",
          "excerpt": "This is the first post",
          "date": "2025-01-15",
          "author": "John Doe"
        }
      ]
    }
  }
}
html
<div class="blog-posts">
  <article wm:for="post in posts" class="post-card">
    <h2 class="text-2xl font-bold">{{post.title}}</h2>
    <p class="text-sm text-gray-500">
      By {{post.author}} on {{post.date}}
    </p>
    <p class="mt-4">{{post.excerpt}}</p>
    <a href="/blog/{{post.slug}}" class="btn-link">Read More</a>
  </article>
</div>
json
{
  "props": {
    "images": {
      "type": "array",
      "default": [
        { "url": "/images/1.jpg", "alt": "Image 1" },
        { "url": "/images/2.jpg", "alt": "Image 2" }
      ]
    }
  }
}
html
<div class="gallery grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
  <img
    wm:for="image in images"
    src="{{image.url}}"
    alt="{{image.alt}}"
    class="w-full h-64 object-cover rounded-lg"
    loading="lazy"
  >
</div>
json
{
  "props": {
    "menuItems": {
      "type": "array",
      "default": [
        { "label": "Home", "url": "/" },
        { "label": "About", "url": "/about" },
        { "label": "Contact", "url": "/contact" }
      ]
    }
  }
}
html
<nav>
  <ul class="flex gap-4">
    <li wm:for="item in menuItems">
      <a href="{{item.url}}" class="hover:text-blue-600">
        {{item.label}}
      </a>
    </li>
  </ul>
</nav>

Leere Listen

Mit Conditional prüfen:

json
{
  "props": {
    "hasItems": {
      "type": "boolean",
      "default": false
    },
    "items": {
      "type": "array",
      "default": []
    }
  }
}
html
<!-- Liste -->
<div wm:if="hasItems">
  <ul>
    <li wm:for="item in items">{{item.name}}</li>
  </ul>
</div>

<!-- Fallback für leere Liste -->
<div wm:if="!hasItems">
  <p class="text-gray-500">Keine Items vorhanden</p>
</div>

Nächste Schritte

Webmate Studio Component Development Dokumentation