4

right now I have this form:

<form ng-submit = "submit()"ng-controller = "formCtrl">
                <input ng-model="formData.stickie" type="text" id="sticky_content" />
                <button type="submit" id="add_sticky" value="add a new stickie!">new sticky</button> 
        </form>

controlled by this model:

app.controller('formCtrl',function($scope,$http){

        $scope.submit = function() {
                $http.post('/api/stickies', $scope.formData)
                                **** somehow assign data to something useable by the function below???******

                        })
                        .error(function(data){
                                console.log('Error: ' + data);
                        });
        };
});

and I want to be able to use the posted data in here:

app.post('/api/stickies',function(req,res){
        var test = formData.stickie;    //returns undefined for sticky and for formData.stickie
        db.run("INSERT INTO stickies (data) VALUES (?)", [ test ]);
});

so in summary, I am trying to pass the $scope.formData variable into my server.js file so that it can be used in my app.post function (and inserted into the db)

Edit: updated code in accordance with answer given below: currently getting `ReferenceError: formData is not Defined, when I submit the form.

user3727514
  • 273
  • 3
  • 6
  • 14

1 Answers1

8

When you use ng-model it is to bind your form components to the scope using certain name. this means that

<input ng-model="stickie_text" type="text" id="sticky_content" />

will bring you a $scope.stickie_text with the current value of your component in your 'formCtrl' controller. Remember it's a bidirectional binding: if you alter that variable, you also alter the value in the form control.

Let's refactor this:

<form ng-submit="submit()" ng-controller="formCtrl">
    <input ng-model="stickie_text" type="text" id="sticky_content" />
    <button type="submit" id="add_sticky" value="add a new stickie!">new sticky</button> 
</form>

This form has only one field: stickie_text. The other one is a button. So far, your form has one field, which stores and reads data in the scope in the specified name ($scope.stickie_text).

When you submit the form, your $scope.submit function is being invoked:

$scope.submit = function() {
    $http
        .post('/api/stickies', {what: to, put: here})
        .success(function(data){
            //what to do here
        })
        .error(function(data){
            console.log('Error: ' + data);
        });
};

So this is your handler and the big question is:

  • what to do here?
  • How do I post the data?
  • How do I handle the same data once I post it?

Notice I changed your handler a bit - placing a comment and replacing the data object.

The POST data must match the server-side. So if your stickie must fly through the network under the name stickie (in this way, a req.body.stickie expression exists on the server-side), the data you must compose is this: {stickie: $scope.stickie_text}. This is because stickie_text is the name you used in the view, and so it's the name of the scope var where such field will read and write from. Remember to install the body parser middleware in your application.

I don't remember much of nodejs, but if I'm right, perhaps doing:

app.post('/api/stickies',function(req,res){
    var test = req.body.stickie;
    db.run("INSERT INTO stickies (data) VALUES (?)", [ test ]);
});

Will do it AS LONG AS YOU USE THE SAME DATA KEYS FROM THE CLIENT. You should also write something in the response (res) object, but that's up to you and nodejs, and your preferred way (e.g. res.write).

So, we'll stick to the same example:

$scope.submit = function() {
    $http
        .post('/api/stickies', {stickie: $scope.stickie_text})
        .success(function(data){
            //what to do here? it's up to you and the data you write from server.
        })
        .error(function(data){
            console.log('Error: ' + data);
        });
};

Test this, and check your database.

Edit - suggested by @Kousha - Use a de-facto namespace for your form data (as you said formData beforehand - remember this is an example and you can use any name you want). It works like this:

  1. Give a prefix to each of your fields in the ng-model, so the same object holds the form data. Since you have only ONE field, it will be enough:

    ng-model="formData.stickie"
    

    deliberately I changed the variable name to match the name waiting in the nodejs server. Don't forget this, since I'll use the object directly as data.

  2. The final value of $scope.formData will be {stickie: whatEverIsInTheInputField}. If I added another field using ng-model="formDta.foo" as binding, the final value of $scope.formData would be {stickie: whatEverIsInTheInputField, foo: otherFieldValue}.

  3. I use the $scope.formData directly in the http request:

    $scope.submit = function() {
        $http
            .post('/api/stickies', $scope.formData)
            .success(function(data){
                //what to do here? it's up to you and the data you write from server.
            })
            .error(function(data){
                console.log('Error: ' + data);
            });
    };
    
  4. Although formData did not exist in the $scope beforehand, the binding created it implicitly before creating stickie under it.

Luis Masuelli
  • 12,079
  • 10
  • 49
  • 87
  • While your method works perfectly fine, I suggest using the an object for ng-model (such as `new_entry.stickie_text`), and then simply `.post('/api/stickies', $scope.new_entry)`. Note that the input name on the receive side is now `stickie_text`. More importantly, this is much easier if you want to send a few items over. – Kousha Jul 29 '14 at 22:21
  • Yes, you're right. I forgot to put that - since that's the way I use it, using an object for the form. – Luis Masuelli Jul 29 '14 at 22:22
  • thank you very much. I learned a lot from your well written post. Is the updated code what you were referring to by sending the "new_entry" object in the form? note the current error at the bottom. – user3727514 Jul 29 '14 at 23:04
  • My example was not with `new_entry` but with `formData`. By using `formData.` as prefix of each ng-model, I can access the whole form data by just using such expression: `$scope.formData`. The sample saying `new_entry` was from @Kousha – Luis Masuelli Jul 30 '14 at 13:00
  • ok I think I am starting to get it. I have updated the question's code. One question: would I use formData.stickie or just stickie in the app.post function in the server file? Currently both are returned as undefined, though I did pass $scope.formData into the $http call in the controller. – user3727514 Jul 30 '14 at 16:46
  • additionally, another question: it seems that, according to your answer, anything labeled with $scope is accessible by the node server. So for instance, $scope.formData would automatically become available in the server.js file. Is this correct? or does something additional have to be done to pass formData to the server (besides including it in the $http post request)? – user3727514 Jul 30 '14 at 17:55
  • No, it is not. `formData` will not be made available to nodejs - only its components, because it is what we're passing as the second parameter to $http. if you inspect `$scope.formData`, the contents will be `{stickie: something}` - **THAT** will be available, and **NOT** the `formData` identifier nor any identifier bound to `$scope` **UNLESS** the call is `$http.post('/your/url', $scope)`. Under normal circumstances **http has nothing to do with scope**. – Luis Masuelli Jul 30 '14 at 19:10