Our credit card processor (Braintree Payments) requires that we not use the "name" attribute on credit card fields (card number, expiration date, and CCV) to obviously make sure they don't get POSTed to the server unencrypted. I found a custom Extension to generate a name-less text box (How to extend html.textboxfor to remove the name attribute?). This works great, since it allows us to generate a text box without the name attribute, but it still adds all the other validation attributes and such automatically. But I have run into a problem.
When I use #Html.NameLessTextBoxFor(model => model.CardNumber) in my view, it correctly generates the text box without a name attribute. We also use Data Annotations in the View Model to generate unobtrusive validation. The visible problem on the actual website is that when there is a validation error with one of these name-less fields, the ValidationMessage span doesn't display any error messages. The name-less field correctly turns red, but the error messages don't display.
I believe I have deduced why this isn't working, but I can't figure out how to fix it. I looked at the generated HTML for the ValidationMessage span, and I see this attribute:
data-valmsg-for="MyViewModel.CardNumber"
That would be correct if my name-less field had the name attribute set like normal. But since I can't set the name attribute, how do I get the ValidationMessage to still work?
Scrub the name attrributes on submit would be something like:
$("form").submit(function () {
$(this.find(":input").removeAttr("name");
});
It's possible that this may be too late in the chain of events though, so you may have to preventDefault and repost the form, something like this:
$("form").submit(function (e) {
if($(this.find(":input[name]").length > 0) {
e.preventDefault();
$(this.find(":input").removeAttr("name");
$(this).trigger("submit");
}
});
Or indeed do as I did and code a callBack into unobtrusive validation to check if validation has passed and at that point remove the name attributes. Here are my notes on adding that callBack:
//Added the following to the onErrors function:
if ($.isFunction(callBackOnError)) {
setTimeout(function () {
callBackOnError();
}, 100);
}
//Then in the exposing declarative section of the plugin
onError: function (callBack) {
callBackOnError = callBack;
}
Have a play with it and see what you find. Keen to know your eventual conclusion, so please do update. Hope this has somewhat helped you.
Related
I have a form that allows the user to edit my model. They can save the data, as well as publish it. When the user hits save I want to go ahead and save the form even if its doesnt pass validation so that can come back and finish filling it out later. But if they blur out of a field and its required I still want it to turn red and show the error message. So basically I want normal client side validation without it preventing the form from posting.
Is there a way to do that?
simply override the form submit and that should disable the validation.
$(function () {
$("form").submit(function () {
if (!$(this).valid()) {
//form is not valid
return true;
}
});
});
You dont need the check there obviously and can just return true, thats just to show you how to check if its valid.
This handler only exist for a ListGrid.
But if you look at the docs for DynamicForm.setValidateOnExit(), it says:
If true, form items will be validated when each item's "editorExit"
handler is fired as well as when the entire form is submitted or
validated. Note that this property can also be set at the item
level to enable finer granularity validation in response to user
interaction - if true at either level, validation will occur on
editorExit.
So how can we add a EditorExitHandler to a DynamicForm or a FormItem?
EDIT :
I want to create an error panel below the form to show all errors dynamically. Each FormITem has the possibility to validate on Exit but I do not know how to capture this validation event to check if the error panel should be updated or not.
There is one method form.getErrors() and form.showError(true). By this you can acheive that. But for that also you need to setValidator for each field.
TextItem name = new TextItem("name", "Name");
name.setRequired(true);
name.setRequiredMessage("Please specify name of the Table");
NTRegExpValidator nameValidator = new NTRegExpValidator("(^[a-zA-Z0-9][\\w\\s.()_-]+)$","It should start with alphabets and can have alphanumeric values ( )_-. and space.");
name.setValidators(nameValidator);
name.addKeyUpFieldHandler(new KeyUpHandler){
form.getErrors();
form.showErrror(true);
});
DynamicForm form = new DynamicForm();
form.setField(name);
After some research, I still don't find a convincing answer. I guess it must a dev requirement
I've got hard time resolving the following. My problem is quite simple : I would like to highlight in red the forms fields that triggered validation errors. The error messages are placed correctly in the FacesContext using a context.addMessage(...) line.
I'd like my system to be generic. All form fields having a message attached are automatically highlighted.
I've found on this site a link to this excellent article :
http://www.jroller.com/mert/entry/how_to_find_a_uicomponent
With it, I did implement a PhaseListener for the RENDER_RESPONSE phase, which do the following :
#Override
public void beforePhase(PhaseEvent event) {
// get context
FacesContext context = event.getFacesContext();
// iterate on all the clientIds which have messages
Iterator<String> clientIdsWithMessages = context.getClientIdsWithMessages();
while (clientIdsWithMessages.hasNext()) {
// get the clientId for the field component
String clientIdWithMessage = clientIdsWithMessages.next();
// split on ":"
String[] splitted = clientIdWithMessage.split(":");
UIComponent component = findComponentInRoot(splitted[splitted.length - 1]);
if (component != null) {
Map<String, Object> attributes = component.getAttributes();
if (attributes.containsKey("style")) {
attributes.remove("style");
}
attributes.put("style", "background-color: #FFE1E1;");
}
}
}
This perform perfectly well for almost all my usage.
Now, where it becomes a bit tricky, is that some of my forms have such code :
<ice:dataTable id="revisionDocuments" value="#{agendaBean.agenda.revisionsDocuments}" var="revision">
<ice:column>
<ice:inputText value="#{revision.sequenceAdresse}" id="revisionSequenceAdresse" />
</ice:column>
....
The generated form has several lines (one for each object of the revisionsDocuments list), and each element has a unique identifier (clientId) which looks like :
contentForm:revisionDocuments:0:revisionSequenceAdresse
With 0 changed for 1, 2, ... for each iteration.
Consequently, the code provided to search the UIComponent from ViewRoot does not work properly. All forms fields have the same "id". What surprise me more is : they have the same "clientId" in FacesContext too :
contentForm:revisionDocuments:revisionSequenceAdresse
I cannot distinguish, while going through the tree, if I do see the right form field or any of the others.
Does anyone have a hint to solve this ? Or another suggestion to implement the highlight of my fields ? I have to admit, I dont really like my code, I consider dirty to manipulate the viewRoot like I'm doing, but I could not figure out a better solution to have a generic highlight of my fields.
I'm running IceFaces 2.0.2 with JSF-Impl 2.1.1-b04 on JBOss AS 7.0.2.Final.
Thank you in advance for the answers.
Best regards,
Patrick
You should apply this in the client side instead. You've got a collection of client IDs with messages. One of the ways is to pass this information to JavaScript and let it do the job. You can find an example of such a PhaseListener in this article: Set focus and highlight in JSF.
Since JSF 2.0 there is however another way without the need for a PhaseListener. There's a new implicit EL variable, #{component} which refers to the UIComponent instance of the current component. In case of UIInput components, there's an isValid() method. This allows you to do something like:
<h:inputText styleClass="#{component.valid ? '' : 'error'}" />
with this in a CSS file:
.error {
background: #ffe1e1;
}
(yes, you can also do this in a style attribute, but mingling style with markup is a poor practice)
To abstract this away (so that you don't need to repeat it in every input), you can just create a composite component for this, something like <my:input>.
For completeness, here is the solution I finally found to highlight the fields that do have error messages with IceFaces 2.0.2 :
The basic idea is strictly the same than proposed by BalusC on http://balusc.blogspot.com/2007/12/set-focus-in-jsf.html
The piece of code I had to change with IceFaces is the small Javascript call :
<script>
setHighlight('${highlight}');
</script>
I could not find any IceFaces component which is re-rendered at each JS call. I found that placing the script into a panelGroup works most of the time. However, there was a case that did not work :
submitting the form with errors do trigger the JS.
then, re-submitting the form with errors on the same field than previous validation do NOT trigger the JS.
then, re-submitting the form with any error field having no more errors do trigger JS.
then, re-submitting the form with any non-errored field having an error do trigger JS.
For some reason, IceFaces do not render the panelGroup that contains the JS when the set of fields having errors is the same between two calls.
I tried to use the Javascript API with code like Ice.onAsynchronousReceive(), using Prototype library to attach an event to the AJAX completion of the commandButton, but had not much success with it. Some of my tests could run (with errors but did the job) and I could observe similar behavior.
Here is the trick I finally used (ugly but working) :
<ice:panelGroup>
<script type="text/javascript">
var useless = '#{testBean.time}';
setHighlight('${highlight}');
</script>
</ice:panelGroup>
The getTime() function simply return the current timestamp. The value is then always different and trigger the JS execution at any AJAX request.
Sadly, IceFaces do not have the RichFaces useful "oncomplete" attribute, which I do regret highly for this case.
Ugly solution, but funny and working.
I have added a text box to a simple form in ASP.NET MVC and I want a client-side 'required' validation for this.
I know I can do this using a strongly typed model view but I would like to do it manually in this case. Is there a simple way to perform this?
I tried setting the Model/property name of the Html.ValidationMessage helper to the input name but this didnt work:
#Html.TextBox("emailStr" )
#Html.ValidationMessage("emailStr","* Required")
Assuming you use default jQuery validation plugin, you can use Rules.Add method on client side for this
$("#emailStr").rules("add", {
required: true,
messages: {
required: "* Required",
}
});
Also, do not forget to include jquery.validate.min.js
Not sure why you would want to do it manually - but I don't think you can use #Html.ValidationMessage unless you use a TextBoxFor. You can't use the TextBoxFor unless you have a model to work with inside the view.
You could write some javascript/jquery to find the textbox and make sure it's not empty, and if it is, unhide an element with the validation message in it.
I have something like this:
I am using Ajax.BeginForm and its updatetargetid is a div which basically informs user whether it was successfully submitted or not and the problem, if any.
My controller function that is handling the form submission checks if there were any errors like duplicate entries and such and does re-checking of client-side rules and returns Content(....) accordingly.
This is what I'm using to clear form afterwards, but as you can see that the form would still get cleared even when my controller function has detected some problem that client-side didn't. I set AjaxOptions OnComplete = "onComplete".
function onComplete() {
if ($("#myForm").validate().form()) {
$("#myForm").clearForm();
}
}
Use function onComplete(ajaxContext){ } instead of function onComplete() {}
From the server end, if there are model validation errors, it usually means the validation summary (if supported) contains some error messages. Using ajaxContext, you can read the the response that is returned as part of ajax call and check the values of validation summary element.
Other option is to design a strategy between your controller and view - e.g. specify an error indicator as part of your response header and use this to decide whether to clear your form or not in OnComplete handler.
so then whats the problem? You simply dont call the onComplete function when there is a server side error. But instead display an error message to let the user know that nothing will happen as there was a server side error. And this way the form will not get cleared.
If everything does work on the server side, then only then will you call the onComplete function.
PK