1

I'm trying to post form data in another view in my node/express application. I'm using Jade as the view engine.

  • Form is posted
  • Handler passes the req.body to the res.body
  • view is rendered

My question is how do I access this res.body object? How to I get at the data? I'm trying to use user input to draw some graphs.

Code below

barchartEntry.jade

form(method="POST")
        #dynamicInput
            input(type="button" value="Add New Bar" onClick="addInput('append');")
            input(type="button" value="Remove Last Bar" onClick="removeInput();")
            br
            label(class="barTitle") Bar 1
            label(class="bartTtle") Value
                input(type="text" name="myInputs[]")
            label Label
                input(type="text" name="myLabel[]")
            br
            #append
            input(type="submit" value="Submit")
    include copyright

Route Handler

exports.postBarchartentry = function postBarchartentry(req, res){
    res.body = req.body;
    res.render('barchart');
};

local JS on new view

$( document ).ready(function() {

        var values = ?
        var labels = ?

        var canvas = document.getElementById("canvas").getContext("2d");
        var Width = canvas.canvas.clientWidth;
        var Height = canvas.canvas.clientHeight;
        var padding = 30;



        function fillBackground(color){
            canvas.fillStyle=color;
            canvas.fillRect(0,0,Width,Height);
        }

        function fillAxes(){
            canvas.beginPath();
            canvas.moveTo(padding, padding);
            canvas.lineTo(padding, Height-padding);
            canvas.lineTo(Width-padding, Height-padding);
            canvas.lineWidth = "3"
            canvas.strokeStyle="black";
            canvas.stroke();
        }

        function draw(){
            fillAxes();
        }

        draw();
});

As you can see, I'm trying to get the inputted form data to be accessable in my last script

Eogcloud
  • 1,335
  • 4
  • 19
  • 44

2 Answers2

2

My question is how do I access this res.body object? How to I get at the data?

You'll have access to this data in your controller as you indicated. If you want to pass this data to another view you need to explicitly pass it to the next view.

exports.postBarchartentry = function postBarchartentry(req, res){
    res.render('barchart', {data1: req.body.field1, data2: req.body.field2});
};

In your barchart view you have two options. (1) you can render HTML directly (via Jade) with the new data. For example, add a div if data1 has data. (2) you can also render JavaScript on the page (again via Jade) so that those values will be available when the browser execute the onReady which I think is what you are trying to do.

Also, make sure you are using Express' bodyParser middleware somewhere in your application so that req.body.X has the actual data:

app.use(express.bodyParser())
Hector Correa
  • 26,290
  • 8
  • 57
  • 73
  • Thank you for your reply. the amount of fields in my form is user defined as they can add extra inputs at will. So I would have to use a loop or seomthing to fetch all the fields and then send that JSON object to the render call. Unfortunately, I don't think there's anyway of passing how many fields a user has added which makes it difficult to do a for loop for example. Any ideas considering this? p.s req.body.field1 - Does field1 refernce the ID or the name of an object? – Eogcloud Feb 19 '14 at 17:34
  • 1
    req.body is a JavaScript object and therefore you should be able to get a list of keys like you would with any other JavaScript object. For example fields = Object.keys(req.body) – Hector Correa Feb 19 '14 at 18:25
2

Hector is correct in that the view only has access to what you pass directly into it. So the question remains what do you want to pass into it?

req.body is indeed a JavaScript object, and your markup gives a really nice way to get at the contents.

I put together a little test project where I used your markup:

label(class="barTitle") Bar 1
label(class="bartTtle") Value
  input(type="text" name="myInputs[]")
label Label
  input(type="text" name="myLabel[]")

When I submitted that form, in my post handler I had something like this:

 app.post('/arraytest', function(req,res) {
   console.log(req.body)
   res.send(req.body)
 })

(We'll ignore for now the ugliness of putting the actual handler inline with the routing call). When that form submits, I get this object for req.body:

{ myInputs: [ '3' ], myLabel: [ 'asdf' ] }

For fun, I added a second input box and pluralized myLabel, so that my form looked like this:

label(class="barTitle") Bar 1
label(class="bartTtle") Value
  input(type="text" name="myInputs[]")
label Label
  input(type="text" name="myLabels[]")
label(class="barTitle") Bar 2
label(class="bartTtle") Value
  input(type="text" name="myInputs[]")
label Label
  input(type="text" name="myLabels[]")

Notice that I didn't change any of the names. I left them with the array brackets at the end. Submitting this form gave me the following object:

{ myInputs: [ '3', '4' ], myLabels: [ 'asdf', 'asdfasfsdf' ] }

So the interaction between the browser and body parsing gives you two arrays with all of your values. Arrays are easy enough to loop over. If you modify your render call to look like:

res.render('barchart', {inputs: req.body.myInputs, labels: req.body.myLabels})

then in your view you can have something like:

- each input, i in inputs
  = input
  = myLabels[i]

But since you want this accessible in your JS, you can use this in your Jade:

script.
  var inputs = !{JSON.stringify(inputs)}
    , labels = !{JSON.stringify(labels)}

  alert(inputs)
  alert(labels)

You'll likely not need the alert calls, but I put them there to convince me that it worked.

Many thanks to this SO question and answer for the dynamic JS portion: How can I render inline JavaScript with Jade?

Community
  • 1
  • 1
juanpaco
  • 6,303
  • 2
  • 29
  • 22
  • Thank you for your reply. Can I ask what is the use of "!" operator in this context? – Eogcloud Mar 03 '14 at 21:59
  • 1
    `!{ }` does interpolation. That is to say, it interprets the JavaScript inside of there and then converts that to a string and puts that in the template. In the above example, Jade evaluates `JSON.stringify(inputs)` and returns that as a string, which is why the resulting JS is something like `{foo:'bar'}`. Without the `!{}`, then your JS would literally be `var inputs = JSON.stringify(inputs)`. – juanpaco Mar 03 '14 at 22:57