or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

behaviors.mdcollection-views.mdindex.mdobjects-and-application.mdregions.mdutilities.mdviews.md
tile.json

collection-views.mddocs/

Collection Views

Specialized views for rendering collections of models with automatic child view management, filtering, sorting, and empty state handling.

Capabilities

CollectionView Class

A view that renders a collection of models by creating child views for each model, with support for filtering, sorting, and custom empty states.

/**
 * View for rendering collections with child views
 * @param options - Configuration options for the collection view
 */
class CollectionView extends Backbone.View {
  constructor(options?: CollectionViewOptions): CollectionView;
  
  /** Render the collection view and all child views */
  render(): this;
  
  /** Set the view's DOM element */
  setElement(element: string | Element): this;
  
  /** Check if the collection is empty (after filtering) */
  isEmpty(): boolean;
  
  /** Build a child view instance for a model */
  buildChildView(child: Backbone.Model, ChildViewClass: typeof View, childViewOptions: object): View;
  
  /** Add a child view at a specific index */
  addChildView(view: View, index?: number, options?: object): this;
  
  /** Detach a child view without destroying it */
  detachChildView(view: View): View;
  
  /** Remove and destroy a child view */
  removeChildView(view: View, options?: object): View;
  
  /** Swap the positions of two child views */
  swapChildViews(view1: View, view2: View): this;
  
  /** Get the empty view region */
  getEmptyRegion(): Region;
  
  /** Sort child views according to viewComparator */
  sort(): this;
  
  /** Filter child views according to viewFilter */
  filter(): this;
  
  /** Set the view comparator and optionally re-sort */
  setComparator(comparator: ViewComparator, options?: { preventRender?: boolean }): this;
  
  /** Remove the view comparator */
  removeComparator(options?: { preventRender?: boolean }): this;
  
  /** Get the current view comparator */
  getComparator(): ViewComparator | undefined;
  
  /** Set the view filter and optionally re-filter */
  setFilter(filter: ViewFilter, options?: { preventRender?: boolean }): this;
  
  /** Remove the view filter */
  removeFilter(options?: { preventRender?: boolean }): this;
  
  /** Get the current view filter */
  getFilter(): ViewFilter | undefined;
  
  /** Attach child view HTML to the container */
  attachHtml(els: Element[], container: Element): void;
  
  /** Detach child view HTML */
  detachHtml(view: View): void;
}

interface CollectionViewOptions extends ViewOptions {
  /** Child view class to use for each model */
  childView?: typeof View;
  
  /** Container selector for child views */
  childViewContainer?: string;
  
  /** Options passed to each child view */
  childViewOptions?: object | ((model: Backbone.Model, index: number) => object);
  
  /** View class to show when collection is empty */
  emptyView?: typeof View;
  
  /** Options passed to the empty view */
  emptyViewOptions?: object | (() => object);
  
  /** Function to filter which models get child views */
  viewFilter?: ViewFilter;
  
  /** Function to sort child views */
  viewComparator?: ViewComparator;
  
  /** Whether to sort when collection is sorted */
  sortWithCollection?: boolean;
  
  /** Prefix for child view events */
  childViewEventPrefix?: string;
  
  /** Hash of child view event handlers */
  childViewEvents?: EventsHash;
  
  /** Hash of child view triggers */
  childViewTriggers?: TriggersHash;
}

Usage Examples:

import { CollectionView, View } from "backbone.marionette";
import { Collection, Model } from "backbone";

// Define child view for individual items
class ItemView extends View {
  tagName: 'li'
  className: 'item'
  
  template(data) {
    return `
      <span class="name">${data.name}</span>
      <span class="price">$${data.price}</span>
      <button class="js-delete">Delete</button>
    `;
  }
  
  ui() {
    return {
      deleteButton: '.js-delete'
    };
  }
  
  events() {
    return {
      'click @ui.deleteButton': 'onDeleteClick'
    };
  }
  
  onDeleteClick() {
    this.model.destroy();
  }
}

// Define empty view
class EmptyView extends View {
  template() {
    return '<li class="empty">No items found</li>';
  }
  tagName: 'li'
}

// Collection view for the list
class ProductListView extends CollectionView {
  tagName: 'ul'
  className: 'product-list'
  
  childView: ItemView
  emptyView: EmptyView
  
  // Filter expensive items
  viewFilter(child, index, collection) {
    return child.get('price') > 10;
  }
  
  // Sort by price descending
  viewComparator(view) {
    return -view.model.get('price');
  }
  
  childViewEvents() {
    return {
      'item:selected': 'onChildSelected'
    };
  }
  
  onChildSelected(childView) {
    console.log('Selected item:', childView.model.get('name'));
  }
}

// Usage
const products = new Collection([
  { name: 'Laptop', price: 999 },
  { name: 'Mouse', price: 29 },
  { name: 'Keyboard', price: 89 }
]);

const listView = new ProductListView({ collection: products });
document.body.appendChild(listView.render().el);

Child View Management

Methods for managing individual child views within the collection view.

/**
 * Build a child view instance for a model
 * @param child - Model for the child view
 * @param ChildViewClass - View class to instantiate
 * @param childViewOptions - Options to pass to child view
 * @returns Constructed child view instance
 */
buildChildView(child: Backbone.Model, ChildViewClass: typeof View, childViewOptions: object): View;

/**
 * Add a child view to the collection view
 * @param view - Child view to add
 * @param index - Index position to insert at
 * @param options - Additional options
 */
addChildView(view: View, index?: number, options?: object): this;

