or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

directives.mdindex.mdparameter-management.mdstate-configuration.mdstate-navigation.mdtransition-hooks.mdurl-management.mdview-management.md
tile.json

parameter-management.mddocs/

Parameter Management

Parameter type system and configuration for URL parameters and state parameters with validation, transformation, and encoding. UI-Router provides a comprehensive parameter system with built-in types and extensibility for custom parameter handling.

Capabilities

Parameter Declaration

Configure state and URL parameters with validation, default values, and behavior options.

/**
 * Parameter declaration for configuring state parameters
 */
interface ParamDeclaration {
  /** Default parameter value */
  value?: any;
  /** Parameter type name or ParamType instance */
  type?: string | ParamType;
  /** Array parameter configuration */
  array?: boolean | string;
  /** URL squashing behavior for default values */
  squash?: boolean | string;
  /** Dynamic parameter flag for change detection */
  dynamic?: boolean;
  /** Inherit parameter from parent state */
  inherit?: boolean;
  /** Disable URL encoding/decoding */
  raw?: boolean;
}

Usage Examples:

// Basic parameter configuration
$stateProvider.state('users', {
  url: '/users?page&sort&filter',
  params: {
    page: {
      type: 'int',
      value: 1,
      squash: true  // Remove from URL when default value
    },
    sort: {
      type: 'string',
      value: 'name',
      squash: false  // Always show in URL
    },
    filter: {
      type: 'string',
      value: '',
      squash: true
    }
  }
});

// Advanced parameter configuration
$stateProvider.state('search', {
  url: '/search/{query}?category&tags&options',
  params: {
    query: {
      type: 'string',
      value: null  // Required parameter
    },
    category: {
      type: 'string',
      value: 'all',
      squash: true
    },
    tags: {
      array: true,        // Accept multiple values
      value: [],
      squash: true
    },
    options: {
      type: 'json',       // JSON serialized object
      value: { limit: 10, offset: 0 },
      dynamic: true,      // Changes don't trigger state reload
      squash: true
    }
  }
});

Built-in Parameter Types

Predefined parameter types for common data formats and URL encoding needs.

/**
 * Built-in parameter types with automatic encoding/decoding
 */
type BuiltInParamTypes = 
  | 'string'    // Default string type
  | 'int'       // Integer numbers
  | 'bool'      // Boolean values (1/0, true/false)  
  | 'date'      // Date objects (ISO 8601 format)
  | 'json'      // JSON serialized objects
  | 'path'      // Path parameters (no forward slashes)
  | 'query'     // Query/search parameters
  | 'hash'      // Hash parameters
  | 'any';      // No encoding/decoding

Usage Examples:

// String parameters (default)
$stateProvider.state('profile', {
  url: '/profile/{username:string}',  // Explicit string type
  // username will be URL-decoded string
});

// Integer parameters
$stateProvider.state('product', {
  url: '/product/{id:int}',
  // id will be parsed as integer, invalid values rejected
});

// Boolean parameters  
$stateProvider.state('settings', {
  url: '/settings?debug&verbose',
  params: {
    debug: { type: 'bool', value: false },    // ?debug=1 or ?debug=true
    verbose: { type: 'bool', value: false }   // ?verbose=0 or ?verbose=false
  }
});

// Date parameters
$stateProvider.state('calendar', {
  url: '/calendar/{date:date}',
  // date will be parsed as Date object from ISO string
});

// JSON parameters for complex data
$stateProvider.state('report', {
  url: '/report?config',
  params: {
    config: {
      type: 'json',
      value: { format: 'pdf', includeCharts: true }
      // URL: ?config=%7B%22format%22%3A%22pdf%22%7D
    }
  }
});

// Path parameters (no slashes)
$stateProvider.state('file', {
  url: '/file/{filename:path}',
  // filename cannot contain forward slashes
});

// Any type (no processing)
$stateProvider.state('raw', {
  url: '/raw/{data:any}',
  // data passed through without encoding/decoding
});

Custom Parameter Types

Define custom parameter types for specialized data handling and validation.

/**
 * Custom parameter type definition
 */
interface ParamType {
  /** Encode parameter value for URL */
  encode(val: any): string;
  /** Decode parameter value from URL */
  decode(val: string): any;
  /** Check if value is valid for this type */
  is(val: any): boolean;
  /** Regular expression pattern for URL matching */
  pattern: RegExp;
  /** Check if two values are equal (optional) */
  equals?(a: any, b: any): boolean;
}

interface ParamTypeDefinition {
  encode?: (val: any) => string;
  decode?: (val: string) => any;
  is?: (val: any) => boolean;
  pattern?: RegExp;
  equals?: (a: any, b: any) => boolean;
}

Usage Examples:

