I have have my angular app validating a sign-up form. On submit, the server also validates the data. I'm outputting error messages in angular using ng-messages.
Here is a shortened version of my form, which works perfectly so far.
<form name="signUpForm" novalidate data-ng-submit="attemptSignUp()">
<label for="firstName">First name</label>
<input type="email" name="email" id="email" required data-ng-model="data.user.email" />
<div class="error" data-ng-messages="signUpForm.email.$error" data-ng-show="signUpForm.$submitted" data-ng-cloak>
<p data-ng-message="required">Please provide your email</p>
</div>
</form>
The server verifies the email address is unique, and if not, returns a 422 error (from Laravel 5), with an array of errors.
[
'email' => 'This email is already in use'
]
I'd like to merge in this, and any other messages sent back from the server into their relevant ng-messages block. Any idea how I could accomplish it?
A simple solution is to have two arrays. One for client side and one for server side errors which is populated in your controller. You can hide the server side errors if client errors exists or opposit to avoid double messages.
The reason I choose to have two arrays instead of populating the forms array is that the JavaScript controller should not know or be dependent on the structure of the HTML. The HTML AngularJS template should be bound to the controller, not opposit.
<form name="signUpForm" novalidate data-ng-submit="attemptSignUp()">
<label for="email">E-mail
<input type="email" name="email" id="email" required data-ng-model="data.user.email" />
<div class="error" data-ng-messages="signUpForm.email.$error" data-ng-show="signUpForm.$submitted" data-ng-cloak>
<p data-ng-message="required">Please provide your email</p>
</div>
<div class="error" data-ng-messages="serverErrors" data-ng-show="signUpForm.$submitted" data-ng-cloak>
<p data-ng-message="emailexists">Email already exists</p>
</div>
</label
</form>
A note on the label: Users using screen-readers will not get your error messages read out loud to them if they are not wrapped inside the label.
Well, this is not the most elegant solution since you really should
leverage the asyncValidators in angular 1.3.x and then create your
custom validation directives.
Resources
http://plnkr.co/edit/s4jJAOqehBkFUC9osMsy?p=preview found in the post by this guy.
Possibly here http://odetocode.com/blogs/scott/archive/2014/10/16/working-with-validators-and-messages-in-angularjs.aspx
And of course in the docs
But be cautious as this is not in any way a complete example ready to be used. It's mostly here for demo purpose and to sort of give you an idea where to start. I have not bothered with clearing any previous errors, revalidating the form or taken into account other validation errors.
Awesomeness
Imagine your controller looks like this
$scope.serverValidations = {};
$scope.attemptSignUp = function(){
Api.validateEmail($scope.email).then(angular.noop, function(data){
$scope.serverValidations = data
for(prop in $scope.serverValidations){
if($scope.signUpForm[prop]){
angular.forEach($scope.serverValidations[prop],function(validation){
$scope.signUpForm[prop].$setValidity(validation.type, false);
});
}
}
});
}
and your response data containing validation errors look like this
{
email:[
{type:'unique', message:'This email is already in use'}
],
name:[
{type:'maxlength', message:'Your name is to long, get a new one :)'}
]
};
Then in your HTML you could do like this
<div class="error" data-ng-messages="signUpForm.name.$error" data-ng-cloak="">
<p data-ng-message="required">You don't have a name?</p>
<p ng-repeat="validation in serverValidations['name']" ng-message="{{validation.type}}">{{validation.message}}</p>
</div>
Here's a dirty Codepen for you: http://codepen.io/anon/pen/yyzMgG?editors=101
When you press submit, after 2 seconds (the time it takes to hit the fake server) your server validations are presented.
First of all you should set validity and error messages
$scope.formErrors = {};
angular.forEach(errors, function(data, name) {
if (!vm.register_form[name]) {
return;
}
$scope.formErrors[name] = data.message;
//this will set errors->server to invalid state
$scope.register_form[name].$setValidity('server', false);
});
The next step will be rendering by ng-messages
<div ng-messages="register_form.email.$error">
<div ng-message="required">Email is required</div>
<div ng-message="email">Invalid email</div>
<div ng-message="server">{{formErrors.email}}</div>
</div>
I had a similar question, but the solutions did not work for me. What I did, and it is/was a hack/work around, was to send different errorcodes, and set a case statement.
Related
I am relatively new to this with some JS and PowerShell experience. I am trying to get some code to work where a user would enter their postcode and hit submit, at which point they would be able to pick their address from a list of addresses within that area. All the data from the search would then be saved to a DB under their profile.
I have found this API http://api.postcodes.io/postcodes/ which when you apend the postcode it returns all the relevant information. My question is how do I get either PHP or JS to lookup that address append the inputted postcode and return the address?
<body>
<div class="clearfix">
<label for="postcodebtn">Enter Postcode:</label><br>
<input type="text" placeholder="Enter Postcode" name="Poscodebtn" required>
<input type="submit" value="Submit">
</div>
<script>
$('#lookup_field').setupPostcodeLookup({
output_fields: {
line_1: '#first_line',
line_2: '#second_line',
line_3: '#third_line',
post_town: '#post_town',
postcode: '#postcode'
}
});
</script>
</body>
I'm the author of that JS library you're using and postcodes.io.
Unfortunately, postcodes.io won't get you premise specific data (e.g. houses at a postcode). But it looks like you're using the JS library for Ideal Postcodes which can perform that task.
In the snippet you provided, you're looking up a postcode in the browser (on JS). The data from that search should be inserted into <input> fields and posted to your PHP server.
However the main issue appears to be you're missing those <input>s as well as a <div> to accommodate your postcode lookup. Furthermore, this should be wrapped up in a form which can be submitted to your server.
There is a page with a dozen or so demos and code snippets on how to use that library here: ideal-postcodes.co.uk/jquery. It will demonstrate all the essential elements you need in order to setup postcode lookup on your website
Good luck!
is there any know that?
I'm testing some javascript as follows
function mem_join_next() {
if (document.mem_join.email.value == "") {
alert("please input your email ID");
document.mem_join.email.focus();
return;
}
document.mem_join.submit();
}
<form name="mem_join" action="/join_step_3" method="post">
<div class="col-xs-12 id">
<p><span>EMAIL</span><span class="star">*</span>
</p>
<input name='email' class="email1" type="text" style="IME-MODE: disabled" size="11">#
<input class="email2" type="text">
<div class="email-check">email_check</div>
</div>
<div class="col-xs-6 next" align="right">
<a onClick="mem_join_next()" style="cursor:pointer">
<img src="/page_imgs/member_img/btn-next.jpg">
</a>
</div>
It's code what i want to run.
But when It is processing, the screen come out the 404 not found error.
even it is right route.
I think the post is not working
cause if i go straight way to single URL address(localhost/join_step_3) , the screen come out the /join_step_3 address screen.
but if i go From join_step_2 form next button TO join_step_3, It is 404 not found please hell me! GOD PROGRAMMERS!
If you directly typed the url and it worked means the page at localhost/join_step_3 worked using GET, because the browser url uses the GET Method.
So, it is quite possible that your localhost/join_step_3 doesn't support POST Method. Therefore, either add the post support on the page depending on the server-side scripting you use, or change method="post" to method="get" in your client html.
Im learning Jquery and AJAX on my own through online tutorials and by posting on SO when I gets stuck, so please keep in mind I am a novice should you be so kind to answer my question.
I have a form inside a modalbox. Ajax prevents it from closing/reloading and a message gets displayed after submission as you can see in image below:
My problem
Both the success and failure messages gets displayed. I would like to change this so that 1) Success message gets displayed on successfull submission or 2) failure message gets displayed on failed submission:
My Form
<div id="inline3" style="width:400px;display: none;">
<h3>Contact Us</h3>
<form name="message-form" action="" id="contact-form" method"post">
Message<br /> <input type="text" name="msg" value="" /><br />
<input type="submit" value="Contact Us" name="contact" class="buttono" />
</form>
<div class="form-feedback" style="display:none">
Thank You We will Get Back to you
</div>
<div class="form-feedback" style="display:none">
Ooops....Something Went Wrong
</div>
<div>
JQUERY
$(function(){
$("#contact-form").submit(function(e){
e.preventDefault();
$form = $(this);
$.post(document.location.url, $(this).serialize(), function(data){
$feedback = $("<div>").html(data).find(".form-feedback").hide();
$form.prepend($feedback)[0].reset();
$feedback.fadeIn(1500)
})
});
})
If anyone can give me a bit of help or advise here it will be greatyly appreciated.
Thanks for reading
First thing I would do is change the backend so that instead of returning html it return json containing only the information you need (like whether the submission was a success or failure and any other messages, etc.).
Then the easiest fix that comes to my mind is to give each of your two feedback message divs unique id's:
<div id="form-feedback-success" class="form-feedback" style="display:none">
Thank You We will Get Back to you
</div>
<div id="form-feedback-error" class="form-feedback" style="display:none">
Ooops....Something Went Wrong
</div>
Keep the class names so that you can use css to style the two in a similar manner.
Then in your javascript check for a success or failure flag. Based on the flag display one or the other div based on the id:
$.post(document.location.url, $(this).serialize(), function(data){
if(data.success) {
$('#form-feedback-success').fadeIn(1500);
}
else {
$('#form-feedback-error').fadeIn(1500);
}
});
You may need to make some tweeks(like deserialize the response from json to an object), but that is the gist of it.
I have the following form as part of my webpage:
<form id="collabAccess" onsubmit="submitCollabForm()" >
<div id="row-1">
<div class="two-col" id="email"><input type="text" placeholder="Enter email addresses separated by commas"/></div>
<div id="collabSelect" class="collab two-col styled-select">
<select id="collabaccess">
<option>Can Read</option>
<option>Can Write</option>
<option>Can Read & Write </option>
<option>Administrator </option>
</select>
</div>
</div>
<div id="message">
<textarea id="personalMessage" cols="154" rows="10" placeholder="Optional: include a personal message"></textarea>
</div>
<div id="submit-wrapper"><input type="submit" value="Add Collaborators" id="addCollaborators" disabled='disabled' class="small-btn disabled"/></div>
</form>
The function submitCollabForm() is as follows:
function submitCollabForm() {
console.log('in submitCollabForm');
var valid = validateEmails();
if (valid == false) {
var email = document.getElementById('email');
email.addClass('error');
}
}
where validateEmails() is just another js function for validating that the email addresses int he form have the correct format.
However, it looks like onsubmit is not being called at all. Even if I change things to onsubmit="console.log('xyz'), no console statement is being output. I've also checked for javascript errors in the console, but I am getting nothing.
Is there any reason why onsubmit is not working properly?
Your validation function needs to return false to stop the form from submitting. It's better to have
onsubmit="return submitCollabForm()"
See With form validation: why onsubmit="return functionname()" instead of onsubmit="functionname()"? for details.
The onsubmit handler is not called, because the form cannot be submitted by any normal means, i.e. the submit event cannot be caused. There is only one submit control, and it is declared as disabled.
if you feel all code is correct still it's not working then,
Simple steps to do,
1) create one script tag in the same page where your form is, create one function and set one alert and test it. If it is working then try following steps.
2) Try to check the path of your javascript file.
3) if path is correct, then change the name of your javascript function sometimes your name tag conflicts with your function name, and submit points to it, so your call is not reaching at your function. It happened with me. so I posted it here, hope it will be helpful to someone.
I have a form with a field, and when that element has ng:invalid I am showing another (which is a tooltip) that has an error message.
However, I need to have that tooltip display different messages based on WHY the field isn't valid. For example:
If the user didn't enter ANY value, it should display "Required"
If the user didn't enter a valid email address, it should display "Please enter a vaild email address"
If the user entered an email address that exists (in a local array, say) then it should display a different message
.. and so on.
Since ng:invalid would be set even if one of the rules fail, I need a way to differentiate between the rules and idenify the one that failed, and then set the HTML for the tooltip based on that.
What's the "angular way" to do this?
EDIT: I was able to solve part of this using ng-invalid-required. But the question is still open, for multiple other rules on the same field.
By default AngularJS exposes an $error object that you can use to get more information about the error. See the following example:
<form name="userForm">
<input id="userEmail" name="userEmail" type="email" data-ng-model="userEmail">
<div class="alert alert-errors" data-ng-show="userForm.userEmail.&dirty && userForm.userEmail.&invalid">
<p data-ng-show="userForm.userEmail.$error.required">Email is required.</p>
<p data-ng-show="userForm.userEmail.$error.email">Please enter a valid email address.</p>
<div>
</form>
Angular only covers some scenarios out of the box. To cover your final requirement, you will need to write a custom validation. This should get you headed in the right direction: https://docs.angularjs.org/guide/forms