/**
 * Detach a child view without destroying it
 * @param view - Child view to detach
 * @returns The detached view
 */
detachChildView(view: View): View;

/**
 * Remove and destroy a child view
 * @param view - Child view to remove
 * @param options - Remove options
 * @returns The removed view
 */
removeChildView(view: View, options?: object): View;

/**
 * Swap the positions of two child views
 * @param view1 - First view to swap
 * @param view2 - Second view to swap
 */
swapChildViews(view1: View, view2: View): this;

Filtering and Sorting

Methods for filtering and sorting child views independently of the collection.

/**
 * Sort child views according to viewComparator
 */
sort(): this;

/**
 * Filter child views according to viewFilter
 */
filter(): this;

/**
 * Set the view comparator function
 * @param comparator - Comparator function or property name
 * @param options - Options for the operation
 */
setComparator(comparator: ViewComparator, options?: ComparatorOptions): this;

/**
 * Remove the current view comparator
 * @param options - Options for the operation
 */
removeComparator(options?: ComparatorOptions): this;

/**
 * Get the current view comparator
 */
getComparator(): ViewComparator | undefined;

/**
 * Set the view filter function  
 * @param filter - Filter function
 * @param options - Options for the operation
 */
setFilter(filter: ViewFilter, options?: FilterOptions): this;

/**
 * Remove the current view filter
 * @param options - Options for the operation
 */
removeFilter(options?: FilterOptions): this;

/**
 * Get the current view filter
 */
getFilter(): ViewFilter | undefined;

interface ComparatorOptions {
  preventRender?: boolean;
}

interface FilterOptions {
  preventRender?: boolean;
}

Usage Examples:

// Dynamic filtering and sorting
class FilterableListView extends CollectionView {
  // ... other configuration
  
  filterByCategory(category) {
    this.setFilter((child, index) => {
      return child.get('category') === category;
    });
  }
  
  sortByName() {
    this.setComparator((view) => view.model.get('name'));
  }
  
  sortByPrice() {
    this.setComparator((view) => view.model.get('price'));
  }
  
  clearFilters() {
    this.removeFilter();
  }
}

// Usage
const listView = new FilterableListView({ collection: products });
listView.render();

// Filter and sort dynamically
listView.filterByCategory('electronics');
listView.sortByPrice();

Empty State Handling

Methods for managing empty states when the collection has no visible items.

/**
 * Check if the collection view should show as empty
 * @returns True if no child views are visible after filtering
 */
isEmpty(): boolean;

/**
 * Get the region used for showing the empty view
 * @returns Region instance for empty view
 */
getEmptyRegion(): Region;

HTML Attachment Methods

Methods for customizing how child view HTML is attached to the DOM.

/**
 * Attach child view HTML elements to the container
 * @param els - Array of child view elements
 * @param container - Container element to attach to
 */
attachHtml(els: Element[], container: Element): void;

/**
 * Detach a child view's HTML from the DOM
 * @param view - Child view to detach
 */
detachHtml(view: View): void;

Static Configuration Methods

Global configuration methods for customizing collection view behavior.

/**
 * Set custom DOM API for all collection views
 * @param mixin - DOM API mixin object
 */
static setDomApi(mixin: DomApiMixin): void;

/**
 * Set custom template renderer for all collection views
 * @param renderer - Template rendering function
 */
static setRenderer(renderer: RendererFunction): void;

Properties

/** Whether to automatically sort when collection is sorted */
sortWithCollection: boolean; // default: true

/** Container for filtered child views */
children: ChildViewContainer;

/** DOM API instance used by the collection view */
Dom: DomApi;

Collection View Lifecycle Events

Collection views trigger events during their lifecycle and child view operations:

// Render lifecycle
collectionView.on('before:render', () => { /* ... */ });
collectionView.on('render', () => { /* ... */ });

// Child view events
collectionView.on('before:add:child', (view) => { /* ... */ });
collectionView.on('add:child', (view) => { /* ... */ });
collectionView.on('before:remove:child', (view) => { /* ... */ });
collectionView.on('remove:child', (view) => { /* ... */ });

// Collection events
collectionView.on('before:render:children', () => { /* ... */ });
collectionView.on('render:children', () => { /* ... */ });

// Empty state events
collectionView.on('before:render:empty', () => { /* ... */ });
collectionView.on('render:empty', () => { /* ... */ });

Type Definitions

type ViewFilter = (child: Backbone.Model, index: number, collection: Backbone.Collection) => boolean;

type ViewComparator = 
  | string 
  | ((view: View) => any) 
  | ((view1: View, view2: View) => number);

interface ChildViewContainer {
  // Underscore collection methods
  forEach(iteratee: (view: View, index: number) => void): void;
  map<T>(iteratee: (view: View, index: number) => T): T[];
  reduce<T>(iteratee: (memo: T, view: View, index: number) => T, initialValue: T): T;
  find(predicate: (view: View, index: number) => boolean): View | undefined;
  filter(predicate: (view: View, index: number) => boolean): View[];
  reject(predicate: (view: View, index: number) => boolean): View[];
  every(predicate: (view: View, index: number) => boolean): boolean;
  some(predicate: (view: View, index: number) => boolean): boolean;
  contains(view: View): boolean;
  isEmpty(): boolean;
  length: number;
  
  // Collection-specific methods
  findByModel(model: Backbone.Model): View | undefined;
  findByModelCid(modelCid: string): View | undefined;
  findByIndex(index: number): View | undefined;
  findIndexByView(view: View): number;
  findByCid(cid: string): View | undefined;
  hasView(view: View): boolean;
}