0

I have Knockout For Students book, and looking at AJAX:

    self.loadUserData = function(){
        $.getJSON("http://127.0.0.1:5000/data", function(data){
            self.firstName(data.firstName);
            self.lastName(data.lastName);
            self.activities(data.activities);
            self.favoriteHobby(data.favoriteHobby);
        });
    }
}

The full code looks like

ajax-chapter-7.html:

<html lang='en'>
<head>
  <title>External data</title>
  <meta charset='utf-8' />
  <link rel='stylesheet' href='style.css' />
</head>
<body>
  <h1>External data</h1>

  <form action="#" method="post">
      <p>
          First name: <input data-bind='value: firstName' />
      </p>
      <p>
          Last name: <input data-bind='value: lastName' />
      </p>
      <div>
          Your favorite hobby:
          <select data-bind='options: activities, value: favoriteHobby'></select>
      </div>
      <p>
          <button data-bind='click: loadUserData'>Load Data</button>
      </p>
  </form>

  <script type='text/javascript' src='knockout-3.4.0.js'></script>
  <script type='text/javascript' src='jquery-3.1.1.min.js'></script>
  <script type='text/javascript'>
    function PersonViewModel(){
        var self = this;
        self.firstName = ko.observable("");
        self.lastName = ko.observable("Johnson");
        self.activities = ko.observableArray([]);
        self.favoriteHobby = ko.observable("");

        // http://stackoverflow.com/questions/25011952/can-you-add-headers-to-getjson-in-jquery

        $.ajaxSetup({
            headers: {
                // 'Origin': 'http://example.com'
            }
        })

        self.loadUserData = function(){
            $.getJSON("http://127.0.0.1:5000/data", function(data){
                Object.keys(data).forEach(function(k){
                    alert(k);
                    alert(data[k]);
                    alert(self[k]);
                    self[k] = data[k];
                });
                // self.firstName(data.firstName);
                // self.lastName(data.lastName);
                // self.activities(data.activities);
                // self.favoriteHobby(data.favoriteHobby);
            });
        }
    }

    ko.applyBindings(new PersonViewModel());
  </script>
</body>
</html>

server.py:

from flask import Flask, jsonify
from flask_cors import CORS, cross_origin

app = Flask(__name__)
CORS(app)


@app.route('/')
def hello():
    return 'Hello, world'


# http://stackoverflow.com/questions/13081532/how-to-return-json-using-flask-web-framework
@app.route('/data')
def data():
    data = {
        'firstName': 'Cody',
        'lastName': 'Childers',
        'activities': [
            'Golf',
            'Kayaking',
            'Web development',
        ],
        'favoriteHobby': 'Golf',
    }

    return jsonify(**data)


if __name__ == "__main__":
    app.run()

The book and code is all working, but the loadUserData is hideous and repetitive. In python we can do this like:

keys = ['firstName', 'lastName', 'activities', 'favoriteHobby']
for key in keys:
    setattr(self, key, getattr(data, key))

boom, done.

Is there a Javascript equivalent to set attributes on self by string, assuming I knew the JSON keys I get are the same as attribute names I wanna set?

Knockout will require me to call attributes as a function, not set them as normal attributes (knockout calls it 'observables').

Thank you

1 Answer 1

4

You can use bracket notation and Object.keys()

$.getJSON("http://127.0.0.1:5000/data", function(data){
    Object.keys(data).forEach(function(k) {
        // you may check if the key is in the "to be transferred ones" here
        self[k] = data[k]; 
    });
});

If you want to assign only certain keys, you can use

var allowedKeys = ['firstName', 'lastName', 'activities', 'favoriteHobby']
$.getJSON("http://127.0.0.1:5000/data", function(data){
    Object.keys(data).forEach(function(k) {
        if (allowedKeys.indexOf(k) > -1) self[k] = data[k]; 
    });
});

Alternatively, you can also use Object.assign(), but without the possibility to exclude some keys:

$.getJSON("http://127.0.0.1:5000/data", function(data){
    self = Object.assign(self, data);
});

And for your comment, if you need to call a function (though you should add a check if the function exists before executing it):

$.getJSON("http://127.0.0.1:5000/data", function(data){
    Object.keys(data).forEach(function(k) {
        // you may check if the key is in the "to be transferred ones" here
        self[k](data[k]); 
    });
});
Sign up to request clarification or add additional context in comments.

3 Comments

this can't work, as observables in knockoutjs are functions. I'm looking at it now
Edited a version with function calls @codyc4321
gerne @codyc4321 :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.