AngularJS form Cannot read property '$setPristine' of undefined - angularjs

I know there is other similar questions to this, but i've read them all and none of them is working for me.
When i try to set my form to a pristine, I keep getting this error:
TypeError: Cannot read property '$setPristine' of undefined
The controller and my angular version (1.4.2) are everything ok, because i also have other thing happening within the same function calling the $setPristine(); method and that one is working.
This is the code i'm using:
html
<form name="cadTel" novalidate>
<div class="form_group">
<label class="col-md-4 f--label"><i class="fa fa-asterisk"></i>Nome</label>
<div class="col-md-8 f--input">
<input type="text" name="ds_contato" ng-model="tel.ds_contato" ng-required="true" />
</div>
</div>
<div class="form_group">
<label class="col-md-4 f--label"><i class="fa fa-asterisk"></i>Telefone</label>
<div class="col-md-8 f--input">
<input type="text" name="num_tel" mask="(99) 9?9999-9999" ng-model="tel.num_tel" ng-required="true" />
</div>
</div>
<input type="button" class="bt-m bt-suc" name="cadastrar" value="Salvar" ng-click="add_telefone(tel)">
<div class="bt-m bt-war" ng-click="reset()">Limpar</div>
</form>
app.js
$scope.tel = {};
$scope.add_telefone = function(tel) {
$scope.tel = angular.copy(tel);
$http({
method: 'POST',
url:'dist/php/db.php?action=add_telefone',
data:$scope.tel,
})
.success(function (data, status, headers, config) {
$scope.reset();
})
.error(function (data, status, headers, config) {
});
};
$scope.reset = function() {
$scope.tel = {};
$scope.cadTel.$setPristine();
};
The option to clean the values are working but to set pristine none.
Any ideas?

I faced the same issue and below fix corrected it.
Angular is not aware of the form id. Please change the form name as below
form name="form.cadTel"
Also during the controller startup set the form
$scope.form = {};
Check this plnkr link.

I am using bootstrap modal to show the forms and when I click Cancel or click outside of modal I wanted to reset the form. I spent hours troubleshooting AngularJS form Cannot read property '$setPristine' of undefined error and solved it by adding a simple condition before reseting the form:
$('#myform-modal').on('hidden.bs.modal', function () {
resetModal();
});
resetModal = function() {
if ( $scope.MyForm ) {
$scope.MyForm.$setPristine();
$scope.MyForm.$setUntouched();
$scope.MyForm.$submitted = false;
delete $scope.data;
}
}

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() { ... }

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>

Cannot read property $valid of undefined

I have a form like this -
<form name="myForm" novalidate>
There are some fields in the form which I am validating and then submitting the form like this -
<input type="button" ng-click="Save(data)" value="Save">
In the controller, I want to check if the form is not valid then Save() should show some error on the page. For that, I am setting up a watch like this -
$scope.$watch('myForm.$valid', function(validity) {
if(validity == false)
// show errors
});
But I am always getting this error on running it -
Cannot read property '$valid' of undefined
Can someone explain why?
Thanks
You just misspelled "myForm" in your controller code. In order to remove the error, Write "myform" instead of "myForm".
However I expect what you want is like this.
$scope.Save = function(data){
alert($scope.myform.$valid);
}
I setup jsfiddle.
In my case I was wrapping the form in a modal created in the controller and therefore got the same error. I fixed it with:
HTML
<form name="form.editAddress" ng-submit="save()">
<div class="form-group">
<label for="street">Street</label>
<input name="street" type="text" class="form-control" id="street" placeholder="Street..." ng-model="Address.Street" required ng-minlength="2" />
<div class="error" ng-show="form.editAddress.street.$invalid">
<!-- errors... -->
</div>
</div>
<button type="submit" class="btn btn-primary" >Save address</button>
</form>
JS
angular.module("app").controller("addressController", function ($scope, $uibModal, service) {
$scope.Address = {};
$scope.form = {};
$scope.save = function() {
if (modalInstance !== null) {
if (isValidForm()) {
modalInstance.close($scope.Address);
}
}
};
var isValidForm = function () {
return $scope.form.editAddress.$valid;
}
});

How to get the value from text box on button click angular js

