Skip to main content
Logo
Explore APIsContact Us
  • Home
  • Match Preview
  • Tournament Preview
  • Virtual Stadium
  1. Resources
  2. Widgets
  3. Conditional Widget Display With Error Handling

Conditional Widget Display With Error Handling

#Intended Audience

This tutorial is for:

  • Frontend developers building conditional UI elements that depend on widget state
  • UX engineers creating graceful error handling experiences
  • Developers familiar with basic widget integration and onTrack callbacks
  • Those building tab interfaces, conditional buttons, or dynamic widget displays

#Goals

By completing this tutorial, you will:

  • Understand when and why to display widgets conditionally
  • Implement hidden widget loading with error detection
  • Use onTrack callback to detect successful widget initialization
  • Display UI controls only when widgets load successfully
  • Move widgets between DOM containers dynamically
  • Handle widget errors without showing broken UI elements

#Prerequisites

Before starting this tutorial, ensure you have:

  • Valid Sportradar Widget license - Contact Sales if needed
  • Basic HTML/CSS/JavaScript knowledge - DOM manipulation, event handling, element styling
  • Completed Widget Loading Tutorial - Understanding of onTrack callback
  • Web development environment - Text editor and modern browser with DevTools
info

This tutorial builds on the concepts from the Adding Loading Indicators tutorial. If you're new to onTrack callbacks, review that tutorial first.


#Overview

#The Challenge

In many UX scenarios, you want to show UI controls (buttons, tabs, toggles) only when the associated widget loads successfully:

  • Tab interfaces - Display tabs only for widgets that loaded without errors
  • Toggle buttons - Show "Show Widget" buttons only if the widget is available
  • Conditional features - Enable features that depend on widget data
warning

Using the silent error mode hides errors but doesn't help you conditionally display UI elements. You need programmatic error detection.

#The Solution

Load widgets in a hidden container, check for successful initialization using onTrack, then move them to the visible area and display related controls only if no errors occurred.


#Tutorial Steps

#Step 1: Set up HTML Structure With Hidden Containers

Create two separate areas: a hidden loading area for widgets, and a visible content area for UI controls.

html
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Conditional Widget Display</title>
    <style>
        #your-content {
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;
        }
    </style>
</head>
<body>
    <!-- Visible content area -->
    <div id="your-content">
        <!-- Button hidden initially, shown only if widget loads successfully -->
        <button id="toggle" style="display: none">Toggle widget display</button>
    </div>
    
    <!-- Hidden loading area for widgets -->
    <div id="loading-area" style="display: none">
        <div id="widget" class="sr-widget" style="display: none"></div>
    </div>
</body>
</html>

#Understanding the Structure

Visible Content Area

#your-content - Contains UI controls that should only appear when the widget loads successfully. Initially, the button is hidden.

Hidden Loading Area

#loading-area - Hidden container where widgets load. This prevents users from seeing widgets during initialization or if errors occur.

Widget Container

#widget - The actual widget element, initially hidden with display: none within the hidden loading area.

tip

This double-hiding approach (loading area hidden AND widget hidden) gives you fine-grained control over when and where the widget appears.


#Step 2: Get DOM Element References

Obtain references to all HTML elements you'll need to manipulate.

js
// Get the HTML elements from the document
const loadingArea = document.getElementById('loading-area');
const pageContent = document.getElementById('your-content');
const widget = document.getElementById('widget');
const button = document.getElementById('toggle');

#Step 3: Initialize the Widgetloader

Load the widget framework with your configuration.

js
(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/betradar/widgetloader", "SIR", {
    theme: false,
    language: "en"
});

#Step 4: Implement the onTrack Callback With Error Detection

Create a callback that listens for successful widget loading and moves the widget to the visible area.

js
// Function to listen to widget events
const onTrack = (eventType, data) => {
    if (eventType === 'data_change') {
        if (!data.error) {
            // Widget loaded successfully - move it to visible area
            loadingArea.removeChild(widget);
            pageContent.appendChild(widget);
            button.style.display = 'block';
        }
        // If data.error exists, widget stays hidden and button stays hidden
    }
}

#What Happens Here

Understanding the Logic Flow

  1. Wait for data_change event - Fired when widget receives data (successful or error)
  2. Check for errors - !data.error means no errors occurred
  3. Move widget to visible area - Remove from loading area, append to content area
  4. Show the button - Display the toggle control
  5. On error - Widget and button both remain hidden
info

The widget continues to exist in the hidden loading area if an error occurs. Users never see broken widgets or empty spaces.


#Step 5: Implement Toggle Functionality

Create a function to toggle widget visibility when the button is clicked.

js
// Toggle widget visibility on button click
const onWidgetToggle = () => {
    widget.style.display = widget.style.display === 'none' ? 'block' : 'none';
}
button.onclick = onWidgetToggle;
note

This toggle function only becomes accessible because the button is only displayed when the widget loaded successfully.


#Step 6: Load the Widget With Configuration

Initialize the widget with the onTrack callback.

js
SIR("addWidget", "#widget", "match.scoreboard", {
    matchId: 43406689,
    onTrack: onTrack
});

#Complete Implementation

View Complete Working Example

html
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Conditional Widget Display</title>
    <style>
        #your-content {
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;
        }
    </style>
