Search code examples
javascriptjsonnode.jsnunjucks

Why do I need to write JSON.parse(JSON.stringify(data))?


I'm writing a Node.js web application which is using Express as framework and Nunjucks as template engine.

One part of the application is to send form data as email. A Nunjucks template with the form data within is compiled during the process, which then is send to the email server.

The form data is a JSON object (req.body), but for some strange reason, I need to submit the form data like this:

const renderer = nunjucks.configure('/path/to/template');

renderer.render('template.html', JSON.parse(JSON.stringify(req.body)));

Simply writing renderer.render('template.html', req.body); isn't working, it throws an error:

TypeError: ctx.hasOwnProperty is not a function
    at Obj.extend.init (D:\Projects\vcs.vitra.com\node_modules\nunjucks\src\environment.js:338:20)
    at new new_cls (D:\Projects\vcs.vitra.com\node_modules\nunjucks\src\object.js:46:28)
    at Obj.extend.render (D:\Projects\vcs.vitra.com\node_modules\nunjucks\src\environment.js:473:23)
    at D:\Projects\vcs.vitra.com\node_modules\nunjucks\src\environment.js:311:35
    at createTemplate (D:\Projects\vcs.vitra.com\node_modules\nunjucks\src\environment.js:234:25)
    at handle (D:\Projects\vcs.vitra.com\node_modules\nunjucks\src\environment.js:249:25)
    at D:\Projects\vcs.vitra.com\node_modules\nunjucks\src\environment.js:263:21
    at next (D:\Projects\vcs.vitra.com\node_modules\nunjucks\src\lib.js:207:13)
    at Object.exports.asyncIter (D:\Projects\vcs.vitra.com\node_modules\nunjucks\src\lib.js:214:5)
    at Obj.extend.getTemplate (D:\Projects\vcs.vitra.com\node_modules\nunjucks\src\environment.js:242:17)

Does somebody has an idea why I need to stringify and parse the form data before it works in Nunjucks? Doesn't seem to make any sense?

Edit

Here is the entire function for better explanation:

Function

function sender(data, callback) {
  const config = require('./config'),
        renderer = nunjucks.configure(path.join(__dirname, 'views', 'mail-templates')),
        transporter = nodemailer.createTransport((smtpTransport(config.smtp)));

  transporter.sendMail({
    from: `${data.name} <${data.email}>`,
    replyTo: data.email,
    to: config.email.receiver,
    subject: config.email.subject,
    html: renderer.render(`${data.origin}.html`, JSON.parse(JSON.stringify(data))),
  }, callback);
}

Function call

sender(req.body, (message, err) => {
  res.json({ message: message, errors: err });
});

req.body aka data

{ contacttype: 'E-Mail',
  software: '',
  text: 'Test',
  email: '',
  name: '',
  origin: 'contact' }

Solution

  • Try change code to

    function sender(data, callback) {
        const config = require('./config'),
            renderer = nunjucks.configure(path.join(__dirname, 'views', 'mail-templates')),
            transporter = nodemailer.createTransport((smtpTransport(config.smtp)));
    
        renderer.render(`${data.origin}.html`, data, function(err, html){
            if (err)
                return callback(err);
    
            transporter.sendMail({
                from: `${data.name} <${data.email}>`,
                replyTo: data.email,
                to: config.email.receiver,
                subject: config.email.subject,
                html: html
                }, callback
            );
        }); 
    }
    

    To create copy/mix of objects use Object.assign

    let copy = Object.assign({}, src1, src2);