I've also done this exercise twice in the past and both times I used
other JS libraries including prototype. My first solution was
specifically for WebWork and I don't recall any changes I had to make
when moving it over to Struts2.
Perhaps it makes sense to ensure that this will be completely pluggable
since many folks are using other JS libraries. My solution only requires
a form post that is the same or a partial version of the post that would
normally be submitted. This allows me to use pretty much any library
that can handle form submission.
I've included my latest interceptor for you guys to look over. Let me
know what you think. I was planning on making a Struts2 plugin that had
this and the necessary JavaScript files and template to work with
Prototype once I had finished it off. But if you are heading in that
direction, we should collaborate on it.
-bp
Musachy Barroso wrote:
This would be for 2.1, and it would be in Bind.js. It is actually only
one
function, which will be calling the functions in
validation.js(addError/clearErrors...). I'm planning to do some
cleanup after that as we
have some javascript/css files hanging around, which are not used.
musachy
On 4/23/07, Ian Roughley <[EMAIL PROTECTED]> wrote:
Is the Ajax code all in a module now (2.1.x)? Would this change be
checked into the 2.0.x branch or just the trunk under the Ajax module,
and then some cleanup/removal of existing code in the trunk?
/Ian
Musachy Barroso wrote:
> I have this working, but I want to give it a little more time to
> anyone to
> object before committing it :), just to review, these are the
different
> validation options:
>
> 1. regular form, regular submit button (normal validation)
> 2. css_html form, or xhtml form (validate="true"), regular submit
button
> (client validation)
> 3. css_html form, or xhtml form (validate="true"), ajax submit button
> (client validation)
> 4. regular form, css_html form, or xhtml form, where action has the
> "ajaxValidation" interceptor, ajax submit button (validate="true")
(ajax
> validation = dojo+interceptor, no DWR)
>
> regards
> musachy
>
> On 4/21/07, Musachy Barroso <[EMAIL PROTECTED]> wrote:
>>
>> I'd like to propose a change on the way we do ajax validation.
>> Instead of
>> using DWR which requires an external dependency and configuring a
>> servlet,
>> I'd like to have an interceptor in the dojo plugin that extends the
>> validator interceptor, which outputs JSON with the messages when
>> there are
>> validation errors.
>>
>> To use ajax validation all a user would have to do is add the
>> interceptor
>> to his/her class and set "validate" to "true" in either the form, or
the
>> submit/anchor that is submitting the form.
>>
>> regards
>> musachy
>> --
>> "Hey you! Would you help me to carry the stone?" Pink Floyd
>
>
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
package com.texturemedia.catapult.struts.ajax;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Validateable;
import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.validator.ValidationInterceptor;
/**
* <p>
* This class is a Struts2 interceptor that is used to handle AJAX
* validation requests from the client. This requires that there is
* a HTTP parameter called <em>ajax-validate</em> whose value must be
* <em>true</em>. Besides that the form values must be serialized as
* they would be if the form is submitted. This can accept partial
* form submissions and will return a JSON object that contains only
* the errors for the form values sent in.
* </p>
*
* <p>
* If there are no errors, the response body will be empty and the
* response code will be 200. If there are errors than the response
* body will contains the error JSON object and the response code
* will be 400.
* </p>
*
* <p>
* The format of the JSON is like this and the entire contents of
* the HTTP response body will look like this:
* </p>
* <pre>
* var errors = {'http.parameter.from.form': ['list', 'of', 'errors'], 'other.form.param': ['more errors']};
* </pre>
*
* @author Brian Pontarelli
*/
public class JSONAjaxValidationInterceptor extends ValidationInterceptor {
private static final Logger logger = Logger.getLogger(JSONAjaxValidationInterceptor.class.getName());
protected String doIntercept(ActionInvocation invocation) throws Exception {
logger.finest("In the interceptor");
String param = ServletActionContext.getRequest().getParameter("ajax-validate");
if (param != null && param.equals("true")) {
logger.finest("Validating and calling before");
super.doBeforeInvocation(invocation);
Object action = invocation.getAction();
if (logger.isLoggable(Level.FINEST)) {
logger.finest("Handling action class [" + action.getClass() + "]");
}
if (action instanceof Validateable) {
logger.finest("Action is validateable");
Validateable validateable = (Validateable) action;
validateable.validate();
}
if (action instanceof ValidationAware && ((ValidationAware) action).hasFieldErrors()) {
logger.finest("Action is aware and has errors - outputting JSON");
outputErrorJSON();
}
return Action.NONE;
}
return super.doIntercept(invocation);
}
// Ensure there are field errors and that at least one of the field errors is from
// a parameter passed in. Only on this case, set 400 HTTP code and go to the ajax_input
// result.
private void outputErrorJSON() {
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
Map<String, Collection<String>> errorsMap = ((ValidationAware) ServletActionContext.getContext().getActionInvocation().getAction()).getFieldErrors();
Set<String> keys = errorsMap.keySet();
StringBuilder build = new StringBuilder();
boolean firstKey = true;
for (String key : keys) {
// If the field wasn't sent in the request, don't add it to the JSON.
if (request.getParameter(key) == null) {
continue;
}
if (!firstKey) {
build.append(",");
} else {
firstKey = false;
}
build.append("'").append(key.replace("'", "\\'")).append("': [");
Collection<String> errors = errorsMap.get(key);
boolean firstError = true;
for (String error : errors) {
if (!firstError) {
build.append(",");
} else {
firstError = false;
}
build.append("'").append(error.replace("'", "\\'")).append("'");
}
build.append("]");
}
if (build.length() > 0) {
response.setStatus(400);
if (logger.isLoggable(Level.FINEST)) {
logger.finest("JSON is " + build.toString());
}
try {
ServletOutputStream os = response.getOutputStream();
os.print("var errors = {" + build.toString() + "};");
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
} else {
logger.finest("No errors found - JSON would be empty");
response.setStatus(200);
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]