Tom Rider
Tom Rider

Reputation: 2815

How to detect changes besides the change event in knockout.js

I am using knockout.js. I created a view model say testViewModel with only 1 observable property testProperty.

function testViewModel()
{
  var self = this;

  self.testProperty = ko.observable("Initial");

}

than i created a span in which the changed value of testProperty is reflected and a input text field by which we can change the testProperty value.

 <span data-bind="text: testProperty"></span><br />
 <input type="text" data-bind="value: testProperty" />

I created an Example Fiddle.It seems that the observable property value is updated when the focusout event is executed on the input text field.

Now my question is that can we change the observable property value update event from focusout to something else. I created a save button also. Is there any way to update the observable property value only on save button press.

I am trying to create an application in which a user can create and save its profile and can edit the saved profile.I am using the same observable properties in create and edit form and these properties are observable. So when user edit its profile the ui should not be updated until user press the save button. This is my goal. Please help me to solve this issue ?

Upvotes: 0

Views: 1133

Answers (3)

Matt Burland
Matt Burland

Reputation: 45145

Your simplest approach would be to have a shadow property for each of your properties. So you bind one to your text boxes and only copy the value to the other property, the one bound to the other UI elements, when save is clicked.

See here: http://jsbin.com/aguyud/5/edit

An easier way using two models and $.extend to copy from one to the other:

http://jsbin.com/aguyud/7/edit

Update, actually scratch that, that doesn't seem to work. I tried this instead:

http://jsbin.com/aguyud/22/edit

which works the first time, but after copying the model with $.extend it seem it's copied all the bindings too, so it only works once!

Upvotes: 1

Jason M. Batchelor
Jason M. Batchelor

Reputation: 2951

Another means, along the same lines of what Matt Burland suggested:

http://jsfiddle.net/mori57/PQxJC/

Basically, wrap your input and button in a form, and bind the form to submit: which is handled by a method on your ViewModel. See the comments I've made inline, but here it is for people who don't want to go out to jsFiddle:

<span data-bind="text: testProperty"></span><br />
<!-- wrap the input and button in a form and
   data-bind to submit, with a reference
   to a handler on your viewmodel -->
<form data-bind="submit: updateProfile">
<!-- this must be bound to your shadow value -->
<input type="text" data-bind="value: _tmpTestProperty" />
<button type="submit">save</button>
</form>​

and in your javascript

function testViewModel()
{
  var self = this;

  self.testProperty = ko.observable("Initial");
  // Create the "shadow" property
  // and prepopulate it with testProperty's value
  self._tmpTestProperty = ko.observable(self.testProperty());

  // Create our form handler
  self.updateProfile = function(val){
    // set the testProperty value to the 
    // value of the shadow property
    self.testProperty(self._tmpTestProperty());
  };

}

ko.applyBindings(new testViewModel());​

In this way, your value doesn't change when you lose focus on the text input box, but is only updated when you submit the form.

Upvotes: 2

Matthew
Matthew

Reputation: 411

I would suggest have testProperty and testProperty_temp. Bind the input to temp and when the button is clicked, set testProperty to the testProperty_temp

function testViewModel()
{
   var self = this;

   self.testProperty = ko.observable("Initial");
   self.testProperty_temp = ko.obserable("");
   self.save = function() { self.testProperty(self.testProperty_temp()); }
 }

Hope this helps

Upvotes: 4

Related Questions