Tony Goodchild
Tony Goodchild

Reputation: 355

How to have Knockout update on global variable change

I am using knockout to bind the value on some input boxes. I have also set the model to subscribe to the values of a global variable (data).

function AppViewModel() {
        this.username = ko.observable(data.user.name);
        this.name = ko.observable(data.visibleByRegisteredUsers.name);
        this.phone = ko.observable(data.visibleByRegisteredUsers.phone);
        this.gender = ko.observable(data.visibleByRegisteredUsers.gender);
        this.distance = ko.observable(data.visibleByRegisteredUsers.distance);
        this.address = ko.observable(data.visibleByRegisteredUsers.address);
        this.postcode = ko.observable(data.visibleByRegisteredUsers.postcode);
        this.latitude = ko.observable(data.visibleByRegisteredUsers.latitude);
        this.longitude = ko.observable(data.visibleByRegisteredUsers.longitude);

        this.name.subscribe(function (newData) {
            data.visibleByRegisteredUsers.name = newData;
        });
        this.phone.subscribe(function (newData) {
            data.visibleByRegisteredUsers.phone = newData;
        });
        this.gender.subscribe(function (newGender) {
            data.visibleByRegisteredUsers.gender = newGender;
        });
        this.distance.subscribe(function (newData) {
            data.visibleByRegisteredUsers.distance = newData;
        });
        this.address.subscribe(function (newData) {
            data.visibleByRegisteredUsers.address = newData;
        });
        this.postcode.subscribe(function (newData) {
            data.visibleByRegisteredUsers.postcode = newData;
        });
        this.latitude.subscribe(function (newData) {
            data.visibleByRegisteredUsers.latitude = newData;
        });
        this.longitude.subscribe(function (newData) {
            data.visibleByRegisteredUsers.longitude = newData;
        });


    }

    ko.applyBindings(new AppViewModel()); 

I am binding input values like this:

<input type="text" class="form-control" placeholder="Lat" id="lat" aria-describedby="basic-addon1" required data-bind="value:latitude">

If I then update the data object such as setting a value for data.visibleByRegisteredUsers.latitude the input box is not being updated. Is there something incorrect in how I have set this up?

Upvotes: 3

Views: 1862

Answers (2)

user3297291
user3297291

Reputation: 23397

You are initializing your viewmodel's properties with values stored in the data object and its nested contents.

After the initialization (e.g.: this.latitude = ko.observable(someValue)), your observable is nothing more than a wrapper with a value. Call the wrapper with a new value and it updates. (this.latitude(10)) Call it without a value and it unwraps. (this.latitude(); // 10)

I.e.: after initializing, you shouldn't touch the data object. You make changes by updating your viewmodel. If you want to parse back to the original format, you'll have to write the logic yourself.

const data = {
  visibleByRegisteredUsers: {
    latitude: 54
  }
};

function AppViewModel() {
  /* ... */
  this.latitude = ko.observable(data.visibleByRegisteredUsers.latitude);
  
  this.latitude.subscribe(console.log);
};

ko.applyBindings(new AppViewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<input data-bind="textInput: latitude">

Upvotes: 3

sander
sander

Reputation: 749

It is normal that this does not work. Knockout does data-binding using observables. The observables you defined are not getting notified when the data-object changed since it is not an observable. What you could do is set an observable object in the VM which is filled with the global variable. Then subscribe to it and update the global as such. Still not sure why you would want this but hey; it might work like that.

Upvotes: 0

Related Questions