-1

On the client side I'm creating a JSON object storing emails and email types from user inputted data in input fields. I then use ajax to send it as a JSON to my server.

$(function () { 
$(document).on('click', '.send', function (e) {
    var dataToSend = [];
    $('.form-group1').each(function () {
        var data = {};
        $(this).find(':input[data-name]').each(function () {
            data[$(this).data('name')] = $(this).val();
        });
        dataToSend.push(data);
    });

    $.ajax({
       url: '/pers1',
       type: 'POST',
       contentType:'application/json',
       data: JSON.stringify(dataToSend),
       dataType:'json',
     });        
    console.log(JSON.stringify(dataToSend))
 });
});

The server then stores this into the database as a JSON object:

class PersonalInfoHandler1(BaseHandler):
@tornado.web.authenticated
def post(self):
    global piData

    receipt = tornado.escape.json_decode(self.request.body)
    print receipt

    piData={                            
            'emails': receipt,
            }      

    self.settings['db'].userInfo.update({'PiUsername':self.current_user},{"$set":piData})
    print 'from pers1'                 
    self.redirect('/pers')

When the page is reloaded the data is sent back in another Handler as:

class PersonalInfoHandler(BaseHandler):
@tornado.web.authenticated
def get(self):
    self.render("personal.html", user=self.current_user, ,emails=user['emails'])

The client gets this back and I try to iterate over the key:value's like this:

var emails = '{{emails}}';
emails = emails.replace(/u'/g,"");
emails = emails.replace(/'/g,"");

emaildata=JSON.stringify(emails)

$.each(emaildata, function(key, value) { 
      alert(key + ': ' + value); 
    });

Instead I get the error in Chrome console:

Uncaught TypeError: Cannot use 'in' operator to search for '28' in "[{emailAdd: , emailDesc: }]" jquery.min.js:2  jquery.min.js:2 m.extend.each jquery.min.js:2 (anonymous function)

So I cannot iterate over the keys and/or values. Is the problem with the actual JSON or code?

user94628
  • 3,641
  • 17
  • 51
  • 88
  • 1
    Am I correct in assuming that your response is an array? Because the `in` operator works on objects: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in – naneau Aug 31 '14 at 16:35
  • Yes it's an array of dicts – user94628 Aug 31 '14 at 16:39

2 Answers2

3

$.each(emaildata, ...) isn't iterating an Array or Object. It's trying to iterate a String value character-by-character.

console.log(typeof emaildata, emaildata);
// string '"[{emailAdd: , emailDesc: }]"'

It is also the stringified form of yet another string.

var emails = '[{emailAdd: , emailDesc: }]';

The value of emails in JavaScript would at least need to be valid JSON, which needs encoding from Python, so it can be parsed:

var emails = '{% raw json_encode(emails) %}';
var emaildata = JSON.parse(emails);

$.each(emaildata, function (key, value) {
    // ...
});

Though, since JSON's syntax came from JavaScript, you can output JSON as an expression for JavaScript to parse directly as Array and Object initializers (note the removal of the quotes):

var emails = {% raw json_encode(emails) %};

$.each(emails, function (key, value) {
    // ...
});
Jonathan Lonowski
  • 121,453
  • 34
  • 200
  • 199
  • Thanks. I've tried doing `var emails = '{{json_encode(emails)}}'; var emaildata = JSON.parse(emails);alert(emaildata);`. But this now gives a `Uncaught SyntaxError: Unexpected token & pers:1001 (anonymous function)` error in my console – user94628 Aug 31 '14 at 17:21
  • In the console it is saying that `var emails = '{{json_encode(emails)}}';` is `var emails = '[{"emailAdd": "", "emailDesc": ""}]';` – user94628 Aug 31 '14 at 17:31
  • 1
    @user94628 Sorry. It appears the view [should use `{% raw json_encode(emails) %}`](http://stackoverflow.com/questions/6527833/how-do-i-include-quoted-html-in-a-tornado-template) to prevent HTML-encoding in either case. I've updated the snippets in my post with it. – Jonathan Lonowski Aug 31 '14 at 17:35
  • thats got rid off that error. When I do console.log to view the output it gives me `0: [object Object]`. Should it not give me the actual names and values assigned to the key:values? I get this error in console:Uncaught TypeError: Cannot use 'in' operator to search for '42' in [{"emailAdd": "fdfd", "emailDesc": "gfgf"}] jquery.min.js:2 r jquery.min.js:2 m.extend.each jquery.min.js:2 (anonymous function) – user94628 Aug 31 '14 at 17:40
  • 1
    @user94628 Since each `value` in the `Array` is an `Object`, [the `[object Object]` is to be expected](http://ecma-international.org/ecma-262/5.1/#sec-15.2.4.2). If you pass the variables to `console.log()` as their own arguments rather than concatenating, most Consoles will show a more detailed view -- `console.log(key, value);`. – Jonathan Lonowski Aug 31 '14 at 17:43
  • ok and I can refer to each key & value by emaildata.key and emaildata.value? – user94628 Aug 31 '14 at 17:47
  • 1
    @user94628 No. `key` and `value` are just local variables inside the `function`. They aren't themselves properties of `emaildata` and [dot notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors) doesn't make use of variables. You can use bracket notation with `key` as another way to retrieve the `value` -- `emaildata[key] === value`. But, part of the benefit of using iterators like `$.each()` is not having to keep referring to the source object (`emaildata`). – Jonathan Lonowski Aug 31 '14 at 17:51
  • ok, so doing `var emails = {% raw json_encode(emails)%}; $.each(emails, function(key, value) { console.log(key + ': ' + value); });` Still returns outpout as `0: [object Object] ` – user94628 Aug 31 '14 at 17:54
  • 1
    @user94628 Change the `console.log(key + ': ' + value);` to `console.log(key, value);` for the Console to show a detailed view. The other 4-5 lines are good. – Jonathan Lonowski Aug 31 '14 at 17:56
2

The problem lies in the fact that you do emaildata=JSON.stringify(emails), but then try to go over that variable using $.each(). Since it is a string, not an object or array, jQuery's each() doesn't work on i. You may have meant $.each(emails).

naneau
  • 489
  • 2
  • 4