Angularjs: Error posting data. Variable undefined - angularjs

This must be something really silly. I cannot get a simple form to work.
Worked through the bunch of links that google spits out but none helped.
I alwajs get the $scope.user undefined below.
This is the form ...
<form name="login" ng-submit="submitLogin()" ng-controller="LoginController">
<ul>
<li>
<input type="text" name="name" ng-model="user.name" placeholder="Username:">
</li>
<li>
<input type='password' name="pass" ng-model="user.pass" placeholder="Password:">
</li>
</ul>
<button type="submit">Submit</button>
</form>
And this is the controller...
basal.controller('LoginController', function($scope, $http) {
$scope.submitLogin = function() {
$http.post('/users', $scope.user)
.success(function(data) {
console.log(data);
alert("Form post good!");
})
.error(function() {
alert(angular.toJson($scope.user));
});
};
});
What am I doing wrong?
How does bi-direction works? How do we know of when the data is passed from the controller to the view and the other way round - from the view to the controller. I get the feeling that this is where my misunderstanding lies.
Thanks.

Your user is never defined or initialised.
Try username and userpass as ng-model definitions like this:
<li>
<input type="text" name="name" ng-model="username" placeholder="Username:">
</li>
<li>
<input type='password' name="pass" ng-model="userpass" placeholder="Password:">
</li>
And then add accordingly
$http.post('/users', {name: $scope.username, pass: $scope.userpass})
Or, as mentioned in the comments, define $scope.user as {} in your Controller

