Specialized views for rendering collections of models with automatic child view management, filtering, sorting, and empty state handling.
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);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;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();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;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;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;/** 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 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 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;
}