CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-knockout

JavaScript MVVM library that makes it easier to create rich, responsive UIs with automatic UI synchronization through observable data binding

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

observables.mddocs/

Observable System

Core reactive data binding system providing observable values, computed observables, and observable arrays for automatic UI synchronization. The observable system is the foundation of Knockout.js, enabling two-way data binding and automatic UI updates.

Capabilities

Observable Creation

Creates observable values that can be read, written, and subscribed to for change notifications.

/**
 * Creates an observable value
 * @param initialValue - The initial value (optional)
 * @returns Observable instance
 */
function observable<T>(initialValue?: T): Observable<T>;

/**
 * Creates an observable array with array manipulation methods
 * @param initialItems - Initial array items (optional)
 * @returns ObservableArray instance
 */
function observableArray<T>(initialItems?: T[]): ObservableArray<T>;

Usage Examples:

import ko from "knockout";

// Basic observable
const name = ko.observable("John");
console.log(name()); // "John"
name("Jane");
console.log(name()); // "Jane"

// Observable with no initial value
const age = ko.observable();
age(25);

// Observable array
const items = ko.observableArray(["apple", "banana"]);
items.push("orange");
console.log(items()); // ["apple", "banana", "orange"]

Computed Observables

Creates computed observables that automatically recalculate when their dependencies change.

/**
 * Creates a computed observable that derives its value from other observables
 * @param evaluator - Function that returns the computed value
 * @param evaluatorTarget - Optional 'this' context for evaluator
 * @param options - Optional configuration
 * @returns Computed observable
 */
function computed<T>(evaluator: () => T): Computed<T>;
function computed<T>(evaluator: () => T, evaluatorTarget: any): Computed<T>;
function computed<T>(options: ComputedOptions<T>): Computed<T>;

/**
 * Creates a pure computed observable with optimized behavior
 * @param evaluator - Function that returns the computed value
 * @returns PureComputed observable
 */
function pureComputed<T>(evaluator: () => T): PureComputed<T>;
function pureComputed<T>(options: ComputedOptions<T>): PureComputed<T>;

Usage Examples:

import ko from "knockout";

const firstName = ko.observable("John");
const lastName = ko.observable("Doe");

// Basic computed
const fullName = ko.computed(() => {
    return firstName() + " " + lastName();
});

// Computed with write function
const fullNameWritable = ko.computed({
    read: () => firstName() + " " + lastName(),
    write: (value) => {
        const parts = value.split(" ");
        firstName(parts[0] || "");
        lastName(parts[1] || "");
    }
});

// Pure computed (optimized for better performance)
const displayName = ko.pureComputed(() => {
    return firstName() + " " + lastName();
});

Observable Interface

Core interface for all observable types with read/write and subscription capabilities.

interface Observable<T> {
    /** Read the current value */
    (): T;
    /** Write a new value and return any for API consistency */
    (value: T): any;
    
    /** Subscribe to value changes */
    subscribe(callback: (newValue: T) => void): Subscription;
    subscribe(callback: (newValue: T) => void, target: any): Subscription;
    subscribe(callback: (newValue: T) => void, target: any, event: string): Subscription;
    
    /** Read value without creating a dependency */
    peek(): T;
    
    /** Manually notify subscribers that the value has changed */
    valueHasMutated(): void;
    
    /** Notify subscribers that the value is about to change */
    valueWillMutate(): void;
    
    /** Extend the observable with additional behavior */
    extend(extenders: ExtenderOptions): Observable<T>;
    
    /** Get the number of active subscriptions */
    getSubscriptionsCount(): number;
}

interface Subscription {
    /** Remove the subscription */
    dispose(): void;
    /** Remove subscription when DOM node is removed */
    disposeWhenNodeIsRemoved(node: Node): void;
}

Observable Array Interface

Extended observable interface for arrays with array manipulation methods.

interface ObservableArray<T> extends Observable<T[]> {
    // Standard array methods
    /** Add items to the end of the array */
    push(...items: T[]): number;
    /** Remove and return the last item */
    pop(): T | undefined;
    /** Remove and return the first item */
    shift(): T | undefined;
    /** Add items to the beginning of the array */
    unshift(...items: T[]): number;
    /** Remove and insert items at specified position */
    splice(start: number, deleteCount?: number, ...items: T[]): T[];
    /** Get a portion of the array */
    slice(start?: number, end?: number): T[];
    /** Reverse the array in place */
    reverse(): ObservableArray<T>;
    /** Sort the array in place */
    sort(compareFunction?: (a: T, b: T) => number): ObservableArray<T>;
    
    // Knockout-specific methods
    /** Get the index of an item */
    indexOf(item: T): number;
    /** Replace an item with another */
    replace(oldItem: T, newItem: T): void;
    /** Remove specific items and return them */
    remove(item: T): T[];
    remove(predicate: (item: T) => boolean): T[];
    /** Remove all items or specific items */
    removeAll(): T[];
    removeAll(items: T[]): T[];
    /** Mark items as destroyed (adds _destroy: true property) */ 
    destroy(item: T): void;
    destroy(predicate: (item: T) => boolean): void;
    /** Mark all items as destroyed */
    destroyAll(): void;
    destroyAll(items: T[]): void;
    
    // Non-mutating methods
    /** Get a sorted copy of the array */
    sorted(compareFunction?: (a: T, b: T) => number): T[];
    /** Get a reversed copy of the array */
    reversed(): T[];
}

Computed Observable Interface

Extended observable interface for computed values with dependency tracking.

interface Computed<T> extends Observable<T> {
    /** Dispose the computed and clean up dependencies */
    dispose(): void;
    /** Check if the computed is currently active */
    isActive(): boolean;
    /** Get the number of dependencies */
    getDependenciesCount(): number;
    /** Get array of dependent observables */
    getDependencies(): Observable<any>[];
}

