---
title: "Widget Rotation and Dynamic Match Switching"
canonical_url: "https://apidocs.sportradar.com/resources/widgets/docs/tutorials/examples/example-widget-rotator"
markdown_url: "https://apidocs.sportradar.com/resources/widgets/docs/tutorials/examples/example-widget-rotator.md"
last_updated: "2026-09-04T14:40:42Z"
---

# Widget Rotation and Dynamic Match Switching

## Intended Audience

This tutorial is for:

- **Frontend developers** building dynamic widget displays with automatic rotation
- **Integration engineers** creating live match dashboards or multi-match displays
- Developers familiar with [basic widget integration](https://apidocs.sportradar.com/resources/widgets/docs/tutorials.md)
- Those building rotating content carousels or live match rotation systems

## Goals

By completing this tutorial, you will:

- Understand how to dynamically update widget content by changing match IDs
- Implement automatic widget rotation with timed intervals
- Use the `addWidget` method to update existing widgets
- Remove widgets programmatically using `removeWidget`
- Manage widget lifecycle with start/stop controls
- Build a complete rotating widget system

## Prerequisites

Before starting this tutorial, ensure you have:

- **Valid Sportradar Widget license** - Contact [Sales](mailto:sales@betradar.com) if needed
- **Multiple match IDs** - At least 2-3 valid match identifiers for rotation
- **Basic HTML/CSS/JavaScript knowledge** - Arrays, intervals, DOM manipulation
- **Completed [Getting Started Guide](https://apidocs.sportradar.com/resources/widgets/docs/tutorials.md)** - Understanding of basic widget integration
- **Web development environment** - Text editor and modern browser

> **Info**
>
> This tutorial uses the [Live Match Tracker](https://apidocs.sportradar.com/resources/widgets/docs/tutorials/lmt/Widgets.match.LMTPlus.md) widget, but the rotation technique works with any widget type.

***

## Overview

### The Use Case

Widget rotation is useful for:

- **Live match dashboards** - Cycle through multiple live matches
- **Featured content rotation** - Highlight different matches/tournaments
- **Space-efficient displays** - Show multiple matches in a single widget area
- **Digital signage** - Automatic content rotation for displays

### How It Works

When you call `addWidget` with the same target element but different configuration (e.g., different `matchId`), the widget framework:

1. Detects the existing widget in that element
2. Updates the widget with the new configuration
3. Re-renders with the new data

> **Tip**
>
> Calling `addWidget` multiple times on the same element **updates** the widget rather than creating duplicates.

***

## Tutorial Steps

### Step 1: Set up HTML Structure

Create a simple page with a widget container and control button.

```html {12-14}
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Widget Rotator</title>
    <style>
        .sr-widget {
            width: 620px;
        }
    </style>
</head>
<body>
    <div class="sr-widget"></div>
    <button onclick="endThisThing()">Remove Widget</button>
</body>
</html>
```

***

### Step 2: Initialize the Widgetloader

Load the widget framework and configure your match IDs array.

```js {8-10}
(function(a,b,c,d,e,f,g,h,i){a[e]||(i=a[e]=function(){(a[e].q=a[e].q||[]).push(arguments)},i.l=1*new Date,i.o=f,
g=b.createElement(c),h=b.getElementsByTagName(c)[0],g.async=1,g.src=d,g.setAttribute("n",e),h.parentNode.insertBefore(g,h)
)})(window,document,"script","https://widgets.sir.sportradar.com/sportradar/widgetloader","SIR", {
    language: 'en'
});

// Configure match IDs for rotation
let matchIds = [41960917, 41960918, 41960919]; // Replace with your match IDs
let ix = 0;  // Current index in the array
let interval; // Will hold the interval timer
```

> **Warning**
>
> Replace the example match IDs with valid match IDs from your license. Using invalid IDs will result in widget errors.

***

### Step 3: Create the Widget Update Function

Implement a function that adds or updates the widget with the next match ID.

```js {2,4-5}
function addOrUpdateWidget(callback) {
    SIR('addWidget', '.sr-widget', 'match.lmtPlus', { matchId: matchIds[ix] }, callback);
    
    // Move to next match ID, wrap to start if at end
    if (++ix >= matchIds.length) { ix = 0; }
}
```

#### Understanding the Logic

**How Widget Updating Works**

1. **Call `addWidget`** - With the current `matchId` from the array
2. **Widget framework detects** - Element `.sr-widget` already contains a widget
3. **Widget updates** - Instead of creating a new widget, it updates the existing one
4. **Index increments** - Move to the next match ID for the next rotation
5. **Array wraps** - When reaching the end, reset to index 0

> **Info**
>
> The optional `callback` parameter allows you to perform actions after the widget loads, such as starting the rotation timer.

***

### Step 4: Start the Rotation

Load the first widget and start the automatic rotation timer.

```js {2-4}
// Load first widget, then start rotation
addOrUpdateWidget(function() {
    // Start rotating every 3 seconds (3000ms)
    interval = setInterval(addOrUpdateWidget, 3000);
});
```

> **Tip**
>
> **Why use a callback?** This ensures the first widget loads before starting the rotation timer, preventing rapid initial updates.

#### Adjusting Rotation Speed

Change the interval duration to control rotation speed:

```js
// Slower rotation - every 5 seconds
interval = setInterval(addOrUpdateWidget, 5000);

// Faster rotation - every 1 second
interval = setInterval(addOrUpdateWidget, 1000);
```

***

### Step 5: Implement Widget Removal

Create a function to stop rotation and remove the widget from the page.

```js {2-6}
function endThisThing() {
    // Stop the rotation timer
    clearInterval(interval);
    
    // Remove the widget from the page
    SIR('removeWidget', '.sr-widget');
    // Alternative: pass DOM element directly
    // SIR('removeWidget', document.querySelector('.sr-widget'));
}
```

#### removeWidget Options

**CSS Selector**

```js
SIR('removeWidget', '.sr-widget');
```

Pass a CSS selector string. The framework will find and remove the widget.

**DOM Element**

```js
SIR('removeWidget', document.querySelector('.sr-widget'));
```

Pass the DOM element directly for more precise control.

> **Danger**
>
> **Always clear intervals before removing widgets** to prevent memory leaks and errors from the interval trying to update a non-existent widget.

***

## Complete Implementation

**View Complete Working Example**

```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Widget Rotator</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            padding: 20px;
        }
        .sr-widget {
            width: 620px;
            margin-bottom: 20px;
        }
        button.rotator {
            padding: 10px 20px;
            background-color: #e74c3c;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
        }
        button.rotator:hover {
            background-color: #c0392b;
        }
    </style>
</head>
<body>
    <h1>Live Match Rotation</h1>
    <div class="sr-widget"></div>
    <button class="rotator" onclick="endThisThing()">Stop & Remove Widget</button>

    <script>
        (function(a,b,c,d,e,f,g,h,i){a[e]||(i=a[e]=function(){(a[e].q=a[e].q||[]).push(arguments)},i.l=1*new Date,i.o=f,
        g=b.createElement(c),h=b.getElementsByTagName(c)[0],g.async=1,g.src=d,g.setAttribute("n",e),h.parentNode.insertBefore(g,h)
        )})(window,document,"script","https://widgets.sir.sportradar.com/sportradar/widgetloader","SIR", {
            language: 'en'
        });

        // Configure match IDs for rotation
        let matchIds = [41960917, 41960918, 41960919];
        let ix = 0;
        let interval;

        // Function to add or update widget
        function addOrUpdateWidget(callback) {
            SIR('addWidget', '.sr-widget', 'match.lmtPlus', { matchId: matchIds[ix] }, callback);
            if (++ix >= matchIds.length) { ix = 0; }
        }

        // Start rotation
        addOrUpdateWidget(function() {
            interval = setInterval(addOrUpdateWidget, 3000);
        });

        // Stop rotation and remove widget
        function endThisThing() {
            clearInterval(interval);
            SIR('removeWidget', document.querySelector('.sr-widget'));
        }
    </script>
</body>
</html>
```

***

## Advanced Variations

### Pause/Resume Functionality

Add controls to pause and resume rotation:

```js
let isPaused = false;

function toggleRotation() {
    if (isPaused) {
        // Resume rotation
        interval = setInterval(addOrUpdateWidget, 3000);
        isPaused = false;
    } else {
        // Pause rotation
        clearInterval(interval);
        isPaused = true;
    }
}
```

```html
<button onclick="toggleRotation()">Pause/Resume</button>
```

### Manual Navigation Controls

Add previous/next buttons for manual control:

```js
function nextWidget() {
    clearInterval(interval); // Stop auto-rotation
    addOrUpdateWidget();
}

function previousWidget() {
    clearInterval(interval); // Stop auto-rotation
    // Move back 2 positions (current increment + desired back step)
    ix = (ix - 2 + matchIds.length) % matchIds.length;
    addOrUpdateWidget();
}
```

```html
<button onclick="previousWidget()">← Previous</button>
<button onclick="nextWidget()">Next →</button>
```

### Rotating Different Widget Types

You can rotate between different widget types:

```js
let widgets = [
    { type: 'match.lmtPlus', config: { matchId: 41960917 } },
    { type: 'match.scoreboard', config: { matchId: 41960918 } },
    { type: 'tournament.standings', config: { tournamentId: 12345 } }
];

function addOrUpdateWidget(callback) {
    const current = widgets[ix];
    SIR('addWidget', '.sr-widget', current.type, current.config, callback);
    if (++ix >= widgets.length) { ix = 0; }
}
```

***

## Troubleshooting

### Issue: Widget Flickers During Rotation

**Symptom:** Brief blank screen between widget updates.

**Cause:** Widget needs time to fetch new data.

**Solution:** Increase rotation interval or add a loading state:

```js
function addOrUpdateWidget(callback) {
    // Show loading indicator
    document.querySelector('.sr-widget').classList.add('loading');
    
    SIR('addWidget', '.sr-widget', 'match.lmtPlus', { 
        matchId: matchIds[ix],
        onTrack: function(event, data) {
            if (event === 'data_change' && !data.error) {
                // Remove loading indicator when data loads
                document.querySelector('.sr-widget').classList.remove('loading');
            }
        }
    }, callback);
    
    if (++ix >= matchIds.length) { ix = 0; }
}
```

### Issue: Rotation Continues After Removal

**Symptom:** Console errors about missing elements after widget removal.

**Cause:** `clearInterval` wasn't called before `removeWidget`.

**Solution:** Always clear the interval first:

```js
function endThisThing() {
    // MUST clear interval before removing
    clearInterval(interval);
    SIR('removeWidget', '.sr-widget');
}
```

### Issue: Rotation Speed Changes Unexpectedly

**Symptom:** Widgets rotate faster or slower than expected.

**Cause:** Multiple intervals created without clearing previous ones.

**Solution:** Always clear existing interval before creating new one:

```js
function startRotation(speed) {
    // Clear any existing interval
    if (interval) {
        clearInterval(interval);
    }
    // Create new interval
    interval = setInterval(addOrUpdateWidget, speed);
}
```

***

## Key Takeaways

### Widget Updates

Calling `addWidget` on an element that already contains a widget updates the existing widget rather than creating duplicates.

### Interval Management

Always use `clearInterval` before removing widgets or starting new intervals to prevent memory leaks and errors.

### removeWidget Method

The `removeWidget` method accepts either a CSS selector string or a DOM element reference for flexible widget removal.

***

## Further Reading

### Core Documentation

- [Global SIR API Reference](https://apidocs.sportradar.com/resources/widgets/docs/tutorials/SIR.md) - Complete API including `removeWidget` method
- [LMT](https://apidocs.sportradar.com/resources/widgets/docs/lmt/lmt.md) - Real-time match visualization
- [Widget Configuration](https://apidocs.sportradar.com/resources/widgets/docs/tutorials/widgets-configuration.md) - All configuration options

### Related Tutorials

- [Widget Visibility in Carousels](https://apidocs.sportradar.com/resources/widgets/docs/tutorials/examples/example-widget-carousels-scrollers-sliders.md) - Managing visibility with display/visibility
- [Adding Loading Indicators](https://apidocs.sportradar.com/resources/widgets/docs/tutorials/examples/example-widget-loading.md) - Smooth transitions during updates
- [Conditional Widget Display](https://apidocs.sportradar.com/resources/widgets/docs/tutorials/examples/example-widget-ontrack-error.md) - Error handling during updates

### JavaScript Resources

- [MDN: setInterval](https://developer.mozilla.org/en-US/docs/Web/API/setInterval) - Interval timing documentation
- [MDN: clearInterval](https://developer.mozilla.org/en-US/docs/Web/API/clearInterval) - Clearing intervals
- [Array Iteration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) - Working with arrays
