0

Trying to jade a json object with nested object, But each prod in order.productOrder does not yeild prod.name...

JSON

{
   "id": "57bf5800473ffcd9bec12845",
   "userId": "57988bf249c8791e403ea6f0",
   "paymentTrans": {
      "trandId": 6720391068199,
      "timestampApproved": "Sat Aug 27 2016 19:48:29 GMT+0300 (IDT)",
      "timestampSent": "Sat Aug 27 2016 19:48:29 GMT+0300 (IDT)",
      "serviceName": "PayPal"
   },
   "totalPerOrder": 160,
   "productOrder": [
      {
         "total": 40,
         "price": 4,
         "quantity": 10,
         "name": "Banana",
         "sku": "BAN"
      },
      {
         "total": 120,
         "price": 10,
         "quantity": 12,
         "name": "Fig",
         "sku": "FIG"
      }
   ]
}

jade

tbody
    each order in orders
        tr
            td.tdRight= moment(order.paymentTrans.timestampSent).format('DD.MM.YYY')
            td.tdCenter.price= order.totalPerOrder
            td.tdLeft= order.paymentTrans.serviceName
            td.tdCenter
                button.btn.product.btn-primary(type='button', ng-click='showDetails()')

        each prod in order.productOrder
            tr.show.hidden
                td.tdRight= prod.name
                td.tdCenter= prod.price
                td.tdCenter= prod.quantity
                td.tdLeft= prod.total
        br

chrome

 > 20|                             td.tdRight= prod.name
   21|                             td.tdCenter= prod.price
   22|                             td.tdCenter= prod.quantity
   23|                             td.tdLeft= prod.total
Cannot read property 'name' of undefined

Tried the code here jade-demo and it worx....

jade input

doctype html
html(lang="en")
  head
    title= pageTitle
    script(type='text/javascript').
      if (foo) {
         bar(1 + 5)
      }
  block content
    .page-header
        h3 ההזמנות שלי
        table.table.table-bordered
            thead
                tr פירוט הזמנות
            tbody
                each order in orders
                    tr
                        td.tdRight= order.paymentTrans.timestampSent
                        td.tdCenter.price= order.totalPerOrder
                        td.tdLeft= order.paymentTrans.serviceName
                        td.tdCenter
                            button.btn.product.btn-primary(type='button', ng-click='showDetails()')
                    for prod in order.productOrder
                        tr.show.hidden
                            td.tdRight= prod.name
                            td.tdCenter= prod.price
                            td.tdCenter= prod.quantity
                            td.tdLeft= prod.total
                    br

locals

{
  orders: [
{
   "id": "57bf5800473ffcd9bec12845",
   "userId": "57988bf249c8791e403ea6f0",
   "paymentTrans": {
      "trandId": 6720391068199,
      "timestampApproved": "Sat Aug 27 2016 19:48:29 GMT+0300 (IDT)",
      "timestampSent": "Sat Aug 27 2016 19:48:29 GMT+0300 (IDT)",
      "serviceName": "PayPal"
   },
   "totalPerOrder": 160,
   "productOrder": [
      {
         "total": 40,
         "price": 4,
         "quantity": 10,
         "name": "Banana",
         "sku": "BAN"
      },
      {
         "total": 120,
         "price": 10,
         "quantity": 12,
         "name": "Fig",
         "sku": "FIG"
      }
   ]
},
{
 "id": "57bf5800473ffcd9bec12845",
 "userId": "57988bf249c8791e403ea6f0",
 "paymentTrans": {
    "trandId": 6720391068199,
    "timestampApproved": "Sat Aug 27 2016 19:48:29 GMT+0300 (IDT)",
    "timestampSent": "Sat Aug 27 2016 19:48:29 GMT+0300 (IDT)",
    "serviceName": "PayPal"
 },
 "totalPerOrder": 160,
 "productOrder": [
    {
       "total": 40,
       "price": 4,
       "quantity": 10,
       "name": "Banana",
       "sku": "BAN"
    },
    {
       "total": 120,
       "price": 10,
       "quantity": 12,
       "name": "Fig",
       "sku": "FIG"
    }
 ]
}
  ]
}

UPDATE 1

td.tdCenter= order.productOrder

gives:

[ { sku: 'APL', name: 'Apple', quantity: 2, price: 12, total: 24 }, { sku: 'AVC', name: 'Avocado', quantity: 2, price: 16, total: 32 } ]

in td.

mongodb

