Angular 2: Apply remote validation errors to form - forms

When submitting a form to my backend, I might get a response with http code 400 indicating that validation has failed.
My backend responds with for example:
{
"status":"fail",
"data":{
"email":[
"Email address already in use"
]
}
}
I would like to invalidate the email field and set the error message, based on the response.
What I've tried is this:
if (err && err.status === 400) {
const response = err.json();
Object.keys(response.data).forEach(key => {
const messages = response.data[key];
this.registerForm.get(key).setErrors({
remote: messages[0] // Set just the first message
}, true);
});
}
This seems to work in part, the problem is that my controls does not get invalid status unless I focus the control by clicking the input.
Am I doing something wrong or is it a bug? All my Googling seems to confirm that I'm doing it correctly.
Any input appr

You can re-implement the register form adapting the reactive form style, where you can perform custom validation of form inputs and do asynchronous validation by returning promises to form to update on resolving the promise.
You may check in Angular 2 documentation for implementing reactive form validation : Reactive Form Validation - Angular 2

Related

How to get the form validation status in "react-validation", when submitting the form?

I'm trying to use react-validation for simple form validation in React. I understood how to validate the fields according to my needs, but what i do not understand, is how to get the "status" of the form, when the user tries to submit the it.
The documentation says that the Form component provides 4 public methods:
validate(name), validateAll(), showError(component [,error]), hideError(component)
From what i understand, these methods are accessible by a ref to the Form component:
<Form ref={c => { this.form = c }} onSubmit={this.handleSubmit.bind(this)}>
When i console log this.form in my submit handler, i do get an object with the above mentioned methods, but when i call one of them, like validateAll(), it returns undefined. I do not understand why.
Can someone help me with this specific plugin, or perhaps recommend a different simple alternative? I need to perform very basic validation(but can't use HTML built in one), and do not need something fancy like react-form or redux-form(i do not even use Redux in this project)
I have checked it in sandbox, please review it,
and I can tall you that it DOES work in this way. When you call this.form.validateAll() it returns undefined BUT it executes all validation functions and appends to form error messages defined in that functions. So may be it is even unnecessary validateAll to return smth
The solution I have found to provide state.isValid. Set isValid = true on form change
handleChange() {
this.setState({ isValid: true });
}
and in each validator set state.isValid = false if validation is not pass

SailsJS CSRF mismatch error customize

I need to customise the error that shows up when someone did not send the CSRF code with the POST request.
So that no one will know what happened with the error and they will not even try to hack in to the CSRF mechanism.
Hope this is clear
For now Sails.js CSRF hook uses res.forbidden() function to handle wrong CSRF token.
It uses it with this message:
return res.forbidden("CSRF mismatch");
So you could rewrite this response by placing a new file with name forbidden.js into /api/responses
Actually you cound copy this one: https://github.com/balderdashy/sails/blob/master/lib/hooks/responses/defaults/forbidden.js
And add condition to check data before production mode check:
...
else sails.log.verbose('Sending 403 ("Forbidden") response');
if (data == 'CSRF mismatch') {
//Return another response for example:
return res.jsonx(500, {/* data here */});
}
// Only include errors in response if application environment
// is not set to 'production'. In production, we shouldn't
// send back any identifying information about errors.
if (sails.config.environment === 'production') {
...
Anyway as long as you will use development mode for sails. You will see all errors when getting 500 or any other error from sails. But in production mode all error messages will be hidden. And your users wouldn't get any error details. Except of error code.
So in production mode without any changes you will get only HTTP 403 code.

Play form binding difficulties - How do I modify a request after getting it in the backend?

I'm currently trying to connect an Extjs form to a Play! Scala backend.
I have no problem receiving the request, but
FormName.bindFromRequest.get returns to me None .
I'm able to find the data generated via submitting from Extjs in the POST request in request.request.body.data (the first request object is generated by SocialSecure's controller), whereas normally the data bound to the form would be found in request.request.body.data.elems
I think Extjs's eschewal of using <form> in their inserted HTML is what causes me this problem, but I'd still like to take advantage of Extjs's nice form verification UI.
Does Play! or Scala have any resources for modifying a request after the server has received it?
More info
This is the method my /requestAudit cuurently points to after a POST request:
def requestAudit = SecuredAction(WithProvider("google")) { // SecureSocial syntax
implicit request => { // let's call this line 0'
println(request.request.body.asFormUrlEncoded) // let's call this line 1'
println(request.body.asText) // let's call this line 2'
newAuditForm.bindFromRequest.fold(
errors => BadRequest(views.html.error(newAuditForm))
success => { /*insert the object into my db*/ }
) } }
Ext.js request
When I'm debugging in Eclipse with an Ext.js form, the Variables window shows: (click for closeup)
where the form values are located in request.body.data.key1, request.body.data.key2, etc
Bootstrap form request
On the other hand, the request for Bootstrap has the values stored in request.body.data.elems
#2manyprojects 's suggestion set me on the right path:
newAuditForm.bindFromRequest(
(request.request.body.asFormUrlEncoded).getOrElse(Map()))
.fold( ... )
worked.
I was still getting form binding errors after changing my code to this, and then I discovered a typo in the name property of one of my Ext.js form fields. The name of the field must be the same on both the UI and the Play Form.

MVC jquery ajax form server side validations

We have a number of forms on our site that are shown with jquery .dialog and we submit them using an ajax post request.
I've done a fair bit of research and from what I can tell there isn't any definite patterns on how to return validation errors from the server side as a result of an ajax request.
Pretty much the only pattern I could find was to post the form and then do validation server side and in either case return a json object that encapsulated a result and if the result was incorrect the form html
ie.
{result: true}
{success: false, html = "<form>....</form>"}
So in the case the result was false you would need to rewire up any events attached to items on the form as you would be replacing the old form with the new form that has the validation errors.
This seems like an ok approach but you also end up potentially returning a lot more data to the client that you need to when they only really need to validation messages and you are also forced to rewire the form up which is a bit annoying.
I did find one other mention of somehow getting the validation errors and returning them in a json object from the action and somehow telling the client to display them against the correct fields.
Is there any frameworks out there that make this easier or should I write my own or just stick to returning the entire partial for the form and rewiring it when validation is incorrect?
I don't know of any frameworks that handle this particular case–and I don't know that there's a clear best practice–but it's easy enough to serialize validation errors and return them as a JSON object. You could try this extension method on ModelStateDictionary:
public static IEnumerable<ValidationResult> GetValidationResults(this ModelStateDictionary dictionary)
{
foreach (var key in dictionary.Keys)
foreach (var error in dictionary[key].Errors)
if (error != null)
yield return new ValidationResult(error.ErrorMessage, new string[] { key });
}
And in the controller:
if (!ModelState.IsValid)
{
return new JsonResult(ModelState.GetValidationResults());
}
But you're right, you would then have to loop through the object and append the errors to the correct fields. If you have ClientValidationEnabled and UnobtrusiveJavaScriptEnabled set to true, the loop would look something like this:
$.each(errors, function(i, item) {
$('span[data-valmsg-for=' + item.MemberNames[0] + ']').html(item.ErrorMessage);
})
If not, it wouldn't be that difficult to match up the error messages to their respective fields as the object contains the field name. This would definitely save you some data across the wire, but it moves a larger share of the validation responsibility into Javascript. Like I said, I don't know that there's a clear best practice, but I have used this method in the past with success.

ASP.NET MVC 2: Custom client side validation rule for dropdowns

I have some custom validation that I need to perform that involves checking the selected option of a dropdown and flagging it as invalid should the user select a specific option.
I am using ASP.NET MVC 2 and have a custom Validator and custom server side and client side validation rules as described in this blog article. The server side validation is working fine, however, the client side validation is failing.
Here is the javascript validation rule:
Sys.Mvc.ValidatorRegistry.validators["badValue"] = function(rule) {
var badValue = rule.ValidationParameters["badValue"];
return function(value, context) {
if (value != badValue) {
return true;
}
return rule.ErrorMessage;
};
};
The rule is being applied to the dropdowns successfully, and placing a breakpoint within the returned function confirms that the validation is firing, and that the 'badValue' is being correctly set. However, 'value' is always null, and so the check always fails. What am I doing wrong?