interface PureComputed<T> extends Computed<T> {
    // Pure computeds have the same interface but optimized behavior
}

interface ComputedOptions<T> {
    /** Function to compute the value */
    read?: () => T;
    /** Function to handle writes (makes computed writable) */
    write?: (value: T) => void;
    /** Context for read/write functions */
    owner?: any;
    /** Whether this is a pure computed */
    pure?: boolean;
    /** Defer evaluation until first access */
    deferEvaluation?: boolean;
    /** Dispose when this DOM node is removed */
    disposeWhenNodeIsRemoved?: Node;
    /** Function that returns true when computed should be disposed */
    disposeWhen?: () => boolean;
}

Extenders

Observable extension system for adding additional behavior like throttling and rate limiting.

const extenders: {
    /** Throttle observable notifications */
    throttle: (observable: Observable<any>, timeout: number) => Observable<any>;
    /** Rate limit observable notifications */
    rateLimit: (observable: Observable<any>, options: RateLimitOptions) => Observable<any>;
    /** Defer observable notifications */
    deferred: (observable: Observable<any>, value: true) => Observable<any>;
    /** Control notification behavior */
    notify: (observable: Observable<any>, value: "always" | any) => Observable<any>;
    /** Track array changes for observable arrays */
    trackArrayChanges: (observable: ObservableArray<any>, value: true) => ObservableArray<any>;
};
interface RateLimitOptions {
    timeout: number;
    method?: "notifyAtFixedRate" | "notifyWhenChangesStop";
}

interface ExtenderOptions {
    throttle?: number;
    rateLimit?: number | RateLimitOptions;
    deferred?: true;
    notify?: "always" | any;
    trackArrayChanges?: true;
}

Usage Examples:

import ko from "knockout";

// Throttle updates
const throttledValue = ko.observable("").extend({ throttle: 500 });

// Rate limit updates
const rateLimitedValue = ko.observable("").extend({ 
    rateLimit: { timeout: 500, method: "notifyWhenChangesStop" } 
});

// Defer updates
const deferredValue = ko.observable("").extend({ deferred: true });

Dependency Tracking

Control dependency tracking behavior in computed observables and subscriptions.

/**
 * Execute function without creating dependencies
 * @param callback - Function to execute
 * @param callbackTarget - Optional 'this' context
 * @param callbackArgs - Optional arguments array
 * @returns Result of callback
 */
function ignoreDependencies<T>(
    callback: () => T, 
    callbackTarget?: any, 
    callbackArgs?: any[]
): T;

/**
 * Information about current computed context
 */
const computedContext: {
    /** Get number of dependencies in current context */
    getDependenciesCount(): number;
    /** Get array of dependencies in current context */
    getDependencies(): Observable<any>[];
    /** Check if this is the initial evaluation */
    isInitial(): boolean;
    /** Register a dependency in current context */
    registerDependency(observable: Observable<any>): void;
};

Usage Examples:

import ko from "knockout";

// Access current computed context inside a computed
const computed = ko.computed(() => {
    const context = ko.computedContext;
    console.log("Dependencies:", context.getDependenciesCount());
    console.log("Is initial run:", context.isInitial());
    return someValue();
});

// Execute code without dependency tracking
const result = ko.ignoreDependencies(() => {
    // This won't create dependencies even inside a computed
    return someObservable() + anotherObservable();
});

Observable Utilities

Utility functions for working with observables and managing async observable patterns.

/**
 * Creates a promise that resolves when a predicate becomes true
 * @param predicate - Function returning boolean or observable boolean
 * @returns Promise that resolves when predicate is true
 */
function when<T>(predicate: () => T): Promise<T>;

/**
 * Subscribe to a predicate with callback (alternative to promise)
 * @param predicate - Function returning boolean or observable boolean  
 * @param callback - Callback called when predicate becomes true
 * @returns Subscription that can be disposed
 */
function when<T>(predicate: () => T, callback: (value: T) => void): Subscription;

Usage Examples:

import ko from "knockout";

const isReady = ko.observable(false);
const data = ko.observable(null);

// Promise-based usage
ko.when(() => isReady()).then(() => {
    console.log("System is ready!");
});

// Callback-based usage
const subscription = ko.when(() => data(), (value) => {
    console.log("Data received:", value);
});

// Wait for complex conditions
ko.when(() => {
    return user.isLoaded() && permissions.isLoaded() && settings.isLoaded();
}).then(() => {
    console.log("All data loaded, initializing app");
});

Testing Functions

Type checking functions for observable objects.

/**
 * Test if object is an observable
 * @param obj - Object to test
 * @returns True if object is observable
 */
function isObservable(obj: any): boolean;

/**
 * Test if object is an observable array
 * @param obj - Object to test  
 * @returns True if object is observable array
 */
function isObservableArray(obj: any): boolean;

/**
 * Test if object is a computed observable
 * @param obj - Object to test
 * @returns True if object is computed
 */
function isComputed(obj: any): boolean;

/**
 * Test if object is a pure computed observable
 * @param obj - Object to test
 * @returns True if object is pure computed
 */
function isPureComputed(obj: any): boolean;

/**
 * Test if object is subscribable
 * @param obj - Object to test
 * @returns True if object is subscribable
 */
function isSubscribable(obj: any): boolean;

/**
 * Test if object is a writeable observable
 * @param obj - Object to test
 * @returns True if object is writeable observable
 */
function isWriteableObservable(obj: any): boolean;

/**
 * Alternative spelling for isWriteableObservable
 * @param obj - Object to test
 * @returns True if object is writeable observable
 */
function isWritableObservable(obj: any): boolean;

docs

binding.md

components.md

index.md

observables.md

performance.md

templates.md

utils.md

tile.json