<form class="form-group has-success has-feedback" novalidate>
<br/>
<label class="control-label" for="inputSuccess2">Enter the Phone Number</label>
<input type="number" class="form-control" ng-model="user.phonenum" name="phonenum" id="inputSuccess2">
<button ng-click="myData.doClick(item, $event)" class="btn btn-primary">Get Mobile Phone Number Data</button>
</form>
<br/>
Data from server: {{myData.fromServer.State}}
<script>
angular.module("myapp", [])
.controller("MyController", function($scope, $http) {
$scope.myData = {};
$scope.myData.doClick = function(item, event) {
var responsePromise = $http.get("https://ajith-indian-mob-info.p.mashape.com/getInfo?mobno="+item, {headers: {'X-Mashape-Key': ''}});
responsePromise.success(function(data, status, headers, config) {
$scope.myData.fromServer = data;
});
responsePromise.error(function(data, status, headers, config) {
alert("AJAX failed!");
});
}
});
</script>
Hi i am new to angular how do i get the value from textbox into the controller angular?
Personally in my controller, I define the object user (for a better reading, this is not required)
$scope.user = {}
Then
<input type="number" class="form-control" ng-model="user.phonenum" name="phonenum" id="inputSuccess2">
will automatically bind the content of this textbox to the variable $scope.user.phonenum, you can access it, simply with :
$scope.myData.doClick = function() {
var responsePromise = $http.get("https://ajith-indian-mob-info.p.mashape.com/getInfo?mobno="+$scope.user.phonenum, {headers: {'X-Mashape-Key': ''}});
...
you can get the value of model in your controller if it is inside the scope of the controler with $scope.ModelName
do this $scope.user.phonenum wherever you want the value of phone number
But check if the model is within the scope of the controller.
with Angular you should change your way of thinking, in the controller you don't work with the view... you work with the model (and let the directives update that model). So, in your example the textbox is mapped to user.phonenum, so you could do something like $scope.user.phonenum in your controller.

Submit form with ng-submit and trigger synchronous post request

I have a form that I want to trigger validation on when the user clicks submit. If the validation fails, then suitable error messages are displayed. This much works.
However if the validation passes I want the form to submit a synchronous POST request with full page reload as if the action and method parameters were set as usual.
How does one achieve trigger the normal post action (not AJAX) from the ng-submit function on the AngularJS scope?
My form of course looks basically like the following:
<form id="myForm" name="myForm" ng-submit="formAction(this, models)">
...
<input type="submit" value="Submit">
</form>
The best I can think of is to mirror the contents of the form with another hidden form submitting that one, but there must be a better way!
TO CLARIFY: If validation passes, I need the form submission to essentially behave like a normal synchronous post form submission which lands the user at the page returned by the server from the post request.
http://plnkr.co/edit/cgWaiQH8pjAT2IRObNJy?p=preview
Please check this plunkr
Basically what I am doing is passing the $event object. form is the target of the event object, and we can submit it.
function Ctrl($scope) {
$scope.list = [];
$scope.text = 'hello';
$scope.submit = function($event) {
if ($scope.text) {
$scope.list.push(this.text);
if(this.text === 'valid'){
$event.target.submit();
}
$scope.text = '';
}
};
}
Try inside formAction after you've submitted the data:
$route.reload();
I dont think you need to do a full page refresh. You have a single page app I am assuming; use it. Try something like this:
<section class="contact">
<article>
<h1>Contact</h1>
<form role="form" name="contactForm" ng-submit="formSubmit(contactForm)">
<div class="form-group">
<input class="form-control" ng-model="name" name="name" id="name" type="text" placeholder="Name" required/>
</div>
<div class="form-group">
<input class="form-control" ng-model="email" name="email" id="email" type="email" placeholder="Email Address" required/>
</div>
<div class="form-group">
<textarea class="form-control" ng-model="message" name="message" id="message" rows="5"></textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-lg">Send Message</button>
<a class="btn btn-default btn-lg" href='mailto:me#something.net'>Or email me</a>
</div>
</form>
</article>
'use strict';
MyApp.controller('ContactController', function ContactController ($scope, EmailService) {
$scope.formSubmit = function(form) {
EmailService.send(form).then(function(data) {
if(data.message.sent) {
$scope.resetForm();
alert("Message Sent");
}
else {
alert("Something went wrong. Try emailing me.");
}
});
}
$scope.resetForm = function() {
$scope.name = "";
$scope.email = "";
$scope.message = "";
}
});
MyApp.factory('AjaxService', function AjaxService ($q, $http) {
return {
http: function(ajaxParams) {
var deferred = $q.defer();
$http(ajaxParams)
.success(function (data, status, headers, config) {
deferred.resolve({
success: true,
status: status,
message: data
});
})
.error(function (data, status, headers, config) {
deferred.reject({
success: false,
status: status,
message: "Http Error"
});
});
return deferred.promise;
}
}
});
MyApp.factory('EmailService', function EmailService (AjaxService) {
return {
send: function(emailData) {
var ajaxParams = {
method: 'POST',
url: ''//where ever your form handler is,
data: {
name: emailData.name.$modelValue,
email: emailData.email.$modelValue,
message: emailData.message.$modelValue
},
cache: false
}
return AjaxService.http(ajaxParams);
}
}
});

Resources