2

For this JSON dictionary,

{
"user":null, 
"currency":"EUR",
"balance":0,
"tranlist": [ 
   { "date":"323","address":"a"},
   { "date":"121","address":"s"},
 ]
}

When I use this function, I have problem with getting the Transactions List

$(document.body).append($(
 '<table>' + $.map(data, function(value,key){
     return '<tr><td>'+key+'</td><td>'+value+'</td></tr>'
  }).join('')+'</table>'
));

And here is output:

 currency   EUR
 balance    0
 transactions   [object Object],[object Object],[object Object],[object Object]

How can I fix my code?

Matt
  • 74,352
  • 26
  • 153
  • 180
Spring
  • 11,333
  • 29
  • 116
  • 185

3 Answers3

6

The code you show (that I wrote in a previous answer) was intended for a fast preview of your structure and as an example of object browsing.

Now you must make some code more specific to your problem. For example :

  $(document.body).append($(
     '<table>' + $.map(data, function(value,key){
         console.log(value);
         return '<tr><td>'+key+'</td><td>'
             + ((value && $.isArray(value))
                 ? value.map(function(v){return v.date+':'+v.address}).join(', ')
                 : value
             )+ '</td></tr>'
      }).join('')+'</table>'
    ));

Demonstration

You could also devise a generic and recursive toString function but apart debugging (and console.log is better for that), there isn't much point.

Community
  • 1
  • 1
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • tnx this works but I am confused, why the key shows the title and the value shows the value, while your functions parameters are (value,key) but not (key,value) – Spring Jan 08 '13 at 15:11
  • 1
    Because [$.map](http://api.jquery.com/jQuery.map/) passes the value before the key. It's the same order as in [anyArray.map](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map). – Denys Séguret Jan 08 '13 at 15:12
  • could you also look this one? tnx http://stackoverflow.com/questions/14236448/jqueery-mobile-changepage-does-not-work-properly – Spring Jan 09 '13 at 13:56
4
$(document.body).append(
    $('<table>').append(
      $.map(data, function (value, key) {
        return $('<tr>').append( $('<td>', {text: key}) )
                        .append( $('<td>', {text: value}) );
      })
    );
));

Note that it's not recommendable to build HTML from concatenating strings. Constructing elements with a separation of markup and data $('<td>', {text: key}) is the cleanest solution.

Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • I'm not sure it's not recommendable. It's generally recommended to build a big HTML string instead of appending multiple small elements. – Denys Séguret Jan 08 '13 at 14:34
  • 1
    @dystroy This is not something I would call a good practice. If the data contains user input or other funny bits of format then you open a hole for XSS attacks this way, which is bad, obviously. Concatenation (when done right) happens to be a little bit faster, so it is an *optimization*. But in this case I'd make sure that the data does not contain HTML, which is a step that most people forget. Squeezing out two dozen milliseconds in page run time will not be necessary in most cases, so I'd always recommend the clean and secure method. – Tomalak Jan 08 '13 at 14:40
  • @Tomalak tnx but I dont see anything as output, am I missing something? – Spring Jan 08 '13 at 14:52
  • @Spring Woops, my bad. I forgot the angle brackets with `$('' ...)`. Of course the nested objects will still be output as `[object Object]`, since you did not say how to handle them.
    – Tomalak Jan 08 '13 at 15:09
2

Not exactly answer to your question but instead of build HTML on your own I would suggest using Pure JavaScript Template Engine for that (jQuery plugin).

The engine (a jQuery plugin) is very light and it is great for type of job you do (especially iterating over children elements).

I would suggest you spend literately a few minutes going though Get Started page and a few tutorials explaining iteration over children element.


Example using PURE

HTML code:

<div id="sample">
  <div class="currency">EUR</div>
  <div class="balance">0</div>
  <table>
    <tr class="date">
      <td>date</td><td class="value"></td>
    </tr>
    <tr class="address">
      <td>address</td><td class="value"></td>
    </tr>
  </table>
<div>

JavaScript code (please note that data variable used in the last statement is the same as the one in your question)

//declaration of the actions PURE has to do
var directive = {
  '.currency': 'currency',
    '.balance': 'balance',
    'table': {
    'trans<-tranlist': {
      'tr.date .value': 'trans.date',
      'tr.address .value': 'trans.address'
    }
  }
};

// note the use of render instead of autoRender
$('#sample').render(data, directive);

Output HTML would be as follows:

<div id="sample">
  <div class="currency"></div>
  <div class="balance"></div>
  <table>
    <tr class="date">
      <td>date</td><td class="value">323</td>
    </tr>
    <tr class="address">
      <td>address</td><td class="value">a</td>
    </tr>
    <tr class="date">
      <td>date</td><td class="value">121</td>
    </tr>
    <tr class="address">
      <td>address</td><td class="value">s</td>
    </tr>
  </table>
<div>

Of course you could do much more like setting class attributes from JSON object or filtering items etc.

Tom
  • 26,212
  • 21
  • 100
  • 111