</head>
<body>
    <div id="your-content">
        <button id="toggle" style="display: none">Toggle widget display</button>
    </div>
    
    <!-- Load widgets in hidden area -->
    <div id="loading-area" style="display: none">
        <div id="widget" class="sr-widget" style="display: none"></div>
    </div>

    <script>
        // Get DOM element references
        const loadingArea = document.getElementById('loading-area');
        const pageContent = document.getElementById('your-content');
        const widget = document.getElementById('widget');
        const button = document.getElementById('toggle');

        // Initialize widgetloader
        (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/betradar/widgetloader", "SIR", {
            theme: false,
            language: "en"
        });

        // onTrack callback with error detection
        const onTrack = (eventType, data) => {
            if (eventType === 'data_change') {
                if (!data.error) {
                    loadingArea.removeChild(widget);
                    pageContent.appendChild(widget);
                    button.style.display = 'block';
                }
            }
        }

        // Toggle widget visibility
        const onWidgetToggle = () => {
            widget.style.display = widget.style.display === 'none' ? 'block' : 'none';
        }
        button.onclick = onWidgetToggle;

        // Load widget with onTrack callback
        SIR("addWidget", "#widget", "match.scoreboard", {
            matchId: 43406689,
            onTrack: onTrack
        });
    </script>
</body>
</html>

#Advanced Use Cases

#Loading Multiple Widgets With Conditional Display

You can extend this pattern to handle multiple widgets:

js
const widgets = [
    { id: 'widget-1', matchId: 43406689 },
    { id: 'widget-2', matchId: 43406690 },
    { id: 'widget-3', matchId: 43406691 }
];

const createOnTrack = (widgetId, buttonId) => {
    return (eventType, data) => {
        if (eventType === 'data_change' && !data.error) {
            const widget = document.getElementById(widgetId);
            const button = document.getElementById(buttonId);
            const loadingArea = document.getElementById('loading-area');
            const pageContent = document.getElementById('your-content');
            
            loadingArea.removeChild(widget);
            pageContent.appendChild(widget);
            button.style.display = 'block';
        }
    };
};

// Load each widget with its own callback
widgets.forEach((config, index) => {
    SIR("addWidget", `#${config.id}`, "match.scoreboard", {
        matchId: config.matchId,
        onTrack: createOnTrack(config.id, `toggle-${index}`)
    });
});

#Error Logging and Fallback Content

Handle errors explicitly with custom messaging:

js
const onTrack = (eventType, data) => {
    if (eventType === 'data_change') {
        if (!data.error) {
            // Success: move widget and show controls
            loadingArea.removeChild(widget);
            pageContent.appendChild(widget);
            button.style.display = 'block';
        } else {
            // Error: log and show fallback
            console.error('Widget failed to load:', data.error);
            
            // Optional: Show fallback message
            const fallback = document.createElement('div');
            fallback.className = 'widget-error-message';
            fallback.textContent = 'Content temporarily unavailable';
            pageContent.appendChild(fallback);
        }
    }
};

#Troubleshooting

#Issue: Button Appears but Widget Doesn't

Symptom: The toggle button shows up, but clicking it doesn't display the widget.

Cause: The widget wasn't properly moved from the loading area.

Solution: Verify the DOM manipulation in your onTrack callback:

js
// Check in browser console
console.log('Widget parent:', widget.parentElement);
// Should show #your-content, not #loading-area

#Issue: Widget Shows Briefly Then Disappears

Symptom: Widget flashes on screen then vanishes.

Cause: Multiple data_change events firing without proper flag management.

Solution: Add a flag to track widget movement:

js
let widgetMoved = false;

const onTrack = (eventType, data) => {
    if (eventType === 'data_change' && !data.error && !widgetMoved) {
        loadingArea.removeChild(widget);
        pageContent.appendChild(widget);
        button.style.display = 'block';
        widgetMoved = true;
    }
};

#Issue: Console Errors About removeChild

Symptom: Uncaught DOMException: Failed to execute 'removeChild'

Cause: Trying to remove a widget that isn't a child of the loading area.

Solution: Check parent before removing:

js
if (widget.parentElement === loadingArea) {
    loadingArea.removeChild(widget);
    pageContent.appendChild(widget);
}

#Key Takeaways

Hidden Loading Area

Load widgets in a hidden container to prevent displaying broken widgets or errors. Only move them to visible areas after confirming successful initialization.

Error Detection

Use !data.error in the onTrack callback to programmatically detect successful widget loading before showing UI controls.

DOM Manipulation

Moving widgets between containers with removeChild and appendChild gives you full control over when and where widgets appear.


#Further Reading

#Core Documentation

  • Widget Events (onTrack) - Complete event reference and all event types
  • Error Handling Guide - Comprehensive error handling strategies
  • Widget Configuration - All widget configuration options

#Related Tutorials

  • Adding Loading Indicators - Basic onTrack usage for loading states
  • Widget Visibility in Carousels - Managing visibility in dynamic layouts

#Advanced Topics

  • Silent Error Mode - When to use silent mode vs programmatic detection
  • Dynamic Widget Loading - Loading widgets on demand
  • Performance Best Practices - Optimizing widget loading
Last updated 14 days ago
Is this site helpful?
Widgets, Engagement Tools
Adding Loading Indicators to WidgetsWidget Rotation and Dynamic Match Switching
On this page
  • Intended Audience
  • Goals
  • Prerequisites
  • Overview
  • The Challenge
  • The Solution
  • Tutorial Steps
  • Step 1: Set up HTML Structure With Hidden Containers
  • Step 2: Get DOM Element References
  • Step 3: Initialize the Widgetloader
  • Step 4: Implement the onTrack Callback With Error Detection
  • Step 5: Implement Toggle Functionality
  • Step 6: Load the Widget With Configuration
  • Complete Implementation
  • Advanced Use Cases
  • Loading Multiple Widgets With Conditional Display
  • Error Logging and Fallback Content
  • Troubleshooting
  • Issue: Button Appears but Widget Doesn't
  • Issue: Widget Shows Briefly Then Disappears
  • Issue: Console Errors About removeChild
  • Key Takeaways
  • Further Reading
  • Core Documentation
  • Related Tutorials
  • Advanced Topics