Struts 2 XML form validation breaks when new element that does not need validation is added - validation

I am facing an issue that is really hard to debug. I have a JSP page that has some form elements on it that submit to a Struts2 action. I also have a XML form validation file to perform some validation on the submitted fields. The file has the naming convention 'actionName-validation.xml'
This works fine, but when I add a drop down box, outside of the form, the validation now fails. Instead it redirects to a blank page and my breakpoint in my action class is not hit.
Is there a way to turn on some kind of debugging or logging for the validation? Why would adding a tag outside of a form cause this to happen?
Here is the code on the JSP page:
<s:select id="dataSource" name="selectedDataSource" theme="simple" listValue="top"
headerKey="" headerValue="Choose Data" list="dataSources" size="1" />
<div id="forms">
<s:form method="post" action="MyAction" theme="simple">
<p>
<label class="input" for="name"
<span style="color:red;">*</span>
<span>Name</span><br>
<s:textfield theme="simple" name="name" maxlength="11" size="11" />
<br>
<s:fielderror theme="plain"><s:param value="'name'" /</s:fielderror></label>
</p>
<s:submit value="Create New" theme="simple" cssStyle="display: block; clear: left;"/>
</s:form>
</div>
If I remove the <s:select> tag, it works.
Any help would be greatly appreciated it.
EDIT2: I found the problem. I needed a get method for the list that is used to populate the select drop down inside the action that the form submits to.
I had one for the action that initially is called for the page, but when the validation fails and it re-loads that page from the form action class, it tries to re-populate the select drop down and needs a getter there. I feel silly for not finding that sooner. Would be nice if there were some type of logging or messaging of these types of issues.
thanks.

The error you are encountering is not a validation error (handled by the Validation Interceptor), but an error occurred when setting the parameters (raised by the Parameters Interceptor) and for which the Conversion Error Interceptor added a fieldError, which you are not seeing because
your INPUT result lands on a blank page and
you are using theme="simple" on the textfield, which forces you to add <s:fielderror fieldName="dataSource" /> to show it (or <s:fielderror /> to show them all).
Read how the INPUT result works, set your page as the INPUT page, print the errors, then you will discover the problem, that is most likely related to the fact that you've not specified a listKey attribute in your select, that is sending the description instead of the code of the datasource to selectedDataSource, which is probably an Integer.

I found the problem. I needed a get method for the list that is used to populate the select drop down inside the action that the form submits to.
I had one for the action that initially is called for the page, but when the validation fails and it re-loads that page from the form action class, it tries to re-populate the select drop down and needs a getter there. I feel silly for not finding that sooner. Would be nice if there were some type of logging or messaging of these types of issues.

Related

parsley.js 'fails' when trying to validate checkbox

We are re-designing a site and part of that re-design involves making the site accessible to screen readers and the like. I'm using latest version (2.8.0). Here's what's happening --- validation for all text, select and textarea fields in our forms work perfectly. In order to be accessible, checkbox and radio inputs are wrapped in tags. The html for a set of checkboxes looks like this:
<div class="form-group">
<p id="applicant_type_desc" style="margin-bottom: 6px;"><strong>I am: <span class="text-danger" aria-hidden="true">*</span><span class="sr-only">Required</span></strong> <em class="small">(check all that apply)</em></p>
<div class="checkbox">
<label id="applicant_type_patient_desc">
<input type="hidden" name="applicant_type_patient" id="" value="N">
<input type="checkbox" name="applicant_type_patient" id="applicant_type_patient" value="Y" {checked_applicant_type_patient} aria-labelledby="applicant_type_desc applicant_type_patient_desc" data-parsley-multiple="type" data-parsley-error-message="Please specify whether you are a patient, relative, employee or other.">
A patient
</label>
</div>
followed by more checkbox divs without error messages and ended with an end div for the for form-group wrapper.
If I load the form and click 'submit', all the text fields are validated properly. If I add 'required' to the checkbox above, when 'submit' is clicked nothing happens and the form is submitted with no validation at all.
The same thing happens when I try to validate a radio button set as required.
There is some custom jQuery and parsley code which creates a div to hold all the error messages and transforms the error messages into links to the field id so that a screen reader can follow them and focus on the field in error. But imho, this should have no effect on why the form validation doesn't kick in.
I'm absolutely baffled.
FYI - I tried this using an earlier version (2.0.3) of parsley and the validation actually worked, although all my custom error processing was ignored.
Any insight would be greatly appreciated.
As it turns out, parsley handles the errorswrapper element differently for text, textarea and selects then it does for checkboxes and radio buttons.
The starting wrapper element for text, textarea and select contains the parsley-data-id attribute whereas checkbox and radio button elements contain the parsley-data-multiple attribute whether that was generated by parsley or entered manually in the html.
My code was looking for parsley-data-id and, of course the jquery selector failed and generated an error. A colleague was able to spot this for me while we were looking at the page in chrome inspector. Once i saw the error, making a simple adjustment to the form:error event function allowed everything to work.

