Nguyễn Hoàng
Nguyễn Hoàng

Reputation: 179

KnockoutJS, Binding View

I'm struggling with issues from KnockoutJS, I have block code below

var viewModel = function (value){
    this.name = ko.observable(value);
}
var model = {}; model.firstName = "ABC";
var AppViewModel = new viewModel(model.firstName);
ko.applyBindings(AppViewModel);

And in HTML i have a view with binding

data-bind="textInput: name".

It's good work. TextView display with text: "ABC". I have a question. when I change value in TextView. Whether if that model (special firstName) update new value from textView ?

Upvotes: 0

Views: 44

Answers (2)

DibsyJr
DibsyJr

Reputation: 884

The problem is that model.firstName is an object property but it isn't an observable, instead you're using that object property to set the observable, the observable is the two way binding, if you want firstName to be an observable/two way binding you can do it like so:

var viewModel = function (){
    VM = this;
    VM.firstName = ko.observable("ABC");
    return VM;
}

var AppViewModel = new viewModel();
ko.applyBindings(AppViewModel);

Here we're creating a function viewModel() that returns an object with the property firstName which is a knockout observable containing "ABC". Then we're creating an instance of that view model and applying it to the page. Now if you make any changes in the input it should update the value of AppViewModel.firstName.

Or to keep it more similar to your code you can do it like this:

var viewModel = function (){
    this.firstName = ko.observable("ABC");
}

var AppViewModel = new viewModel();
ko.applyBindings(AppViewModel);

Note that there is no need to create the model object with the property firstName, you can just initialise the observable with a string and it will pick up any changes made in the textInput binding.

Upvotes: 1

Jeroen
Jeroen

Reputation: 63840

Your constructor function AppViewModel takes in the Model upon construction. The resulting ViewModel will be two-way data-bound to the view.

What you'd typically have is a reverse method to the constructor, that can be used e.g. when saving the changes through a Model in a back-end. Here's a demo with your example:

function AppViewModel(model){
    var self = this;
    
    self.firstName = ko.observable(model.firstName);
    self.lastName = ko.observable(model.lastName);
    
    self.asModel = ko.computed(function() {
        return {
            firstName: self.firstName(),
            lastName: self.lastName()
        };
    });
    
    self.saveInBackend = function() {
        // Typically you'd ajax here, instead we log the model:
        console.log(self.asModel());
    };
}
var model = {}; 
model.firstName = "John";
model.lastName = "Doe";

var viewModel = new AppViewModel(model);

ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

Firstname: <input data-bind="textInput: firstName"><br>
Lastname: <input data-bind="textInput: lastName"><br>
<button data-bind="click: saveInBackend">saveInBackend</button>
<h4>Debug info, this is the state of your *view model*:</h4>
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
<h4>Debug info, this is the state of an updated model:</h4>
<pre data-bind="text: ko.toJSON($root.asModel(), null, 2)"></pre>
<h4>Debug info, this is the state of your *initial model* (which doesn't change):</h4>
<pre data-bind="text: ko.toJSON(window.model, null, 2)"></pre>

Upvotes: 0

Related Questions