JavaScript MVVM library that makes it easier to create rich, responsive UIs with automatic UI synchronization through observable data binding
npx @tessl/cli install tessl/npm-knockout@3.5.0Knockout.js is a JavaScript MVVM (Model-View-ViewModel) library that enables developers to create rich, desktop-like user interfaces with automatic UI synchronization through observable data binding. It provides a powerful and extensible set of declarative bindings that allow HTML elements to automatically stay in sync with underlying data models, eliminating the need for manual DOM manipulation.
npm install knockouthttps://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.1/knockout-min.js// ES6 Module
import ko from "knockout";// CommonJS
const ko = require("knockout");<!-- Browser Global -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.1/knockout-min.js"></script>
<!-- ko global variable is available -->import ko from "knockout";
// Create a view model with observables
function ViewModel() {
this.firstName = ko.observable("John");
this.lastName = ko.observable("Doe");
// Computed observable
this.fullName = ko.computed(() => {
return this.firstName() + " " + this.lastName();
});
// Observable array
this.items = ko.observableArray(["Item 1", "Item 2"]);
// Methods
this.addItem = () => {
this.items.push("New Item " + (this.items().length + 1));
};
}
// Apply bindings to connect view model to DOM
ko.applyBindings(new ViewModel());<!-- HTML with data-bind attributes -->
<div>
<p>First name: <strong data-bind="text: firstName"></strong></p>
<p>Last name: <strong data-bind="text: lastName"></strong></p>
<p>Full name: <strong data-bind="text: fullName"></strong></p>
<input data-bind="value: firstName" />
<input data-bind="value: lastName" />
<ul data-bind="foreach: items">
<li data-bind="text: $data"></li>
</ul>
<button data-bind="click: addItem">Add Item</button>
</div>Knockout.js is built around several key concepts:
Core reactive data binding system providing observable values, computed observables, and observable arrays for automatic UI synchronization.
function observable<T>(initialValue?: T): Observable<T>;
function observableArray<T>(initialItems?: T[]): ObservableArray<T>;
function computed<T>(evaluator: () => T): Computed<T>;
function pureComputed<T>(evaluator: () => T): PureComputed<T>;interface Observable<T> {
(): T; // Read value
(value: T): any; // Write value
subscribe(callback: (newValue: T) => void): Subscription;
peek(): T; // Read without creating dependency
valueHasMutated(): void; // Manually notify of changes
valueWillMutate(): void; // Notify before changes
}
interface ObservableArray<T> extends Observable<T[]> {
push(...items: T[]): number;
pop(): T | undefined;
shift(): T | undefined;
unshift(...items: T[]): number;
remove(item: T): T[];
removeAll(): T[];
indexOf(item: T): number;
replace(oldItem: T, newItem: T): void;
}
interface Computed<T> extends Observable<T> {
dispose(): void;
isActive(): boolean;
getDependenciesCount(): number;
}Declarative binding system that connects view models to DOM elements with automatic synchronization and a rich set of built-in binding handlers.
function applyBindings(viewModel: any, rootNode?: Node): void;
function applyBindingsToNode(node: Node, bindings: object, viewModel: any): void;
function contextFor(node: Node): BindingContext | undefined;
function dataFor(node: Node): any;interface BindingContext<T = any> {
$data: T;
$root: any;
$parent?: any;
$parents: any[];
$index?: Observable<number>;
$component?: any;
}
const bindingHandlers: {
// Text and appearance
text: BindingHandler;
html: BindingHandler;
visible: BindingHandler;
css: BindingHandler;
style: BindingHandler;
attr: BindingHandler;
class: BindingHandler;
// Control flow
foreach: BindingHandler;
if: BindingHandler;
ifnot: BindingHandler;
with: BindingHandler;
// Form fields
value: BindingHandler;
click: BindingHandler;
event: BindingHandler;
submit: BindingHandler;
enable: BindingHandler;
disable: BindingHandler;
checked: BindingHandler;
options: BindingHandler;
// Templates and components
template: BindingHandler;
component: BindingHandler;
};Comprehensive utility library providing array manipulation, DOM utilities, data conversion, and cross-browser compatibility functions.
const utils: {
// Array utilities
arrayForEach<T>(array: T[], action: (item: T, index: number) => void): void;
arrayFilter<T>(array: T[], predicate: (item: T) => boolean): T[];
arrayMap<T, U>(array: T[], mapping: (item: T) => U): U[];
arrayIndexOf<T>(array: T[], item: T): number;
// Object utilities
extend<T, U>(target: T, source: U): T & U;
objectForEach(obj: object, action: (key: string, value: any) => void): void;
// Observable utilities
unwrapObservable<T>(value: T | Observable<T>): T;
peekObservable<T>(value: T | Observable<T>): T;
// DOM utilities
parseHtmlFragment(html: string): Node[];
setHtml(node: Node, html: string): void;
triggerEvent(element: Element, eventType: string): void;
registerEventHandler(element: Element, eventType: string, handler: EventListener): void;
// Data utilities
parseJson(jsonString: string): any;
stringifyJson(data: any): string;
postJson(url: string, data: any): void;
};Reusable UI component system with view model and template composition, registration, and loading capabilities for modular application architecture.
const components: {
register(name: string, config: ComponentConfig): void;
unregister(name: string): void;
isRegistered(name: string): boolean;
get(name: string, callback: (definition: Component) => void): void;
clearCachedDefinition(name: string): void;
};interface ComponentConfig {
viewModel?: ViewModelConfig;
template: TemplateConfig;
synchronous?: boolean;
}
interface Component {
template: Node[];
createViewModel?: (params: any, componentInfo: ComponentInfo) => any;
}
interface ComponentInfo {
element: Node;
templateNodes: Node[];
}Flexible templating system supporting multiple template engines, template sources, and rendering options for dynamic content generation.
function renderTemplate(
template: string | Node,
dataOrBindingContext?: any,
options?: TemplateOptions,
targetNode?: Node,
renderMode?: "replaceChildren" | "replaceNode" | "ignoreTargetNode"
): void;
function setTemplateEngine(templateEngine: TemplateEngine): void;interface TemplateOptions {
templateEngine?: TemplateEngine;
afterRender?: (elements: Node[], data: any) => void;
}
abstract class TemplateEngine {
abstract renderTemplateSource(
templateSource: TemplateSource,
bindingContext: BindingContext,
options: TemplateOptions
): Node[];
}Task scheduling, memoization, and configuration options for controlling Knockout.js runtime behavior and optimizing performance.
const tasks: {
scheduler: (callback: () => any) => void;
schedule(callback: () => any): number;
cancel(handle: number): void;
runEarly(): void;
};
const memoization: {
memoize(callback: (val: any) => void): Node[];
unmemoize(memoId: string, callbackParams: any[]): void;
unmemoizeDomNodeAndDescendants(domNode: Node, extraCallbackParamsArray: any[]): void;
parseMemoText(memoText: string): string;
};function toJS(viewModel: any): any;
function toJSON(viewModel: any, replacer?: Function, space?: string | number): string;
function unwrap<T>(value: T | Observable<T>): T;function isObservable(obj: any): boolean;
function isObservableArray(obj: any): boolean;
function isComputed(obj: any): boolean;
function isPureComputed(obj: any): boolean;
function isSubscribable(obj: any): boolean;
function isWriteableObservable(obj: any): boolean;
function isWritableObservable(obj: any): boolean;/**
* Global error handler for Knockout.js errors
* @param error - Error object to handle
*/
function onError(error: Error): void;const options: {
deferUpdates: boolean; // Defer observable updates
useOnlyNativeEvents: boolean; // Use only native DOM events
foreachHidesDestroyed: boolean; // Hide destroyed items in foreach
createChildContextWithAs: boolean; // Create child context with 'as' binding
};const version: string;