Desperately need another set of eyes. This form submission works perfectly on the first submission. But unless I reload the page again it fails. I feel like I've checked everything, the form values are reset fine no matter what in the js but for some reason they do not make it into the Request payload on the second post. Any help is much appreciated.
$scope.submitLogin = function(data) {
var form = $scope.login;
$scope.formerror = '';
$scope.success = '';
if (form.username.length > 0 &&
form.password.length > 0) {
console.log(form.username);
console.log(form.password);
$http.post('/login', form)
.success(function(data) {
$scope.success = data['res'];
$scope.login = [];
window.scrollTo(0, 0);
})
.error(function(data) {
$scope.formerror = data;
});
} else {
$scope.formerror = "something went wrong. Try again.";
}
//$scope.form = new Array({'error':'test', 'msg':''});
}
<form id="login-form" ng-submit="submitLogin()" role="form">
<label for="login_user">username: </label>
<input id="login_user" ng-model="login.username" type="text" name="username" class="form-control" placeholder="username">
<label for="login_password">password: </label>
<input id="login_password" ng-model="login.password" type="password" name="password" class="form-control" placeholder="password">
<input class="btn btn-primary" type="submit" class="btn btn-success btn-send" value="login">
</form>
Related
I want to display an error message under the 'Email Address' input if the user is disabled and display a separate error message if the user is invalid under the 'Password' input. When debugging I found that if a user is disabled the "Status code is 503" and if the input is invalid the "Status code is 400".
HTML
<md-content id="login" layout="column" layout-align="center center" class="inputdemoErrors">
<div flex="25"></div>
<p class="m0">project</p>
<form id="loginForm">
<md-input-container>
<label for="username">Email Address</label>
</md-input-container>
<md-input-container class="email-field">
<input name="username" id="username" type="email" class="validate" ng-model="username" enter-key="submitLogin()" autocomplete="off" required>
<div ng-show="disabled" ng-messages="loginForm.username.$error" role="alert">
<div ng-message="required">User Account is Disabled</div>
</div>
</md-input-container>
<md-input-container>
<label for="password">Password</label>
</md-input-container>
<md-input-container class="password-field">
<input name="password" id="password" type="password" class="validate" ng-model="password" enter-key="submitLogin()" autocomplete="off" required>
<div ng-show="invalid" ng-messages="loginForm.password.$error" role="alert">
<div ng-message="required">Invalid Email or Password</div>
</div>
</md-input-container>
<a class="waves-effect waves-light btn-large" style="width: 100%; margin: 0; background-color: #29B6F6;" ng-click="submitLogin()">Login</a>
</form>
</md-content>
JS
angular
.module('login')
.controller('LoginCtrl', LoginCtrl);
function LoginCtrl($scope, $location, SecService, RecService, Service) {
var vm = this;
vm.ctrlName = 'LoginCtrl';
$scope.submitLogin = function() {
$scope.invalid = $scope.loginForm.$invalid;
if($scope.invalid) {
return;
}
else
$scope.dataLoading = true;
var creds = {
username: $scope.username,
password: $scope.password
};
SecService.login(creds).then(function (response) {
if (response.success) {
RecService.connect();
SecService.setCredentials($scope.username, $scope.password);
Service.loadCurrentUser();
$location.path('/main');
}
if (response = 503)
{
$scope.disabled = $scope.loginForm.$disabled;
if ($scope.invalid) return invalid;
}
if (response = 400)
{
$scope.invalid = $scope.loginForm.$invalid;
if ($scope.invalid) return invalid;
}
});
};
}
}());
I am trying to display "User Account is Disabled" if the user is disabled (503), and "Email or Password is Invalid" if they have an invalid input (400). This should happen when the login button is clicked.
Hard to give a good answer without knowing what functionality you want with the ng-messages.
If you omit ng-messages:
<div ng-show="showDisabled">
User Account is Disabled
</div>
<div ng-show="showInvalid">
Invalid Email or Password
</div>
The following doesn't look right, so remove it for now:
if (response = 503)
{
$scope.disabled = $scope.loginForm.$disabled;
if ($scope.invalid) return invalid;
}
if (response = 400)
{
$scope.invalid = $scope.loginForm.$invalid;
if ($scope.invalid) return invalid;
}
It doesn't look like the return values are used anywhere and it should be response === x, not response = x.
Replace with:
$scope.showDisabled = response === 503;
$scope.showInvalid = response === 400;
Another note, if you need to access the form like this:
ng-messages="loginForm.password.$error"
The form needs a name:
<form name="loginForm">
Instead of id:
<form id="loginForm">
Hey so I have a form which has three fields name,email and phone.
<div ng-show="Nerd.adding">
<form class="col-sm-6" name="Nerd.nerdAddFrm" novalidate >
<div class="form-group">
<label for="inputName">Name</label>
<input type="text" class="form-control" id="inputName" placeholder="Name" ng-model="Nerd.nerd.name" required >
</div>
<div class="form-group">
<label for="inputEmail">Email</label>
<input type="email" class="form-control" id="inputEmail" placeholder="Email" ng-model="Nerd.nerd.email" required >
</div>
<div class="form-group">
<label for="inputPhone">Phone</label>
<input type="text" class="form-control" id="inputPhone" placeholder="Phone" ng-model="Nerd.nerd.phone" required >
</div>
<button ng-click="Nerd.saveNerd(Nerd.nerd)" type="submit" class="btn btn-primary">Submit</button>
<button ng-click="Nerd.load()" type="button" class="btn btn-default">Cancel</button>
</form>
</div>
As you can see the cancel button calls a Nerd.load() function in the controller. The controller basically resets the view and resets all the binded data to the model.
Nerd.load = function () {
Nerd.editing = false;
Nerd.adding = false;
Nerd.nerd = [];
nerdResource.query(
function (data) {
Nerd.nerds = data;
}
);
};
You can see that I am setting Nerd.nerd equal to an empty array. This should empty out the form fields data. It works fine for Name and Phone. But when I go back to the page it still shows what was last typed. There is no page reload as I am showing and hiding divs based on controller variables. EG <div ng-show="Nerd.adding">. Can anyone help me out with this?
I am on angularjs version 1.3.14. Any help on this would be great.
Thanks.
You need to attach these variables to your $scope like so:
$scope.Nerd.load = function () {
$scope.Nerd.editing = false;
$scope.Nerd.adding = false;
$scope.Nerd.nerd = [];
nerdResource.query(
function (data) {
$scope.Nerd.nerds = data;
}
);
};
Also, I think you should set $scope.Nerd to an empty object like:
$scope.Nerd = {};
instead of setting it to an empty array. You need to use $scope when interacting with the view. This code doesn't look the angular the way it is currently written.
If you can try according some way.
Nerd.load = function () {
Nerd.editing = false;
Nerd.adding = false;
Nerd.nerd = [];
nerdResource.query(
function (data) {
Nerd.nerds = data;
Nerd.nerd = []; // Put here and array make Empty
}
);
};
When I hit the submit button at the first time these codes works. But when I hit the second time to the button even if email and password values were true nothing happens and the user can not login. But if I write the true values at the first time, it works and user can login. So I figured the cause of this problem is about the "return false;" phrase. But if I remove return false; phrase, the form posts and ajax codes become useless. I must avoid the posting without ajax.
jQuery:
<script>
$(document).ready(function(){
$('#submit-btn').click(function(){
var email = $('#email').val();
email = $.trim(email);
var password = $('#password').val();
password = $.trim(password);
if(email == "") {
$('#email').css({
"background-color": "#FF7070"
});
$('#box1').css({
"visibility": "visible"
});
return false;
}else if(password == "") {
$('#password').css({
"background-color": "#FF7070"
});
$('#box2').css({
"visibility": "visible"
});
return false;
}else{
$.ajax({
type: "POST",
url: "ajax.php",
data: $('#loginform').serialize(),
timeout: 5000,
success: function(c) {
if(c == "no") {
$('#box3').css({
"visibility": "visible"
});
return false;
} else if (c == "ok") {
window.location.href = "homepage.php";
}
},
error: function(a, b) {
if (b == "timeout") {
alert("Error: #101");
}
},
statusCode: {
404: function(){
alert("Error: #102")
}
}
});
}
return false;
})
});
</script>
Html:
<form name="loginform" id="loginform" method="post" action="">
<div class="field">
<input type="text" maxlength="40" id="email" name="email" placeholder="E-mail">
</div>
<div class="field">
<input type="password" id="password" name="password" placeholder="Password" autocomplete="off">
</div>
<div class="field">
<input type="submit" id="submit-btn" value="Log in">
</div>
<div class="keep-login">
<label for="remember">
<input type="checkbox" name="remember" id="remember" checked="checked">Remember me
</label>
<span>Forgot password?</span>
</div>
</form>
PHP:
if(Input::exists()) {
if(Token::check(Input::get('token'))) {
$validate = new Validate();
$validation = $validate->check($_POST, array(
'email' => array('required' => true),
'password' => array('required' => true)
));
if($validation->passed()) {
$user = new User();
$remember = (Input::get('remember') === 'on') ? true : false;
$login = $user->login(Input::get('email'), Input::get('password'), $remember);
if($login) {
echo "ok";
} else {
echo "no";
}
} else {
echo "no";
}
}
}
First, remove the method and action attributes of the form element. You can remove the form tag altogether but if you want to support non-javascript submissions, you'll need the form tag (however, the original question did not ask for this). You're 'submitting' the form via jQuery, so you don't need a method and an action on a form tag.
Input type="password" never autocompletes, so you don't need that attribute.
I also added an error div. Here is your new html:
<div id="error" style="display: none;">Login failed.</div>
<form>
<div class="field">
<input type="text" maxlength="40" id="email" name="email" placeholder="E-mail">
</div>
<div class="field">
<input type="password" id="password" name="password" placeholder="Password">
</div>
<div class="field">
<input type="submit" id="submit-btn" value="Log in">
</div>
<div class="keep-login">
<label for="remember">
<input type="checkbox" name="remember" id="remember" checked="checked">Remember me
</label>
<span>Forgot password?</span>
</div>
</form>
Replace your $.ajax statement with a $.post statement, and simply your logic.
$.post("ajax.php", { e: email, p: password }, function (data) {
if (data == "ok") window.location.href = "homepage.php";
else $("#error").slideDown().delay(3000).slideUp(); // I added div#error with "Failed to Login" message in the html above
});
This code will now redirect if the returned data is "ok"; otherwise, it will show div#error (again, this is in the html above), delay for 3 seconds, and then hide the message.
The return false; is unnecessary in each instance in your code above because after each conditional, the code ends - there is no other code to prevent from executing (which is why you would use return false; in this context).
You can do the $.trim on the same line as when you assign the variables, like I did with the slideUp, delay, and slideDown.
I'm trying to code a controller so some inputs get disabled after changes in another one.
This is the controllre:
app.controller('SignUpController',function ($scope, $http) {
this.unavaliable = true
this.userUnavaliable = function() {
console.log(this.unavaliable)
return this.unavaliable
}
this.userExists = function(mail) {
if (mail) {
var who = $http.get("/existingUsers/"+mail)
who.success(function(data,status, headers, config) {
if (data.mail) {
this.unavaliable = true
console.log(data.mail + " ya existe en la DB")
}
else{
this.unavaliable = false
}
});
who.error(function(data, status, headers, config) {
alert("AJAX failed!");
})
}
}
})
As my markup below shows, one input should obtain a certain class, and another one should get disabled when unavaliable is set to true. But even I can get to the console.log(), the variable seems to never get true.
This is my markup:
<form class="form-inline" role="form">
<div class="form-group">
<input type="email" class="form-control input-lg" ng-model="signup.mail" placeholder="e-mail" ng-change="signup.userExists(signup.mail)" ng-class="{'has-error':signup.userUnavaliable()}">
</div>
<div class="form-group">
<input type="password" class="form-control input-lg" placeholder="Contraseña" ng-nodel="signup.password">
</div>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="signup.role" value="admin"> Administrador
</label>
</div>
<button type="submit" class="btn btn-primary" ng-disabled="signup.unavaliable" >Registrar</button>
</form>
I tried with $scope instead of this but never got it to work that way
Try this:
app.controller('SignUpController',function ($scope, $http) {
var that = this;
that.unavaliable = true;
that.userUnavaliable = function() {
console.log(that.unavaliable)
return that.unavaliable
}
that.userExists = function(mail) {...
Your issue seems to be related to JS Context; in the example above it is preserved in that variable. That is how it is done in JOhn's Papa approach
I just implemented a reCaptcha on a WP Site contact form.
It works like this:
Submission is cancelled using $form.submit(function(e) { e.preventDefault(); return false; }
reCaptcha is dynamically inserted before the form.
if reCaptcha's AJAX response is successful, perform HTLMFormElement.submit, using $form[0].submit();
HTML
<div id="ny_cf-3" class="footer-ny widget widget_ny_cf"><h2 class="widgettitle">Contact Us</h2>
<!-- contact form widget -->
<p class="response"></p>
<form method="post" enctype="multipart/form-data" class="ny-footer-contact-form" action="http://wpstage.leadscon.com/leadsconny/" data-submit="return fm_submit_onclick(1)" id="fm-form-1" name="fm-form-1">
<div class="form-group" id="fm-item-text-53546749dea0d">
<input type="text" name="text-53546749dea0d" id="text-53546749dea0d" style="width:px;" placeholder="Your name" class="form-control">
</div>
<div class="form-group" id="fm-item-text-5354674e4b90b">
<input type="text" name="text-5354674e4b90b" id="text-5354674e4b90b" style="width:px;" placeholder="Email address" class="form-control">
</div>
<div class="form-group" id="fm-item-textarea-5354675009293">
<textarea name="textarea-5354675009293" id="textarea-5354675009293" style="width:px;height:100px;" placeholder="Your message" class="form-control"></textarea>
</div>
<input type="email" class="teddybear" style="display:none">
<button type="submit" id="fm_form_submit" name="fm_form_submit" class="btn btn-primary btn-block submit">Submit</button>
<input type="hidden" name="fm_nonce" id="fm_nonce" value="1165f15ac2">
<input type="hidden" name="fm_id" id="fm_id" value="1">
<input type="hidden" name="fm_uniq_id" id="fm_uniq_id" value="fm-536b89c742833">
<input type="hidden" name="fm_parent_post_id" id="fm_parent_post_id" value="4">
</form>
<!-- end cf widget -->
</div>
JavaScript code:
var getRecaptcha = function($form, $frmResponseField) {
$form.fadeOut();
// Add the reCaptcha
// ========================================================================
var $recaptchaForm = $('<form class="recaptcha_form" style="display:none;"><p><strong>Spam verification (sorry):</strong></p><p class="response"></p><button class="btn btn-success btn-sm" type="submit">Submit</button></form>');
var recaptcha_el = $('<div id="recaptcha_el"></div>').insertAfter($recaptchaForm.find('.response')).get(0);
$recaptchaForm.insertBefore($form).slideDown();
leadsCon.reCaptchaHTML().appendTo($(recaptcha_el));
Recaptcha.create('6LdUZPASAAAAAGZI_z-qQ7988o0nGouHHtIsh4yX', recaptcha_el, {
theme : 'custom',
custom_theme_widget: 'recaptcha_widget',
callback: Recaptcha.focus_response_field
});
// Bind submit action to check it
$recaptchaForm.submit(function(e) {
e.preventDefault();
var challenge = Recaptcha.get_challenge();
var response = Recaptcha.get_response();
var $btn = $recaptchaForm.find('button[type="submit"]')
var btnVal = $btn.html();
var $responseField = $recaptchaForm.find('.response');
var data = {
action: 'verify_recaptcha',
challenge: challenge,
response: response
};
$btn.html("<i class='dashicons dashicons-clock'></i>");
$responseField.text('');
$.post(ajax_object.ajax_url, data, function(response) {
if ( response.success == true ) {
$responseField.removeClass('text-danger').addClass('text-success').html('<i class="icon-ok"></i> You got it. One second...');
// We're ok.. send.
Recaptcha.destroy();
$recaptchaForm.remove();
$frmResponseField.removeClass('text-danger').addClass('text-success').html('<i class="icon-ok"></i> Wait while we send your message.');
$form[0].submit();
} else {
$responseField.removeClass('text-success').addClass('text-danger').html('<i class="dashicons dashicons-dismiss"></i> Oops! Try again.');
$btn.html(btnVal);
}
});
});
};
$('.ny-footer-contact-form').submit(function (e) {
e.preventDefault();
var $form = $(this);
var $responseField = $form.siblings('.response').removeClass('text-success text-danger').html('');
var command = $form.attr('data-submit').match(/return (\w+)\((.+)\)/i);
var fn = window[command[1]];
var $honeypot = $form.find('input.teddybear');
if ( fn(command[2]) && $honeypot.val() == '' ) {
getRecaptcha($form, $responseField);
} else {
$responseField.removeClass('text-success').addClass('text-danger').html('<i class="dashicons dashicons-dismiss"></i> There are missing fields.');
}
return false;
});
My impression is that since $form[0].submit() is not in any way filtered and doesn't trigger the submit event from jQuery, spammers are using that to submit the form and circunvent the reCaptcha.
What can I do?
A spammer will not execute your javascript code. They will simply post to the correct URL. Therefore you can't reliably validate anything on the client, you'll have to validate it on the server as well.
Bots can even does not run your JS - they just find forms in raw html and try to act as an user submitting the form. You have to validate reCaptcha value on server side, see here: https://developers.google.com/recaptcha/docs/php