Laravel testing form press method doesn't works

I'm trying to cover my project with test and faced with problem.
The "press" method of TestCase fails with 'InvalidArgumentException: Unreachable field ""'
However the "see" method sees the needed button
Besides another form on another page tests fine
Hours of debug show me that the issue might be in the fact that the problem form has multiple (with this brackets []) inputs
Test code that fails
$this->type($params['from'], 'from[]');
$this->type($params['event'], 'event[]');
$this->type($params['class'], 'class[]');
$this->type($params['method'], 'method[]');
$this->press('save_handlers');
With form and button everythings is okey
Button:
<button type="submit" class="btn btn-primary btn-block" name="save_handlers">Save</button>
And of course button is in the form tag
Indeed, the problem is linked with the fact that there are attributes with brackets[].
I just had the same problem. I'm using a form with multiple checkboxes, and all of them have the same name (but different id) : codes[]. I'm doing this in order to retrieve them later (in a controller) simply as an array of values.
<input id="perm-0" type="checkbox" name="codes[]" value="perm-0" />
<input id="perm-1" type="checkbox" name="codes[]" value="perm-1" />
<input id="perm-2" type="checkbox" name="codes[]" value="perm-2" />
My friend var_dump() told me that the Symfony component which parses the form inputs doesn't like it when I'm using codes[] with nothing inside the brackets. It is seen as two fields : "codes" and "" instead of codes[]. That's causing the Unreachable field "" error.
A simple solution I found is to simply add an explicit index for the codes[] array :
<input id="perm-0" type="checkbox" name="codes[0]" value="perm-0" />
<input id="perm-1" type="checkbox" name="codes[1]" value="perm-1" />
<input id="perm-2" type="checkbox" name="codes[2]" value="perm-2" />
This way each checkbox is distinct from others, and the method press() does not cause the error any more.
It seems that this doesn't affect the processing of the resulting array in my controller.
This seems rather confusing seeing as the docs state this:
"Press" a button with the given text or name.
While the docblock above the actual press method states the following:
Submit a form using the button with the given text value.
So instead of using the value of the name attribute (save_handler) use the actual text (Save).
$this->press('Save');

Requests with AJAX in a portlet (Liferay)

I have an issue with my portlet and I don't know exactly how to solve it.
My portlet adds or retrieves info from liferay's DB by inserting a name in 2 text fields.
After pressing the submit button, I see the response from the server, a JSON response like this:
{"id":301,"name":"Pepo"}
If a user correctly inserted or if the search throws a good result. I have to go back in the browser to see the portal again.
How can I use AJAX to pass the following URL dynamically from the portlet to the server without refreshing the page afterwards?
http://localhost:8080/c/portal/json_service?serviceClassName=com.liferay.test.service.TrabajadorServiceUtil&serviceMethodName=findByName&servletContextName=TrabajadorPlugin-portlet&serviceParameters=[param1]&param1=NameInsertedByUser
Now I'm using the <form> tag like this:
<%
//Shows "New Employee" in the text field when portlet is rendered, or gets the user input and pass it as a param to the URL
PortletPreferences prefs = renderRequest.getPreferences();
String employee = (String)prefs.getValue("name", "New Employee");
%>
<form id="postForm" method="post" action="http://localhost:8080/c/portal/json_service">
<input name="serviceClassName" type="hidden" value="com.liferay.test.service.TrabajadorServiceUtil" />
<input name="serviceMethodName" type="hidden" value="create" />
<input name="servletContextName" type="hidden" value="TrabajadorPlugin-portlet" />
<input name="serviceParameters" type="hidden" value="[param]" />
<input name="param" type="text" value="<%=employee%>" />
<input type="submit" value="Submit"/>
</form>
I understand how AJAX works, but I need some help to create my function in order to achieve the URL to be correctly sent to the server for both GET and POST requests. This is my first try with AJAX.
Thank you very much, hope somebody understands my problem and could help me.
First of all, I see no point at all to use JSON services here. Just write ordinary portlet with MVC Controller, and in controller write action handling for corresponding actions (storing data, searching etc).
In controller you can directly call static methods like create or findByName from java class com.liferay.test.service.TrabajadorServiceUtil (or TrabajadorLocalServiceUtil) - that's how people usually do it.
If for some reason you really must use JSON, you should of course do these actions with AJAX calls - and render results using JavaScript.
Updating after question update:
The easiest and most correct way to send AJAX requests in Liferay would be to use AlloyUI JS framework that's a part of Liferay. You can read more on how to send AJAX requests with it here: http://www.liferay.com/web/nathan.cavanaugh/blog/-/blogs/4733559
In order to accomplish your goal I'd suggest implementing processAction(ActionRequest actRequest, ActionResponse actResponse) method in your controller/portlet.
In order to actually send data to it you'll have to have actionURL, which you can create using for example portlet:actionURL tag:
<portlet:actionURL /> or with Java code PortletURL actionUrl = portletResponse.createActionURL();
Then just submit your form using POST to this URL, and in actionRequest you'll have your parameters.