// Custom slug parameter type
angular.module('myApp').config(['$urlServiceProvider', function($urlServiceProvider) {
  $urlServiceProvider.config.type('slug', {
    encode: function(val) {
      return val ? val.toLowerCase()
                     .replace(/[^a-z0-9]+/g, '-')
                     .replace(/^-|-$/g, '') : '';
    },
    decode: function(val) {
      return val ? val.replace(/-/g, ' ') : '';
    },
    is: function(val) {
      return typeof val === 'string' && /^[a-z0-9-]+$/.test(val);
    },
    pattern: /[a-z0-9-]+/
  });
  
  // Custom email parameter type
  $urlServiceProvider.config.type('email', {
    encode: function(val) {
      return val || '';
    },
    decode: function(val) {
      return val;
    },
    is: function(val) {
      return typeof val === 'string' && 
             /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val);
    },
    pattern: /[^@\s]+@[^@\s]+\.[^@\s]+/
  });
  
  // Custom coordinate parameter type
  $urlServiceProvider.config.type('coords', {
    encode: function(coords) {
      if (!coords || !coords.lat || !coords.lng) return '';
      return coords.lat + ',' + coords.lng;
    },
    decode: function(val) {
      if (!val) return null;
      const parts = val.split(',');
      return {
        lat: parseFloat(parts[0]),
        lng: parseFloat(parts[1])
      };
    },
    is: function(val) {
      return val && typeof val.lat === 'number' && typeof val.lng === 'number';
    },
    pattern: /-?\d+\.?\d*,-?\d+\.?\d*/,
    equals: function(a, b) {
      return a && b && a.lat === b.lat && a.lng === b.lng;
    }
  });
}]);

// Use custom parameter types
$stateProvider.state('article', {
  url: '/article/{slug:slug}',
  // slug will be encoded/decoded with custom logic
});

$stateProvider.state('contact', {
  url: '/contact/{email:email}',
  // email will be validated against email pattern
});

$stateProvider.state('map', {
  url: '/map/{center:coords}',
  // center will be encoded as "lat,lng" and decoded as {lat, lng}
});

Array Parameters

Handle multiple values for a single parameter using array configuration.

/**
 * Array parameter configuration
 */
interface ArrayParamConfig {
  /** Enable array mode */
  array?: boolean | string;
  /** Default array value */
  value?: any[];
  /** Array squashing behavior */
  squash?: boolean;
}

Usage Examples:

// Basic array parameters
$stateProvider.state('search', {
  url: '/search?tags&categories',
  params: {
    tags: {
      array: true,
      value: [],
      squash: true
    },
    categories: {
      array: true,
      value: ['all'],
      squash: false
    }
  }
});

// URLs with array parameters:
// /search?tags=javascript&tags=angular&tags=routing
// /search?tags[]=javascript&tags[]=angular (alternative syntax)
// /search?categories=tech&categories=tutorial

// Array with custom separator
$stateProvider.state('filter', {
  url: '/filter?ids',
  params: {
    ids: {
      array: ',',  // Use comma separator instead of repeated params
      value: [],
      type: 'int'  // Array of integers
    }
  }
});

// URL: /filter?ids=1,2,3,4

// Navigate with array parameters
$state.go('search', {
  tags: ['javascript', 'angular', 'ui-router'],
  categories: ['tutorial', 'documentation']
});

Parameter Inheritance

Configure parameter inheritance between parent and child states.

/**
 * Parameter inheritance configuration
 */
interface ParameterInheritance {
  /** Inherit parameter from parent state */
  inherit?: boolean;
}

Usage Examples:

// Parent state with shared parameters
$stateProvider.state('app', {
  url: '/app?theme&lang',
  params: {
    theme: { value: 'light', squash: true },
    lang: { value: 'en', squash: true }
  }
});

// Child state inheriting parent parameters
$stateProvider.state('app.dashboard', {
  url: '/dashboard?view',
  params: {
    theme: { inherit: true },  // Inherit from parent
    lang: { inherit: true },   // Inherit from parent
    view: { value: 'grid', squash: true }
  }
});

// Navigate to child state with inherited parameters
$state.go('app.dashboard', { theme: 'dark', view: 'list' });
// URL: /app/dashboard?theme=dark&view=list&lang=en

Dynamic Parameters

Configure parameters that don't trigger state reloads when changed.

/**
 * Dynamic parameter configuration for real-time updates
 */
interface DynamicParamConfig {
  /** Mark parameter as dynamic (no reload on change) */
  dynamic?: boolean;
}

Usage Examples:

// Dynamic parameters for real-time updates
$stateProvider.state('chat', {
  url: '/chat/{roomId}?scroll&filter',
  params: {
    roomId: {
      type: 'string'
      // Static parameter - changing triggers reload
    },
    scroll: {
      type: 'int',
      value: 0,
      dynamic: true,  // Changing doesn't trigger reload
      squash: true
    },
    filter: {
      type: 'string',
      value: '',
      dynamic: true,  // Changing doesn't trigger reload
      squash: true
    }
  },
  controller: ['$scope', '$stateParams', function($scope, $stateParams) {
    // Watch for dynamic parameter changes
    $scope.$watch(function() {
      return $stateParams.scroll;
    }, function(newScroll) {
      scrollToPosition(newScroll);
    });
    
    $scope.$watch(function() {
      return $stateParams.filter;
    }, function(newFilter) {
      filterMessages(newFilter);
    });
  }]
});

