Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot read property 'title' of undefined. Express

Hi im developing nodejs express app. I am getting exception and dont know why. Everything seem to perfect for me. My exception is shown below:

 500 TypeError: C:\Nodejs\NodejsBlog\apps\blog/views/postdetail.jade:23<br/> 21| .col- md-12 <br/> 22| .posts <br/> > 23| h3= post.title <br/> 24| p=post.body <br/> 25| p tag:      <br/> 26| i=post.tag <br/><br/>Cannot read property 'title' of undefined
21| .col-md-12
22| .posts
> 23| h3= post.title
24| p=post.body
25| p tag:
26| i=post.tag
Cannot read property 'title' of undefined
at eval (eval at (C:\Nodejs\NodejsBlog\node_modules\jade\lib\jade.js:152:8), :221:59)
at C:\Nodejs\NodejsBlog\node_modules\jade\lib\jade.js:153:35
at Object.exports.render (C:\Nodejs\NodejsBlog\node_modules\jade\lib\jade.js:197:10)
at Object.exports.renderFile (C:\Nodejs\NodejsBlog\node_modules\jade\lib\jade.js:233:18)
at View.exports.renderFile [as engine] (C:\Nodejs\NodejsBlog\node_modules\jade\lib\jade.js:218:21)
at View.render (C:\Nodejs\NodejsBlog\node_modules\express\lib\view.js:76:8)
at Function.app.render (C:\Nodejs\NodejsBlog\node_modules\express\lib\application.js:504:10)
at ServerResponse.res.render     (C:\Nodejs\NodejsBlog\node_modules\express\lib\response.js:798:7)
at C:\Nodejs\NodejsBlog\apps\blog\routes.js:64:14
at callbacks (C:\Nodejs\NodejsBlog\node_modules\express\lib\router\index.js:164:37)

And here is the app.post code:

app.get('/Post/:id',function(req,res){
    var postdata;
    var comments;
    Post.findOne({_id:req.params.id},function(err, docs){
            if(docs) {
                postdata=docs;  
                console.log('Gönderi bulundu');
                console.log(docs);
                console.log(postdata);
                console.log(postdata.title);
            } else {

                console.log('Gönderi bulunamadı');
            }
        });

        Comment.findOne({postid:req.params.id},function(err, docs){
            if(docs) {
                console.log('Yorum bulundu');
                console.log(docs);
            } else {
                comments=docs;  
                console.log('Yorum bulunamadı');
            }
        });

    return res.render(__dirname+"/views/postdetail",{
            title: 'adfasdf',
            stylesheet: 'postdetail',
            post:postdata,
            comments:comments
            });
});

And my view:

extends ../../../views/bloglayout
block js
script(type='text/javascript')
    $(function() {
        $("#commentform" ).submit(function( event ) {
            alert( "Handler for .submit() called." );
            $.ajax({
                url: '/Post/Comment/',
                type: "POST",
                data: $('#commentform').serialize(),
                success: function(response){
                alert('Yorum Kaydedildi');
                }
            }); 
            event.preventDefault();
        });
    });

block content
.row
    .col-md-12
        .posts
            h3=post.title
            p=post.body
            p tag:
                i=post.tag
            p Anahtar Kelimeler:
                b=post.keywords
        .row
            .col-md-4
                h5 Yorum Yap
                  form#commentform(role='form',action='/Post/Comment', method='post')
                            input(type='hidden',name='comment[postid]',value=postdata._id)
                        .form-group
                            input.form-control(type='email',name='comment[email]',placeholder='E-posta adresi')
                        .form-group
                            input.form-control(type='text',name='comment[website]', placeholder='Website')
                        .form-group
                            textarea.form- control(type='text',name='comment[content]', placeholder='Yorum')
                        button.btn.btn-  default(type='submit') Ekle
                -comments.forEach(function(comment) {
                .well
                    p
                        b=comment.content
                    p=comment.email
                -})

Also i checked my mongodb. There is data. I dont know why 'title' property is 'undefined' have no idea.

like image 821
ftdeveloper Avatar asked Dec 05 '13 21:12

ftdeveloper


1 Answers

This is a race condition issue. The two functions that pull from MongoDB are asynchronous and so the call to res.render() happens before the DB returns the data in each function's respective callback. You need to nest each function so that they have access to the proper context. See below:

app.get('/Post/:id', function (req, res, next){
  Post.findOne({_id:req.params.id},function(err, postData){
    if (err) return next(err);  

    Comment.findOne({postid:req.params.id},function(err, comments){
      if (err) return next(err);

      return res.render(__dirname+"/views/postdetail",{
        title: 'adfasdf',
        stylesheet: 'postdetail',
        post:postData,
        comments:comments
      });

    });
  });
});

However, you can see how this can get pretty messy as you nest further and further. To prevent this, you can use a control flow library like caolan/async

Side Note:

You're Jade is looking to iterate over a comments array and you are returning a single doc from MongoDB (assuming you are using the mongoose module). You will want to change your Mongoose function from findOne() to simply find() so that mongoose can return an array of docs with the proper postid.

Edit:


Vinayak Mishra is also correct in pointing out that you can use Express' routing middleware as a way to impose control flow within a route. Here is an example:

// Use the app.param() method to pull the correct post doc from the database.
// This is useful when you have other endpoints that will require work on
// a Post document like PUT /post/:postid
app.param('postid', function (req, res, next, id) {

  Post.findById(id, function (err, post) {
    if (err) return next(err);
    if (!post) return next('route');
    req.post = post;
  });

});

app.get('/post/:postid',
  // -- First route middleware grabs comments from post doc saved to req.post
  function (req, res, next) {
    Comment.find({ postid: req.post.id }, function (err, comments) {
      if (err) return next(err);
      req.comments = comments;
      next();
    });
  },
  // -- This route middleware renders the view
  function (req, res, next) {
    res.render('/postDetail', {
      // ... list locals here ...
    });
  }
);
like image 166
srquinn Avatar answered Sep 30 '22 14:09

srquinn