How to make a field required without data annotation

I am using the MvcContrib Grid to display a table on the page. I am using a custom column to produce a checkbox on the table so that the user can select multiple rows and submit the form.
I don't want the form to submit unless at least one checkbox has been selected. I could easily write this Javascript myself to enforce the validation, but I wanted to know how I could fit it in with the unobtrusive library supplied with MVC3.
I imagine I just need to set my inputs with the proper classes and attributes and then the scripts (validate and validate.unobtrusive) on the page should pick them up and mark them as needing validation, but I haven't been able to get the right combination thus far.
Here is the input that I am currently generating:
<input type="checkbox"
name="foo"
value="#item.foo"
class="input-validation-error"
data-val-required="Please select an option."
data-val="true" />
Try setting the data-val attributes on the item, then you have to tell jQuery you have new content to re-parse the form via something like:
$.validator.unobtrusive.parse($('#yourForm'));
where form is of course a reference to your form element.
There is also this great posting and jQuery has a few internal adapters you can call:
from http://www.devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-2
jQuery.validator.unobtrusive.adapters.addSingleVal("notequalto", "otherproperty", "mynotequaltofunction")
From my experience, a commonly overlooked mistake with displaying client-side validation is putting a Html.ValidationMessageFor(lambda) on the page.
Without that, no client-side validation will fire to prevent the form submit and/or display the message that is generated using annotations on the client-side.
Hope this helps.
<div class="editor-field">
<input class="text-box single-line"
data-val="true" data-val-number="The field Qty Available must be a number."
data-val-range="The field Qty Available must be between 0 and 120."
data-val-range-max="120" data-val-range-min="0"
data-val-required="The Qty Available field is required."
id="QtyOnHand" name="QtyOnHand" type="text" value="12" />
<span class="field-validation-valid" data-valmsg-for="QtyOnHand"
data-valmsg-replace="true"></span>
</div>
The tie-in between the data model annotations and the data-val-* attributes should be clear after reading the above code, but it's where the client side validation ties in might not be so obvious. Open the \Scripts\jquery.validate.unobtrusive.js file and search for "data-val". Right away you'll see that the JavaScript uses the data-val-, input- and field-* CSS classes to display/hide validation messages on the client.
The above is taken from this great article, which you might want to read in full.

why validation fails if using custom component inside a datatable?

I have a very strange problem.
The required validation inside a datatable works great if I am working directly with the original components for instance:
<ice:inputText id="inputTextt" field="#{bean[fieldValue]}" required="true"/>
<ice:message for="inputTextt"></ice:message>
will raise the required message when I press the button to POST the form.
Well, I have a custom component gra:inputTextValidated where I put the same stuff but a little bit more complex:
<ice:inputText
id="#{id}"
value="#{bean[field]}"
rendered="#{rendered and empty validatorBean}"
styleClass="#{styleClass} #{not required ? 'graNotRequired':''}"
style="width: #{width};height:#{height}"
partialSubmit="#{partialSubmit}"
disabled="#{disabled}"
required="#{required}">
</ice:inputText>
<ice:message
styleClass="graValidationMessage graNotRequired"
for="#{id}" />
so now, from the datatable I am calling my component like:
<gra:inputTextValidated
id="inputText"
bean="#{bean}"
field="#{fieldValue}"
renderLabel="false"
required="true"
disabled="#{disabled}"
width="90%"
height="#{secondTabComponentsHeight}"
>
</gra:inputTextValidated>
Now the validation message no longer occurs. The gra:inputTextValidated component works fine, the value is rendered so it's only a problem about validation.
I've spent about 3 hours on this and I am extremely sure it's something about the ids, somehow the for attribute of the ice:message does not correctly see my input text from the custom component (but it is there, rendered as a spam).
Do you have any suggestion?
Solved.
The above code is working.

Resources