luke
luke

Reputation: 37463

Is it possible to have knockoutjs update the 'initialdata' object?

Here's a much simplified example of what I'm trying to do with knockoutjs:

<!DOCTYPE HTML>
<html>
    <head>
        <title>test</title>
        <script type="text/javascript" src="https://github.com/downloads/SteveSanderson/knockout/knockout-2.0.0.debug.js"></script>
        <script type="text/javascript">

            var derp = { "foo": 1, "bar": 2 };

            window.onload = function() { go(); }

            function go()
            {
                var ViewModel = function(foobar)
                {
                    this.foo = ko.observable(foobar.foo);
                    this.bar = ko.observable(foobar.bar);
                }

                ko.applyBindings(new ViewModel(derp));
            }

        </script>
    </head>
    <body>
        <input data-bind="value: foo"/>
        <input data-bind="value: bar"/>
        <button onclick="go();">Go</button>
    </body>
</html>

The objective of this code is to have knockoutjs to update the the values in derp, not the copy inside of the ViewModel.

Is there a way to accomplish this easily with knockout, or am I barking up the wrong tree?

Edit for context:

This is culled from a much larger application. My intent was to use knockout to display and edit the properties of a large, wooly, javascript object. These objects are instantiated dynamically by the user, and can be switched between at-will.

Before I found found knockout, I was manually created DOM elements to do the displaying and editing of each object which was messy and cumbersome. I have some experience with MVVM via WPF in C#, and would have much preferred to use that approach. My initial understanding of knockout was that it'd do just that, not realizing that the ViewModel copies the values captured by ko.observable*. The ViewModel still has a use for me, as it allows me to conditionally expose and simplify access to the members I'd like to edit.

Upvotes: 3

Views: 457

Answers (2)

Etch
Etch

Reputation: 3054

I am not 100% sure I fully understand what you want, but I will take a crack at it.

You have defined your model as so:

var ViewModel = function(foobar)
            {
                this.foo = ko.observable(foobar.foo);
                this.bar = ko.observable(foobar.bar);
            }

you initialized your knockout model with var derp = { "foo": 1, "bar": 2 }; aka lotsmorecomplicatedobject.

So your inputs will get those values due to the data-bind tag. You then modify those input values then hit the save button and want to update your original javascript object.

If that is the case I would lean towards this...

Change your viewModel to this:

var ViewModel = function(foobar)
                {

                    this.foo = ko.observable(foobar.foo);
                    this.bar = ko.observable(foobar.bar);
                    save: function() { derp.foo = this.foo;
                                       derp.bar = this.bar;          
                        //  ko.utils.postJson(location.href, { obj1: this.foo, obj2: this.bar });
                    }
                }

And then change your button click event to: ViewModel.save();

I added the postJson object as an example because this is how I handle that type of data. I look at the variable you pass into the initial ViewModel definition as just that.. Here is my data that I want to pre-populate my viewmodel from and from that point forward I use my ViewModel for everything. Once you take that mindset you dont have a need to update the original object.

Upvotes: 1

AlfeG
AlfeG

Reputation: 1473

I do like @Etch response with Save method. This helps a lot. But if You want to automate such a things, then I would go with subscribe on observables.

Maybe it's not a cleaner way to do this. Would be more happy if I'm were able to pass variable by reference.

I've prefer to use some wrapper around observables to type less:

var returnFireObservable = function(variable, property) {
    var obs = ko.observable(variable[property]);
    obs.subscribe(function(newValue) {
        variable[property] = newValue;
    });
    return obs;
};

And use in code this way:

var ViewModel = function(foobar) {
    this.foo = returnFireObservable (foobar, "foo");
    this.bar = returnFireObservable (foobar, "bar");
};

ko.applyBindings(new ViewModel(derp));

Little demo http://jsfiddle.net/AlfeG/eQ9Zf/2/

Hope this helps.

Upvotes: 3

Related Questions