"productOrder" : [ { "sku" : "APL" , "name" : "Apple" , "quantity" : 2 , "price" : 12 , "total" : 24} , { "sku" : "AVC" , "name" : "Avocado" , "quantity" : 2 , "price" : 16 , "total" : 32}]

webStorm snapshot of console and mongodb webStorm snapshot of console and mongodb

Orders Screenshot with uniteratable order.productOrder data I just added a td line so: td.tdCenter= order.productOrder Orders Screenshot with missing data

UPDATE 2 - order.js Controller

exports.getOrders = (req, res) => {

    Order.find()
        .populate({
            path: 'orders',
            match: { _id: req.user._id }
        })
        .exec(function (err, orders) {
            orders.forEach(function(elem){
                console.log("ELEM = " + elem.productOrder);
                console.log("ELEM = " + typeof elem.productOrder);
            });

            res.render('account/orders', {
                title: 'ניהול ההזמנות שלי',
                angularApp: 'storeApp',
                orders: orders
            });
        });
};

Console snapshot of order.js

console.log("ELEM = " + elem.productOrder); enter image description here

How can I fix this??

Jadeye
  • 3,551
  • 4
  • 47
  • 63
  • The JSON you're showing is different from the array being shown in the "UPDATE". Does your code actually fail with the JSON that you're posting ("Banana" and "Fig")? – robertklep Aug 27 '16 at 20:36
  • @robertklep, just different mockup-data I'm using...the code is failing, and more: `each prod in order.productOrder.length ? order.productOrder : ['empty']` returns `empty`... – Jadeye Aug 27 '16 at 20:47
  • I can't reproduce the issue, it's working just fine for me. See [this gist](https://gist.github.com/robertklep/b7bda8efc7249d44fd839c914a32165e) for the output that's generated. – robertklep Aug 27 '16 at 21:06
  • @robertklep, I know, that is what makes it so strange... Code works elsewhere but not under my app... Any idea how to 'debug' this? – Jadeye Aug 28 '16 at 04:19
  • How is your app structured? I assume that you're using `res.render()` in Express? Try and see if it works better with a standalone version that renders your template. [Here is a gist](https://gist.github.com/robertklep/545a71b835051a706f47bfba6fb28e6b). – robertklep Aug 28 '16 at 06:07
  • @robertklep, it does not make sense, the data is there, how come it's not accessible from `jade`?? please look at the screenshot update. As per your question, it is `hackathon-starter` based so kinda basic `MEAN Stack` with angular added to client side. – Jadeye Aug 28 '16 at 14:04
  • What does `typeof order.productOrder[0]` yield? – robertklep Aug 28 '16 at 19:22
  • @robertklep, jade template - - console.log("jade = " + typeof order.productOrder[0]); = jade = undefined; order.js controller console.log("ELEM = " + typeof elem.productOrder); = ELEM = object...P.s.check out the UPDATE 2 – Jadeye Aug 28 '16 at 20:12
  • `Object.prototype.toString.call(order.productOrder)` = `[object Object]` – Jadeye Aug 28 '16 at 20:28
  • What I find strange is that you're populating `orders`, yet it doesn't seem to appear in the output as expected (as `order.orders`). Last thing I can think of: see if it works better if you're using `orders.toObject()` instead of plain `orders`. – robertklep Aug 29 '16 at 08:20

1 Answers1

0

First and foremost I must thank @robertklep for the persistence & guidance...
Unbelievable.....3 dayz...for this resolution:

order.js Controller

Order.find().lean()
        .populate({

The query needed the lean() mongooose function in order to return plain javascript objects that jade could parse in each & for loops of the nested objects, so:

jade

each order in orders
    tr
        td.tdRight= moment(order.paymentTrans.timestampSent).format('DD.MM.YYY')
        td.tdCenter.price= order.totalPerOrder
        td.tdLeft= order.paymentTrans.serviceName
        td.tdCenter
            button.btn.product.btn-primary(type='button', ng-click='showDetails()')
                | פירוט
    tr
        td.tdRight= 'name'
        td.tdCenter= 'price'
        td.tdCenter= 'quantity'
        td.tdLeft= 'total'
    for prod in order.productOrder
        tr
            td.tdRight= prod.name
            td.tdCenter= prod.price
            td.tdCenter= prod.quantity
            td.tdLeft= prod.total

output chrome snapshoot Credit to

ecdeveloper's OS anser on Convert Mongoose docs to json

Community
  • 1
  • 1
Jadeye
  • 3,551
  • 4
  • 47
  • 63