Skip to content

board.props - Component Configuration

Read configuration values set by the board host through the Props Editor.

Overview

board.props provides read-only access to component configuration. Props are set by the board host and cannot be changed by the component itself.

Think of props as component settings - like a YouTube video's title, autoplay setting, or volume level.

Basic Operations

get() - Read Prop Value

typescript
// Get prop value (returns undefined if not set)
const title = board.props.get<string>('title');

// Get with default value
const maxClicks = board.props.get<number>('maxClicks', 10);
const theme = board.props.get<string>('theme', 'light');

getAll() - Get All Props

typescript
const allProps = board.props.getAll();

console.log(allProps);
/*
{
  title: 'Team Voting',
  maxClicks: 10,
  theme: 'dark',
  showTimer: true
}
*/

Subscriptions

subscribe() - Watch for Changes

Props can change when the host updates settings through the Props Editor:

typescript
// Subscribe to specific prop
board.props.subscribe('title', (newTitle, oldTitle) => {
  console.log(`Title changed: ${oldTitle} → ${newTitle}`);
  document.querySelector('h1').textContent = newTitle;
});

// Subscribe to theme changes
board.props.subscribe('theme', (newTheme) => {
  document.body.className = newTheme; // 'light' or 'dark'
});

TypeScript Support

Define your component's prop types:

typescript
interface MyComponentProps {
  title: string;
  maxClicks: number;
  theme: 'light' | 'dark';
  showTimer: boolean;
}

const board = new BoardAPI<any, MyComponentProps>();

// Now fully typed!
const title = board.props.get('title');     // string | undefined
const theme = board.props.get('theme');     // 'light' | 'dark' | undefined
const props = board.props.getAll();         // MyComponentProps

Examples

Configurable Timer

typescript
import { BoardAPI } from '@boardapi/sdk';

interface TimerProps {
  duration: number;      // seconds
  autoStart: boolean;
  showMilliseconds: boolean;
}

const board = new BoardAPI<any, TimerProps>();

board.on('ready', () => {
  // Read initial config
  const duration = board.props.get('duration', 60);
  const autoStart = board.props.get('autoStart', false);
  const showMs = board.props.get('showMilliseconds', false);

  initTimer(duration, autoStart, showMs);
});

// React to config changes
board.props.subscribe('duration', (newDuration) => {
  resetTimer(newDuration);
});

board.props.subscribe('showMilliseconds', (show) => {
  updateDisplay(show);
});

Themed Component

typescript
interface ThemeProps {
  primaryColor: string;
  secondaryColor: string;
  fontSize: 'small' | 'medium' | 'large';
  darkMode: boolean;
}

const board = new BoardAPI<any, ThemeProps>();

function applyTheme() {
  const props = board.props.getAll<ThemeProps>();

  // Apply colors
  document.documentElement.style.setProperty('--primary', props.primaryColor || '#3B82F6');
  document.documentElement.style.setProperty('--secondary', props.secondaryColor || '#10B981');

  // Apply font size
  const fontSizes = { small: '14px', medium: '16px', large: '18px' };
  document.documentElement.style.setProperty('--font-size', fontSizes[props.fontSize || 'medium']);

  // Apply dark mode
  document.body.classList.toggle('dark', props.darkMode);
}

board.on('ready', applyTheme);

// Re-apply when host changes settings
board.props.subscribe('primaryColor', applyTheme);
board.props.subscribe('secondaryColor', applyTheme);
board.props.subscribe('fontSize', applyTheme);
board.props.subscribe('darkMode', applyTheme);

Quiz Component with Config

typescript
interface QuizProps {
  question: string;
  options: string[];
  correctAnswer: number;
  showFeedback: boolean;
  allowMultipleAttempts: boolean;
}

const board = new BoardAPI<any, QuizProps>();

board.on('ready', () => {
  const props = board.props.getAll<QuizProps>();

  // Render question
  document.querySelector('#question').textContent = props.question;

  // Render options
  const optionsContainer = document.querySelector('#options');
  props.options?.forEach((option, index) => {
    const button = document.createElement('button');
    button.textContent = option;
    button.onclick = () => checkAnswer(index);
    optionsContainer.appendChild(button);
  });
});

function checkAnswer(selected: number) {
  const correctAnswer = board.props.get('correctAnswer');
  const showFeedback = board.props.get('showFeedback', true);

  if (selected === correctAnswer) {
    if (showFeedback) {
      board.ui.showToast('Correct!', { type: 'success' });
    }
  } else {
    const allowRetry = board.props.get('allowMultipleAttempts', true);

    if (showFeedback) {
      const message = allowRetry ? 'Try again!' : 'Incorrect';
      board.ui.showToast(message, { type: 'error' });
    }

    if (!allowRetry) {
      disableOptions();
    }
  }
}

Data Source Configuration

typescript
interface DataSourceProps {
  apiUrl: string;
  refreshInterval: number;  // seconds
  maxItems: number;
}

const board = new BoardAPI<any, DataSourceProps>();

let refreshTimer: number;

async function fetchData() {
  const apiUrl = board.props.get('apiUrl');
  const maxItems = board.props.get('maxItems', 10);

  if (!apiUrl) return;

  const response = await fetch(apiUrl);
  const data = await response.json();

  renderData(data.slice(0, maxItems));
}

function startAutoRefresh() {
  const interval = board.props.get('refreshInterval', 60);

  // Clear existing timer
  if (refreshTimer) {
    clearInterval(refreshTimer);
  }

  // Start new timer
  refreshTimer = setInterval(fetchData, interval * 1000);
}

board.on('ready', () => {
  fetchData();
  startAutoRefresh();
});

// Update data source when config changes
board.props.subscribe('apiUrl', fetchData);
board.props.subscribe('maxItems', fetchData);
board.props.subscribe('refreshInterval', startAutoRefresh);

Defining Props in manifest.json

Props are defined in your component's manifest.json:

json
{
  "name": "my-component",
  "version": "1.0.0",
  "props": {
    "title": {
      "type": "string",
      "default": "My Component",
      "label": "Title",
      "description": "Component title"
    },
    "maxClicks": {
      "type": "number",
      "default": 10,
      "min": 1,
      "max": 100,
      "label": "Max Clicks"
    },
    "theme": {
      "type": "string",
      "enum": ["light", "dark"],
      "default": "light",
      "label": "Theme"
    },
    "showTimer": {
      "type": "boolean",
      "default": true,
      "label": "Show Timer"
    }
  }
}

The Props Editor in the platform will automatically generate a UI for these settings.

Props vs Storage

FeaturePropsStorage
Set byHost (via Props Editor)Component code
WriteableNo (read-only)Yes
Use caseConfiguration, settingsUser data, state
ExamplesTitle, color, max itemsCounter, votes, form data

Best Practices

  1. Always provide defaults - Use get(key, default) syntax
  2. Subscribe to changes - Re-render when host updates settings
  3. Validate prop values - Host might set invalid values
  4. Document props - Add clear descriptions in manifest.json
  5. Use enums for choices - Limit options in manifest.json

What's Next?