npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

knockout-editable

v1.0.1

Published

Plugin for Knockout which allows to accept or roll back changes on observables and view models

Readme

knockout-editable

This is plugin for KnockoutJS which allows to accept or rollback changes on observables or view models. It is extremely easy to use solution suitable in most use cases.

You could find examples of usage on http://romanych.github.com/ko.editables/

Installation

knockout-editable is now live on npm. It depends on knockout.

npm install knockout knockout-editable

How to use

editable extender

Adds following methods to any writeable observable:

  • beginEdit()
  • commit()
  • rollback()
  • oldValue()

Also it adds hasChanges observable property. hasChanges returns boolean value indicating wether the actual value of observable is different to initial value or not. Under initial value we understand value of ubservable when beginEdit() was called.

Example:

var name = ko.observable().extend({editable: true});
var nameLength = ko.dependentObservable(function() {
    return name() ? name().length : 0;
});

name('user');       // name set to 'user'
name.beginEdit();   // begin transaciton
name('me');         // name set to 'me', nameLength was recalculated
name.oldValue(); 	// gives us 'user'
nameLength();       // gives us 2
name.hasChanges();  // gives us `true`
name.commit();      // transaction commited; values are unchanged since last edit; we could start another one
name.hasChanges();  // gives us `false`
name.rollback();    // nothing happens since transation is commited
name.hasChanges();  // gives us `false`
name.beginEdit();   // begin another transaction
name('someone');    // name set to 'someone', nameLength was recalculated
name.rollback();    // rollback transaction; name set to initial value 'me', nameLength recalculated
name();             // gives us 'me'

Note: it is safe to extend same observable multiple times

Check out examples/index.html for this example.

ko.editable plugin

Extends any object with same methods and properties as editable extender. Basically it iterates over all poperties of passed object and extends all writeable observables with editable extender. Also it goes into deep when scaning for observables. So you could use pretty compex viewModels and activate editable with single call

Example:

var user = {
    FirstName: ko.observable('Some'),
    LastName: ko.observable('Person'),
    Address: {
        Country: ko.observable('USA'),
        City: ko.observable('Washington')
    }
};
ko.editable(user);

user.beginEdit();
user.FirstName('MyName');
user.hasChanges();          // returns `true`
user.commit();
user.hasChanges();          // returns `false`
user.Address.Country('Ukraine');
user.hasChanges();          // returns `true`
user.rollback();
user.Address.Country();     // returns 'USA'

Tip: if you are using view models based on classes the best practice is to call ko.editable(this) when all data properties are defined

Check out examples/advanced.html for this example.

Using scopes with extender

From time to time model is pretty complex and part of it declared in different places. Just small example, you have view model with 2 sets of fields:

  • Personal Information

  • Settings

    var ViewModel = function() { var self = this; self.FirstName = ko.observable(); self.LaststName = ko.observable();

      self.ReceiveEmails = ko.observable(false);
      self.ShowMyEmail = ko.observable(false);

    };

You want to add check have user changed something in Personal information or in Setting sections. It is very easy to do with scoping:

var ViewModel = function() {
	var self = this;
	self.FirstName = ko.observable().extend({editable: { scope: 'Personal' }});
	self.LastName = ko.observable().extend({editable: { scope: 'Personal' }});
	self.ChangedPersonalInformation = ko.computed(function() {
		return ko.editable.hasChanges('Personal');
	});

	self.ReceiveEmails = ko.observable(false).extend({editable: { scope: 'Settings' }});
	self.ShowMyEmail = ko.observable(false).extend({editable: { scope: 'Settings' }});
	self.ChangedSettings = ko.computed(function() {
		return ko.editable.hasChanges('Settings');
	});
};

The usage is pretty simple:

var viewModel = new ViewModel();
viewModel.FirstName('Josh');
viewModel.LastName('Pill');

ko.editable.beginEdit('Personal'); // Important! You begin to edit scopes, not the view model or observable.
ko.editable.beginEdit('Team');

viewModel.FirstName('Me');
viewModel.ChangedPersonalInformation(); // `true`
viewModel.ChangedSettings();            // `false`

viewModel.ShowMyEmail(true);
viewModel.ChangedSettings();            // `true`

ko.editable.commit('Personal');
ko.editable.rollback('Settings');

viewModel.FirstName();                  // `Me`
viewModel.ShowMyEmail();                // `false`
viewModel.ChangedPersonalInformation(); // `false`
viewModel.ChangedSettings();            // `false`

Check out examples/scoping.html for this example.