How to use a one way binding in knockout

nixon picture nixon · Sep 10, 2013 · Viewed 7.3k times · Source

I have a viewModel like this:

    var viewModel =
    {
        firstName: 'Fred'
    }

and a text box bound to it like this

<input data-bind="value: firstName" >

I was under the impression that this would set up a one way binding as the firstName property is not an observable. Changes to the text box are updating the viewModel object. Can someone explain what is going on and how \ if my assumption is wrong ?

Answer

Ali Habibzadeh picture Ali Habibzadeh · Sep 10, 2013

If you execute a property OR drop the observable in a knockout binding it becomes a one way/read only. So in the following model for example:

class Person {
  constructor(data) {
    // Method 1: Consume observable using ()
    this.firstName = ko.observable(data.firstName);
    // Method 2: Omit the observable
    this.flatFirstName = data.firstName;
    this.lastName = ko.observable(data.lastName);
    this.fullName = ko.computed(() => `${this.firstName()} ${this.lastName()}`);
  }
}

const me = new Person({
  firstName: "John",
  lastName: "Smith"
});

ko.applyBindings(me);

I can make FirstName a one way/read only property simply by executing it in the binding:

<input data-bind="value: firstName()">
<input data-bind="value: flatFirstName">
<input data-bind="value: lastName">
<label data-bind="text: fullName"></label>

So now the first input only gets the value and can not set it but the second input will have two way binding and will update the LastName property.

Hope this helps.

class Person {
  constructor(data) {
    // Method 1: Consume observable using ()
    this.firstName = ko.observable(data.firstName);
    // Method 2: Omit the observable
    this.flatFirstName = data.firstName;
    this.lastName = ko.observable(data.lastName);
    this.fullName = ko.computed(() => `${this.firstName()} ${this.lastName()}`);
  }
}

const me = new Person({
  firstName: "John",
  lastName: "Smith"
});

ko.applyBindings(me);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<input data-bind="value: firstName()">
<input data-bind="value: flatFirstName">
<input data-bind="value: lastName">
<label data-bind="text: fullName"></label>