Skip to content

Power Helpers

Power helpers are utility functions that extend Olova's functionality. They can be used in templates, directives, and expressions to transform data, format values, or provide reusable logic.

Basic Usage

js
const app = createApp({
  data: {
    price: 99.99,
    items: ['Apple', 'Banana']
  }
});

app.power({
  // Add your helper functions here
  uppercase: (str) => str.toUpperCase(),
  currency: (num) => `$${num.toFixed(2)}`
});
html
<!-- Use in templates -->
<div>{uppercase(items[0])}</div>      <!-- Output: APPLE -->
<div>{currency(price)}</div>          <!-- Output: $99.99 -->

Helper Types

  1. Value Transformers Transform data into different formats.
js
app.power({
  // Number formatting
  currency: (value, currency = 'USD') => 
    new Intl.NumberFormat('en-US', {
      style: 'currency',
      currency
    }).format(value),

  // Date formatting
  dateFormat: (date) => 
    new Intl.DateTimeFormat('en-US').format(date),

  // String manipulation
  truncate: (text, length = 20) => 
    text.length > length ? `${text.slice(0, length)}...` : text
});
html
<div>{currency(99.99)}</div>              <!-- $99.99 -->
<div>{currency(99.99, 'EUR')}</div>       <!-- €99.99 -->
<div>{dateFormat(new Date())}</div>       <!-- 3/14/2024 -->
<div>{truncate('Long text here', 10)}</div><!-- Long text... -->
  1. Computed Values Helpers that perform calculations.
js
app.power({
  tax: (amount, rate = 0.08) => amount * rate,
  total: (price, quantity) => price * quantity,
  discount: (price, percent) => price * (1 - percent/100)
});
html
<div>Tax: {tax(price)}</div>
<div>Total: {total(price, quantity)}</div>
<div>Sale Price: {discount(price, 20)}</div>
  1. Static Values Constants that can be used throughout your app.
js
app.power({
  TAX_RATE: 0.08,
  SHIPPING_RATES: {
    standard: 5.99,
    express: 15.99
  },
  STATUS_CODES: {
    active: 'ACTIVE',
    pending: 'PENDING',
    inactive: 'INACTIVE'
  }
});
html
<div>Tax: {price * TAX_RATE}</div>
<div>Shipping: {SHIPPING_RATES.standard}</div>

Advanced Features

Dynamic Expressions Helpers can use expressions in curly braces to access state.

js
app.power({
  total: (price) => `{price * quantity}`,  // References state.quantity
  greeting: (name) => `Hello, {username || name}!`  // Uses fallback
});

Chaining Helpers Combine multiple helpers for complex transformations.

js
app.power({
  double: x => x * 2,
  addTax: x => x * (1 + TAX_RATE),
  format: x => `$${x.toFixed(2)}`
});
html
<div>{format(addTax(double(price)))}</div>

Best Practices

js
// Good ✅
app.power({
  calculateTotal: (price, quantity) => price * quantity
});

// Bad ❌
app.power({
  calculateTotal: (price) => price * globalQuantity
});
  1. Use Descriptive Names
js
// Good ✅
app.power({
  formatCurrency: (value) => `$${value.toFixed(2)}`,
  calculateTaxAmount: (price) => price * 0.08
});

// Bad ❌
app.power({
  fmt: (v) => `$${v.toFixed(2)}`,
  calc: (p) => p * 0.08
});
  1. Handle Errors Gracefully
js
app.power({
  safeDiv: (a, b) => {
    try {
      if (b === 0) return 'Cannot divide by zero';
      return a / b;
    } catch (error) {
      console.error('Division error:', error);
      return 'Error';
    }
  }
});

Common Use Cases

  1. Form Validation
js
app.power({
  isEmail: (email) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email),
  isRequired: (value) => !!value && value.trim() !== '',
  minLength: (value, min) => value.length >= min
});
  1. Data Formatting
js
app.power({
  phoneFormat: (phone) => {
    const cleaned = phone.replace(/\D/g, '');
    return `(${cleaned.slice(0,3)}) ${cleaned.slice(3,6)}-${cleaned.slice(6)}`;
  },
  
  fileSize: (bytes) => {
    const sizes = ['B', 'KB', 'MB', 'GB'];
    let i = 0;
    while (bytes >= 1024 && i < sizes.length - 1) {
      bytes /= 1024;
      i++;
    }
    return `${bytes.toFixed(1)} ${sizes[i]}`;
  }
});
  1. UI Helpers
js
app.power({
  classNames: (...classes) => 
    classes.filter(Boolean).join(' '),
    
  pluralize: (count, singular, plural) => 
    count === 1 ? singular : (plural || `${singular}s`),
    
  timeAgo: (date) => {
    const seconds = Math.floor((new Date() - date) / 1000);
    const intervals = {
      year: 31536000,
      month: 2592000,
      week: 604800,
      day: 86400,
      hour: 3600,
      minute: 60
    };
    
    for (const [unit, secondsInUnit] of Object.entries(intervals)) {
      const interval = Math.floor(seconds / secondsInUnit);
      if (interval >= 1) {
        return `${interval} ${unit}${interval === 1 ? '' : 's'} ago`;
      }
    }
    return 'just now';
  }
});