Initialize $scope.user = {} in the first line of your controller.
basal.controller('LoginController', function($scope, $http) {
$scope.user = {};
$scope.submitLogin = function() {
...
In your example, $scope.user == null. The form doesn't create a new object container for you.

Related

AngularJS error: TypeError: v2.login is not a function

I would like to call the login function when I click the login button but keep getting the error message in the title. Can someone point out the error in my script?
login.js code below:
/*global Firebase, angular, console*/
'use strict';
// Create a new app with the AngularFire module
var app = angular.module("runsheetApp");
app.controller("AuthCtrl", function ($scope, $firebaseAuth) {
var ref = new Firebase("https://xxxxx.firebaseio.com");
function login() {
ref.authWithPassword({
email : "xxxxx",
password : "xxxx"
}, function (error, authData) {
if (error) {
console.log("Login Failed!", error);
} else {
console.log("Authenticated successfully with payload:", authData);
}
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
And the code for login.html is also below:
<div class="container" style="max-width: 300px">
<form class="form-signin">
<h2 class="form-signin-heading" style="text-align: center">Please Sign In</h2>
<input type="text" class="form-control" name="username" ng-model = "username" placeholder="Email Address" required="" autofocus="" />
</br>
<input type="password" class="form-control" name="password" ng-model = "password" placeholder="Password" required=""/>
</br>
<button class="btn btn-lg btn-primary btn-block" type="submit" ng-click="login()">Login</button>
</form>
</div>
Edge case here, but I want to mention it for posterities' sake. I got this same error when using the controllerAs pattern with a form name with the same value as ng-submit. For example:
<form name="authCtrl.signUp" ng-submit="authCtrl.signUp()">
Throws: TypeError: v2.signUp is not a function
The solution was to change the name of the form to something different:
<form name="authCtrl.signUpForm" ng-submit="authCtrl.signUp()">
In my case, I was having an exact same issue as yours. However, coming across gkalpak's answer to such a scenario helped me out.
Turned out to be what I was calling was addBuddy() function, from a form named "addBuddy". The solution was to change the name of either of the two things to make one stand out or differentiable from the other. I changed the name of the form to "addBuddyForm" and voila! My function worked!
Here's a snippet of my case:
<form name="addBuddy" class="form-horizontal" novalidate>
...
<button class="btn btn-sm btn-info" ng-click="addBuddy()>Submit</button>
Which, I changed to:
<form name="addBuddyForm" class="form-horizontal" novalidate>
...
<button class="btn btn-sm btn-info" ng-click="addBuddy()>Submit</button>
...and it worked! :)
In AngularJS call the function from view it must be in the $scope.
JS
// exposes login function in scope
$scope.login = login;
HTML
<div class="container" ng-controller="AuthCtrl" style="max-width: 300px"> <!-- I notice here for include ng-controller to your main div -->
<form class="form-signin">
<h2 class="form-signin-heading" style="text-align: center">Please Sign In</h2>
<input type="text" class="form-control" name="username" ng-model = "username" placeholder="Email Address" required="" autofocus="" />
</br>
<input type="password" class="form-control" name="password" ng-model = "password" placeholder="Password" required=""/>
</br>
<button class="btn btn-lg btn-primary btn-block" type="submit" ng-click="login()">Login</button>
</form>
This may not be specific to your problem, but I was also getting this error and it took a bit to figure out why.
I had named both a function and a variable the same, with the variable assigned in the function, and so the assignment of the variable was overriding the function and it was exploding on a second run.
You'll notice in the example the uploadFile() function as an upload.uploadFile = true; This was a wonderful file that was meant to be upload.uploadingFile - a flag used to control the behavior of a spinner. Once that was fixed, the issue went away.
Example:
(function()
{
'use strict';
angular.module('aumApp.file-upload')
.controller('FileUploadCtrl', FileUploadCtrl);
function FileUploadCtrl($scope, $http)
{
upload.uploadFile = function()
{
upload.uploadFile = true;
var backendUrl = '/ua_aumcore/events/api/v1/events/uploadFile';
var fd = new FormData();
fd.append('file', upload.src);
$http({ url: backendUrl, data: fd, method: 'POST', transformRequest : angular.identity, headers: { 'Content-Type' : undefined } })
.then(function uploadSuccess(response)
{
upload.data = response.data;
upload.message = "Uploaded Succesfully.";
upload.uploadSuccess = true;
upload.uploadingFile = false;
},
function uploadFailure(response)
{
upload.message = "Upload Failed.";
upload.uploadSuccess = false;
upload.uploadingFile = false;
});
};
}
FileUploadCtrl.$inject = ['$scope', '$http'];
})();
To be callable from the view, a function must be in the $scope. Add
$scope.login = login;
to the JS code of the controller.
You also need to actually use that controller. Change
<div class="container" style="max-width: 300px">
to
<div ng-controller="AuthCtrl" class="container" style="max-width: 300px">
This is all fundamental stuff. My advice would be to learn from an AngularJS tutorial before going further.
Two enable two-way binding you have to assign your login function to $scope. Replace your code for function with this:
$scope.login=function() {
ref.authWithPassword({
email : "nick.koulias#gmail.com",
password : "Jaeger01"
}, function (error, authData) {
if (error) {
console.log("Login Failed!", error);
} else {
console.log("Authenticated successfully with payload:", authData);
}
});
}
It may be a late answer by me.
But It working for me
Check form name you set
e.g. ng-form="login"
and function name
e.g. ng-click="login()"
Then it will not work . You have to change one of them.
e.g. ng-form="loginForm"
Explanation:
AngularJS 1.x registers any form DOM element that has a name property in $scope via formDirectiveFactory. This directive automatically instantiates form.FormController if the above is true:
If the name attribute is specified, the form controller is published onto the current scope under
from: angular.js:24855
Hence if you have a <form name=myForm> it will override your $scope.myForm = function() { ... }

Angularjs cannot read property firstname of undefined

I have a form such as
Html:
<form ng-submit="log(user)">
<input type="text" ng-model="user.firstname">
<input type="text" ng-model="user.lastname
</form>
Angular:
.controller ('', function ($scope){
$scope.log = function (user){
console.log (user.firstname)
}
})
This was working before but now it throws cannot read property user.firstname
Please help me. Thank you
AngualarJs is rich in two way data binding. You didn't need to pass the scope object user in the function log. Its available in controller always with updated value. Just Initialise the user as scope object and try the code
In html:
<form ng-submit="log()">
<input type="text" ng-model="user.firstname" />
<input type="text" ng-model="user.lastname" />
</form>
In Js
.controller ('', function ($scope){
$scope.user = {}; // Declare here
$scope.log = function (){
console.log ($scope.user.firstname);
}
})
if user parameter is undefined you can't access firstname on undefined value, You can try below snippet to solve your problem.
.controller ('', function ($scope){
$scope.log = function (user){
if(user){ //Strict Check: toString.call(user) == "[object Object]"
console.log (user.firstname)
}
}
})
This is full working example, somewhat similar to yours.
<div ng-app="myApp" ng-controller="myCtrl">
First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{firstName + " " + lastName}}
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.firstName = "John";
$scope.lastName = "Doe";
});
</script>
Please try this.
Thanks
Amit
Remove below code
ng-submit="log(user)"
and remove button type submit
and add below line
<input type="button" ng-click="log()"/>
Your js file
$scope.log=function(){
console.log($scope.firstname);
console.log($scope.lastname);
}

Select some data and then persist to next controller/view in Angularjs

I am bringing in some simple data via a service that uses angular-resource like so:
angular.module('InvoiceService',
['ngResource'])
.factory('InvoiceService', function ($resource) {
return $resource('data.json');
})
.controller("DashboardListCtrl", function (InvoiceService) {
var vm = this;
InvoiceService.query(function (data) {
vm.invoices = data;
});
vm.submit = function (form) {
console.log(form)
};
});
And the html:
<form name="invoices" role="form" novalidate>
<ul>
<li ng-repeat="invoice in vm.invoices">
<input type="checkbox" id="{{'id-' + $index}}" />
<p><strong>Order:</strong></p>
<p>{{invoice.order}}</p>
</li>
<input type="submit" value="Continue" ng-click="vm.submit(invoices)" />
</ul>
</form>
Everything works fine; the data is displays in the view as expected.
The question:
What I'd like to do is be able to select a checkbox, grab the bit of data associated with that checkbox, and pass it along to the next controller/view on submit. How can I do this?
So, what do I do next? Am I on the right track?
**EDIT: added all angular code to help clarify
Posting answer as reply too big to be useful.
You should be using $scope to isolate the controller's data from the rest of the page.
Read up about ng-model http://docs.angularjs.org/api/ng/directive/ngModel and how to use it to two-way-bind checkbox value to a controller variable. No need to use theFormName if you call $scope.submit = function() { } as your ng-model variable will be available in $scope already.
angular.module('InvoiceService',
['ngResource'])
.factory('InvoiceService', function ($resource) {
return $resource('data.json');
})
.controller("DashboardListCtrl", function ($scope, InvoiceService) {
InvoiceService.query(function (data) {
$scope.invoices = data;
});
$scope.submit = function () {
// FIXME to access a property of each $scope.invoices
console.log('checkbox1=' + $scope.invoices[0].checkbox1);
};
});
Then the HTML:
<form role="form" novalidate ng-controller="DashboardListCtrl"><!-- EDIT: added ng-controller=, remove name= -->
<ul>
<li ng-repeat="invoice in invoices"><!-- EDIT: remove 'vm.' -->
<input type="checkbox" id="{{'id-' + $index}}" ng-model="invoice.checkbox1" /><!-- EDIT: added ng-model= -->
<p><strong>Order:</strong></p>
<p>{{invoice.order}}</p>
</li>
<input type="submit" value="Continue" ng-click="submit()" /><!-- EDIT: remove 'vm.' -->
</ul>
</form>

Is there a better way to gather angular form data (for submit)

this is my solution, but I do not know if it is the right way.
html:
<div ng-controller='myctrl as mc'>
<form name='mc.form' ng-submit='mc.submit'>
<input type='email' name='email' />
<input type='user' name='user' />
<button type='submit'>submit</button>
</form>
</div>
javascript:
angular.module('myapp').controller('myctrl', ['$scope', function myctrl($scope) {
var th = this
this.submit = function(form) {
if(!th.form.$invalid) postToServer(getFormData())
}
//I checked the form object, no helper method like this
function getFormData() {
var res = {}
angular.forEach(th.form, function(value, key) {
if(key[0] !== '$') res[key] = value.$modelValue
})
return res
}
function postToServer(data) {
//do post to server
console.log(data)
}
}])
This is an example of basic Angular Forms usage. You want to use ng-modal and within your Controller $scope you should have a Object for your form data that you will be processing. If you give the form a name attribute, it will bind this to your Controller $scope so that you can access within your controller, for example <form name="myForm"> == $scope.myForm.
Please find this live example below, if you open your Console F12 menu you will see the form data when it is submitted.
http://plnkr.co/edit/XSiPnDdB5umxOzu0V3Pf?p=preview
<form name="myForm" ng-submit="submitForm()">
Email: <input name="email" type="email" ng-model="formData.email" />
<br />
User: <input name="user" type="text" ng-model="formData.user" />
<br />
<button type="submit">Submit</button>
</form>
<script>
angular.module('myApp', [])
.controller('mainCtrl', function($scope) {
$scope.formData = {};
$scope.submitForm = function() {
// do form submit logic
// this is the object declared in the controller
// binded with ng-model
console.log('$scope.formData');
console.log($scope.formData);
// this is the ng-form $scope binded into
// the Controller via <form name="name">
// this hold more that just the form data
// validation errors form example
console.log('$scope.myForm');
console.log($scope.myForm);
};
});
</script>
You should use ng-model, it will all the form data will be sent as an object
<div ng-controller='myctrl as mc'>
<form name='mc.form' ng-submit='mc.submit'>
<input ng-model='formData.email' name='email' />
<input ng-model='formData.user' name='user' />
<button type='submit'>submit</button>
</form>
</div>
The input value will bind to the properties of an object call formData in controller
angular.module('myapp').controller('myctrl', ['$scope',
function myctrl($scope) {
var th = this;
$scope.formData= {}; //Initialise the object
this.submit = function(form) {
if (!th.form.$invalid) postToServer();
}
function postToServer() {
//do post to server
console.log($scope.formData); //The value of input will bind to the property of formData
}
}
])

Unable to submit data via form

I have a simple form:
<form ng-submit='addMessage()'>
<input type='text' ng-model='chatMessage' placeholder='chat here' />
<input type='submit' value='chat' />
</form>
And at the moment, a very simple function:
$scope.addMessage = function() {
console.log($scope.chatMessage);
}
The console logging is just logging undefined, no matter what I type into the input box. Clearly I'm missing something, but I'm not sure what that is.
Depending on the way forms are used, sometimes $scope is out of context between the controller on the form. This is because addMessage(), and chatMessage are not on the same level of the $scope hierarchy.
One way to fix this is to create a container for your form items:
$scope.cont = {};
$scope.addMessage = function() {
console.log($scope.cont.chatMessage);
}
And in the form:
<input type="text" ng-model="cont.chatMessage" placeholder="chat here"/>
This is also something you should definitely read if you are going to use angular more: http://jimhoskins.com/2012/12/14/nested-scopes-in-angularjs.html
Look for that fiddle maybe you missed something different .
<div ng-app="app">
<div ng-controller="mainCtrl">
<form ng-submit='addMessage()'>
<input type='text' ng-model='chatMessage' placeholder='chat here' />
<input type='submit' value='chat' />
</form>
<pre>{{msg | json}}</pre>
</div>
</div>
JS:
var app = angular.module("app", []);
app.controller("mainCtrl", function ($scope) {
$scope.msg = [];
$scope.addMessage = function () {
$scope.msg.push($scope.chatMessage);
console.log($scope.chatMessage);
$scope.chatMessage = "";
}
});
This should work:
<form ng-submit='addMessage(chatMessage)'>
<input type='text' ng-model='chatMessage' placeholder='chat here' />
<input type='submit' value='chat' />
</form>
And in your controller:
$scope.addMessage = function(msg) {
console.log(msg);
}
UPDATE
based on your comments i think you are looking for something like this:
$scope.messages = [];
$scope.$watch('messages', function(newMessage) {
alert('hey, a message was added ! :' +newMessage);
}, true);
$scope.addMessage = function(msg) {
$scope.messages.push(msg);
};
Angular has so called watches, the watched function will trigger everytime when a new message is addded to the array. For more information about watches refer to the docs

Resources