// Update dynamic parameters without reload
$state.go('.', { scroll: 100 }, { notify: false });
$state.go('.', { filter: 'important' }, { notify: false });

Parameter Squashing

Control URL generation behavior for default parameter values.

/**
 * Parameter squashing configuration
 */
interface ParameterSquashing {
  /** Squash behavior for default values */
  squash?: boolean | string;
}

Usage Examples:

$stateProvider.state('products', {
  url: '/products?page&sort&category',
  params: {
    page: {
      type: 'int',
      value: 1,
      squash: true     // Remove from URL when value is 1
    },
    sort: {
      type: 'string', 
      value: 'name',
      squash: false    // Always show in URL
    },
    category: {
      type: 'string',
      value: 'all',
      squash: '~'      // Replace with '~' when default
    }
  }
});

// Navigation examples:
$state.go('products');                           // /products?sort=name&category=~
$state.go('products', { page: 1 });             // /products?sort=name&category=~
$state.go('products', { page: 2 });             // /products?page=2&sort=name&category=~
$state.go('products', { category: 'electronics' }); // /products?sort=name&category=electronics

Parameter Validation

Validate parameters during navigation and handle validation errors.

/**
 * Parameter validation patterns
 */
interface ParameterValidation {
  /** URL pattern for parameter matching */
  pattern?: RegExp;
  /** Type validation function */
  is?: (val: any) => boolean;
}

Usage Examples:

// Parameter validation with regex patterns
$stateProvider.state('user', {
  url: '/user/{id:[0-9]+}',  // Only numeric IDs allowed
  resolve: {
    user: ['$stateParams', 'UserService', function($stateParams, UserService) {
      const userId = parseInt($stateParams.id);
      if (!userId || userId < 1) {
        throw new Error('Invalid user ID');
      }
      return UserService.getUser(userId);
    }]
  }
});

// Custom parameter validation
angular.module('myApp').config(['$urlServiceProvider', function($urlServiceProvider) {
  $urlServiceProvider.config.type('uuid', {
    pattern: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,
    is: function(val) {
      return typeof val === 'string' && this.pattern.test(val);
    }
  });
}]);

$stateProvider.state('document', {
  url: '/document/{id:uuid}',
  // id must be valid UUID format
});

// Handle parameter validation errors
$transitions.onError({}, function(trans) {
  const error = trans.error();
  if (error.type === 'INVALID_PARAMS') {
    console.error('Invalid parameters:', error.detail);
    return trans.router.stateService.go('error.params');
  }
});

Parameter Access Patterns

Common patterns for accessing and using parameters in components and controllers.

Controller Parameter Access

// Parameter injection in controllers
angular.module('myApp').controller('ProductController', 
  ['$stateParams', '$state', function($stateParams, $state) {
    
    // Access current parameters
    this.productId = $stateParams.id;
    this.category = $stateParams.category;
    this.page = parseInt($stateParams.page) || 1;
    
    // Navigate with parameter changes
    this.changePage = function(newPage) {
      $state.go('.', { page: newPage });
    };
    
    // Navigate with parameter inheritance
    this.editProduct = function() {
      $state.go('products.edit', {}, { inherit: true });
    };
  }]);

Component Parameter Binding

// Component with parameter bindings
angular.module('myApp').component('userProfile', {
  bindings: {
    userId: '<',
    tab: '<'
  },
  controller: function() {
    this.$onChanges = function(changes) {
      if (changes.userId) {
        this.loadUser(this.userId);
      }
      if (changes.tab) {
        this.switchTab(this.tab);
      }
    };
  }
});

// State with component parameter mapping
$stateProvider.state('profile', {
  url: '/profile/{userId}?tab',
  component: 'userProfile',
  bindings: {
    userId: '$stateParams.userId',
    tab: '$stateParams.tab'
  }
});

Error Handling

Common parameter-related errors and solutions:

// Handle missing required parameters
$stateProvider.state('requiresId', {
  url: '/item/{id}',
  resolve: {
    item: ['$stateParams', function($stateParams) {
      if (!$stateParams.id) {
        throw new Error('Item ID is required');
      }
      return ItemService.getItem($stateParams.id);
    }]
  }
});

// Handle invalid parameter types
$transitions.onBefore({}, function(trans) {
  const params = trans.params();
  
  // Validate numeric parameters
  if (params.id && isNaN(parseInt(params.id))) {
    console.error('Invalid ID parameter:', params.id);
    return trans.router.stateService.go('error.invalid');
  }
  
  // Validate array parameters
  if (params.tags && !Array.isArray(params.tags)) {
    params.tags = [params.tags]; // Convert single value to array
    return trans.router.stateService.go(trans.to(), params, { replace: true });
  }
});