Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a one way binding in knockout

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 ?

like image 413
nixon Avatar asked Sep 10 '13 05:09

nixon


2 Answers

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>
like image 149
Ali Habibzadeh Avatar answered Oct 12 '22 01:10

Ali Habibzadeh


The one way binding means : modifications on UI (typing in the input) are 'applied' to the view model. But if you change the viewModel (by code) the UI wont be refreshed.

If you need to refresh the UI by code (js), you have to use an observable.

As you can see in this fiddle, if you click on the 'Change by code' button the view model will be changed but not the UI.

var viewModel = {
    firstName: 'Fred',
    test: function () {
        alert(viewModel.firstName);
    },
    change: function () {
        viewModel.firstName = "new Value";
    }
};

See fiddle.

I hope it helps.

like image 24
Damien Avatar answered Oct 12 '22 01:10

Damien