Submit form with ng-submit and trigger synchronous post request - angularjs

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);
}
}
});

Related

ng-click only where paper-input form is valid

I'm new to web and can't figure this one out:
I have a form that I want the submit button to be disabled while the form is invalid.
I've tried using the X.$valid and the X.checkValidity() but with no help. I've also looked at the iron-form examples and documentation but I can't
I assume my trouble is the use of Angular + Polymer but I can't find a solution to how to get the behavior I want.
here is my code:
<form id="loginForm" novalidate>
<paper-input ng-model="username" label="{{::tr('Enter a username')}}" required auto-validate error-message="{{::tr('Please enter your username')}}" ng-keyup="keyPress($event.keyCode)" ng-change="password = ''"></paper-input>
<paper-input ng-model="password" label="{{::tr('Enter a password')}}" required auto-validate error-message="{{::tr('Please enter your password')}}" type="password" ng-keyup="keyPress($event.keyCode)"></paper-input>
<div id="loginFailureReason"></div>
<div class="pm4-form-footer">
<paper-button raised ng-click="forgotPassword();" ng-enable="!loading">{{::tr('Forgot your password') }}</paper-button>
<paper-button raised type="submit" ng-click="loginForm.$valid && login()" ng-enable="loginForm.$valid && !loading">{{::tr('Sign in')}}</paper-button>
</div>
</form>
Code of the controller:
loginApp.controller('LoginController', ["$scope", "$http", "$window","trFilter",
function ($scope, $http, $window, tr) {
//Used to determine if to present the reset password form or not
$scope.resettingPassword = false;
//Used to determine if to present the reset code form or not
$scope.submitResetCode = false;
//Model fields that will be sent to server
$scope.username = '';
$scope.password = '';
$scope.login = function () {
$scope.loading = true;
$('input[ng-model], select[ng-model]').each(function () {
angular.element(this).controller('ngModel').$setViewValue($(this).val());
});
$http.post('/Account/DoLogin', { username: $scope.username, password: $scope.password }).
success(function (data, status, headers) {
if (headers('AccountCtrResponse') !== null && headers('AccountCtrResponse') === "Done") {
$window.location.replace("/" + $window.location.hash);
} else {
$scope.logonFailureReason = tr("Login failed due to the following reason: " +headers('AccountCtrResponse'));
$scope.loading = false;
}
}).
error(function () {
$scope.logonFailureReason = "Failure in submitting the request. Try again later or report this if it persists.";
$scope.loading = false;
});
};
If I add the following code it works but I think it is incorrect to put that logic in the controller. In the html:
<paper-button id="submitionButton" raised type="submit" ng-disabled="!formValidity()">
{{::tr('Sign in')}}
</paper-button>
In the controller:
$scope.formValidity = function () {
return loginForm.checkValidity();
};
Try:
<form name="loginForm" >
<paper-input ng-model="username" label="{{::tr('Enter a username')}}" required auto-validate error-message="{{::tr('Please enter your username')}}" ng-keyup="keyPress($event.keyCode)" ng-change="password = ''"></paper-input>
<paper-input ng-model="password" label="{{::tr('Enter a password')}}" required auto-validate error-message="{{::tr('Please enter your password')}}" type="password" ng-keyup="keyPress($event.keyCode)"></paper-input>
<div id="loginFailureReason"></div>
<div class="pm4-form-footer">
<paper-button raised ng-click="forgotPassword();" ng-disabled="loading">{{::tr('Forgot your password') }}</paper-button>
<paper-button raised type="submit" ng-click="login()" ng-disabled="!loginForm.checkValidity()">{{::tr('Sign in')}}</paper-button>
</div>
</form>

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

angular form validation not working on form submitting

I'm new in angularJS. My form doesn't validate on submit. I use angular-validation module downloaded from bower. How can I validate form on submit button?
I use refrence from https://github.com/huei90/angular-validation/blob/master/API.md
My form is like that:
<div ng-controller="nameController">
<form name="myForm" ng-submit="submitForm()">
<label for="ud_fname"></label>
<input
type="text"
id="ud_fname"
name="ud_fname"
placeholder="First Name"
ng-model="form.ud_fname"
valid-method="blur"
validator="required"
required-error-message="Required"
>
<label for="ud_lname"></label>
<input
type="text"
id="ud_lname"
name="ud_lname"
placeholder="Last Name"
ng-model="form.ud_lname"
valid-method="blur"
validator="required"
required-error-message="Required"
>
<input type="submit" value="Add" class="pure-button" />
<input type="reset" value="Reset" class="pure-button" />
</form>
My Controler is like that:
app.controller('nameController', function ($scope, $http) {
// insert record
$scope.submitForm = function (){
var url= 'functions/insert.php';
var data = {
ud_fname: $scope.form.ud_fname,
ud_lname : $scope.form.ud_lname,
};
console.log(data);
$http({
url: url,
data: data,
method: 'post'
}).success(function (response){
console.log(response);
});
};
});
You need to validate on ng-submit & don't call an submitForm if its not valid form
ng-submit="myForm.$valid && submitForm()"
You need to validate the form in your controller as well. Also, it would be better if you pass the form (user) as a parameter. If you are writing unit tests (which you should), it would be easier to test your method easily in that case as there will be no coupling with $scope.
P.S. Migrate your code to controllerAs syntax, you won't regret it.
$scope.submitForm = function (user, isValid){
if (isValid) {
var url= 'functions/insert.php';
var data = {
ud_fname: user.ud_fname,
ud_lname : user.ud_lname,
};
console.log(data);
$http({
url: url,
data: data,
method: 'post'
}).success(function (response){
console.log(response);
});
}
};
And your form will become:-
<form name="myForm" ng-submit="submitForm(form, myForm.$valid)">
.....
</form>

ng-click event is not firing on button click?

i'm creating web application in Angularjs i write code in separate .js file for log in from database
is is execute on page load but not triggering on button click,
my .js code is:
var adminModule = angular.module('angApp', []);
//Defining a Angular Controller
adminModule.controller('AdminCtrl', ['$scope', '$http',
function ($scope, $http) {
Login();
function Login(U_Name, U_PWD) {
debugger;
//Defining the $http service for login the admin user
$http({
method: 'POST',
url: '/Admin/IsAuthenticate',
data: { User_Name: U_Name, User_PWD: U_PWD }
}).success(function (result) {
if (result == true) {
alert('user is valid');
}
else {
alert('unauthorised access!');
}
}).error(function (error) {
//Showing error message
$scope.status = 'Unable to connect' + error.message;
});
}
}]);
and my view as what i'm using for binding this using Angularjs here is an issue above code is working on page load but don't work on button click, the code i use is:
<div class="admin-login" ng-controller="AdminCtrl" ng-app="angApp">
<h2>using angularjs</h2>
<input type="text" id="txtUserAng" placeholder="User Name" ng-model="U_Name" />
<input type="password" id="txtPWDAng" placeholder="Password" ng-model="U_PWD" />
<input type="button" id="login" value="login" ng-click="Login()" />
</div>
anyone please help me what i miss here so i'm not able to trigger ng-click event on button click
thanks in advance.
Your Login function needs to be on a scope. Right now, its essentially a private function:
$scope.Login = function () {
...
}
assign function to a scope variable.
var adminModule = angular.module('angApp', []);
//Defining a Angular Controller
adminModule.controller('AdminCtrl', ['$scope', '$http',
function ($scope, $http) {
$scope.Login = function (U_Name, U_PWD) {
debugger;
//Defining the $http service for login the admin user
$http({
method: 'POST',
url: '/Admin/IsAuthenticate',
data: { User_Name: U_Name, User_PWD: U_PWD }
}).success(function (result) {
if (result == true) {
alert('user is valid');
}
else {
alert('unauthorised access!');
}
}).error(function (error) {
//Showing error message
$scope.status = 'Unable to connect' + error.message;
});
}
$scope.Login();
}]);
Edited:
try to use this html code,but i am not sure.it may be that both ng-init and ng-controller are in same div and ng-controller load first after that ng-init :
<div ng-app="angApp">
<div class="admin-login" ng-controller="AdminCtrl" >
<h2>using angularjs</h2>
<input type="text" id="txtUserAng" placeholder="User Name" ng-model="U_Name" />
<input type="password" id="txtPWDAng" placeholder="Password" ng-model="U_PWD" />
<input type="button" id="login" value="login" ng-click="Login()" />
</div>
</div>

how to send values from view controls to angularjs controller..?

In my Angularjs MVC application i write code for lo-gin which accept values from two text boxes as user name & password
my Angularjs controller code is as which works fine but problem with view
$scope.Login = function Login(U_Name, U_PWD) {
//Defining the $http service for login the admin user
$http({
method: 'POST',
url: '/Admin/IsAuthenticate',
data: { User_Name: U_Name,
User_PWD: U_PWD }
}).success(function (result) {
if (result == true) {
alert('user is valid');
}
else {
alert('unauthorised access!');
}
})
.error(function (error) {
//Showing error message
$scope.status = 'Unable to connect' + error.message;
});
}
this code is executing on ng-click event but doesn't accept values from input boxes
my view code is as:
<div ng-app="angApp">
<div ng-controller="AdminCtrl">
<div class="admin-login">
<h2>using angularjs</h2>
<input type="text" id="txtUserAng" placeholder="User Name" ng-model="U_Name" />
<input type="password" id="txtPWDAng" placeholder="Password" ng-model="U_PWD" />
<input type="button" id="login" value="login" ng-click="Login()" />
</div>
</div>
</div>
Your problem is that you are not passing U_Name, U_PWD variable to Login function. You need to pass input values to your function.
There are 2 ways of achieving it.
First, Pass the model directly to function like
<input type="button" id="login" value="login" ng-click="Login(U_Name, U_PWD)" />
Second, Use $scope.U_Name and $scope.U_PWD
$scope.Login = function() {
var U_Name = $scope.U_Name,
U_PWD = $scope.U_PWD
}
In controller get this
this example without set login parametr
$scope.Login = function Login() {
var U_Name = $scope.U_Name;
var U_PWD = $scope.U_PWD;
console.log($scope.U_Name);
console.log($scope.U_PWD);
}
And you can set login function parrameters that model
<input type="button" id="login" value="login" ng-click="Login(U_Name, U_PWD)" />
use this
data:
{
User_Name: $scope.U_Name,
User_PWD: $scope.U_PWD
}

Resources