struts2 onblur server side ajax validation - ajax

How would I implement AJAX validation in struts2 which lets you know if a username is available onblur? This is what I've managed so far but the docs aren't clear:
JSP:
<%# page
language="java"
contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib
prefix="s"
uri="/struts-tags"%>
<%# taglib
prefix="sj"
uri="/struts-jquery-tags"%>
<!DOCTYPE html>
<html>
<head>
<sj:head jqueryui="true" />
<!-- Don't forget these 2 files!! -->
<script
src="${pageContext.request.contextPath}/struts/utils.js"
type="text/javascript"></script>
<script
src="${pageContext.request.contextPath}/struts/css_xhtml/validation.js"
type="text/javascript"></script>
<script
type="text/javascript"
src="js/register.js"></script>
<title>Register</title>
</head>
<s:url
action="loginLink"
var="loginHREF" />
<s:url
action="forgotPasswordLink"
var="forgotPasswordHREF" />
<s:url
action="Register"
var="registerHREF" />
<body>
<s:form
theme="css_xhtml"
action="Register"
onsubmit="return myValidate()">
<s:textfield
name="user.username"
label="Username"
id="uname"
required="true"
pattern="[a-zA-Z0-9_-]{5,12}"
title="5-12 Alphanumeric characters required" />
<s:textfield
name="user.email"
label="Email"
required="true" />
<s:password
id="pass1"
name="user.password"
label="Password"
required="true"
pattern="{5,12}"
title="5-12 characters" />
<s:password
id="pass2"
label="Confirm Password"
required="true"
pattern="{5,12}" />
<s:textfield
name="user.firstName"
label="First Name"
required="true" />
<s:textfield
name="user.lastName"
label="Last Name" />
<sj:datepicker
yearRange='-90:-3'
changeYear="true"
name="user.birthDate"
readonly="true"
label="Date of Birth" />
<s:submit value="Register" />
</s:form>
<s:a href="%{loginHREF}">Login</s:a>
<s:a href="%{forgotPasswordHREF}">Forgot Password</s:a>
<script>
$("#uname").blur(function() {
var fieldData = $("#uname").serialize();
fieldData = fieldData.slice(5);
//do the POST thingies
$.ajax({
type : "POST",
url : "ValidateUsername",
cache : false,
data : fieldData,
dataType : "json",
complete : function(request) {
alert("In complete");
var form = $('form');
//clear previous validation errors, if any
//StrutsUtils.clearValidationErrors(form);
//get errors from response
var text = request.responseText;
alert(text);
var errorsObject = StrutsUtils.getValidationErrors(text);
//show errors, if any
if (errorsObject.fieldErrors) {
StrutsUtils.showValidationErrors(form, errorsObject);
}
}
});
return false;
});
</script>
</body>
</html>
Action:
#Action("ValidateUsername")
#Results(value = { #Result(name = "success", type = "json"), #Result(name = "input", type = "json") })
#ParentPackage("default")
#InterceptorRef("jsonValidationWorkflowStack")
public class ValidateUsername extends ActionSupport {
private String username;
#Override
public String execute() {
return SUCCESS;
}
#Override
public void validate() {
UserService service = new UserService();
User isTaken = service.findByUsername(username);
service.close();
if (isTaken != null)
addFieldError("user.username", "That username is taken");
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
The docs make it seem like struts2 will handle it for you if you simply add the json interceptor and set validate="true" in the sx:submit tag.
In register.js I check to see that password and confirmation password match.
Basically I would like it to validate even before submit is pressed. Right now On submit it validates it like any other normal form.
Edit: Also, is there a working method other than using dojo? It seems to block all my client side validation including the required attributes, js, etc.
Edit2:I ditched the dojo plugin, learnt some js and managed to put together what i have now. Now the only thing left is to display an error. Alerting the response text shows up a json string with only a username key value pair in it. Should i add another member to the action and process it to display an error message? because the StrutsUtils js is not working. addFieldError("user.username", "That username is taken"); does not modify the json result.
Basically, how can i add fielderrors to my json response?
Edit: I got my action to add my field errors to the json response by modifying the annotations as follows:
#Action("ValidateUsername")
#Results(value = {
#Result(name = "success", type = "json"),
#Result(name = "input", type = "json", params = { "ignoreHierarchy",
"false", "includeProperties",
"actionErrors.*,actionMessages.*,fieldErrors.*" }) })
#ParentPackage("default")
#InterceptorRef("jsonValidationWorkflowStack")
Now the only problem is in:
//clear previous validation errors, if any
**//StrutsUtils.clearValidationErrors(form);**
//get errors from response
var text = request.responseText;
alert(text);
**var errorsObject = StrutsUtils.getValidationErrors(text);**
//show errors, if any
if (errorsObject.fieldErrors) {
StrutsUtils.showValidationErrors(form, errorsObject);
}
None of the StrutsUtils functions are working. When i uncomment clearValidationErrors it does nothing and breaks the rest of the js code. errorsObject is empty and showValidation does nothing even though on printing my jon response i can see a field error with a message. How do i get StrutsUtils to work?
Also, is there a better way to implement my use case? I haven never learnt jquery/ajax and this is my first struts2 application.

Struts is available server-side. You are trying to call
var errorsObject = StrutsUtils.getValidationErrors(text); in the client-side.
StrutsUtils is a class and is not available on client-side/javascript.
There are various ways through which you can send errors.
Please refer my answer in the below link, on how to handle ajax request & response when using struts2.
How to get Ajax response in Struts2

Related

Accessing servlet generated objects (JSONObjects) via AJAX and JQuery

I am new to using AJAX and JQuery with Java Servlets. I want to produce a search page that produces a list of search results (like a google page listing). My database query works and returns a JSONObject or a JSONArray.
My code is not working for the JQUERY. I have tried a lot of different versions. The basic error is that the new page after the search just shows the data in the form of an array print. It does not recognise the HTML.
I have shown my code below with the db query removed. The different versions I tried were with various forms of JSON syntax, with and without GSON, and nothing has worked.
The system is Linux.
Any comments would be appreciated, or even a link to a comprehensive example.
search.js
$(document).ready(function(){
$('#searchbutton').submit(function)
{
var inputdata = searchText:$("#searchtext").val();
};
$.ajax({
type:"POST",
datatype: "json",
url:"search",
data:inputdata,
success: function(data){
$("#searchResults").append("<b>data.linkresult</b>")
});
});
});
});
});
search.java
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
PrintWriter out = response.getWriter();
// reading the user input
String searchword= request.getParameter("search");
String Tmsg = "";
Map<String, Object> data = new HashMap<String, Object>();
data.put("searchresult", searchword);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(new Gson().toJson(data));
search.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Search for a word</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src="./js/jquery-1.9.1.js"></script>
<script type="text/javascript" src="./js/search.js"></script>
<script type="text/javascript" src="./js/jquery-1.9.1.min.js"></script>
</head>
<body>
<form action="search">
Search<br>
<div>Word -
<input id="searchtext" type="text" name="search" size="40px">
</div>
<div>
<input id="searchbutton" type="submit" value="Submit">
</div>
</form>
<div id="searchresults">
</div>
Result (just this one line is displayed):
{"searchresult":"search example"}
To parse the Json message received from the servlet, you can achieve this by doing something like this. Lets assume that you have received the following message from the servlet
{"key1":"val1","key2":"val2","key3":"val3"}
And you want it to be displayed in a table.
success: function(data){
var output = '<table>';
for ( var key in data) {
if (data.hasOwnProperty(key)) {
output += "<tr>";
output += "<td>" + key + "</td>";
output += "<td>" + data[key] + "</td>";
output += "</tr>";
}
}
output += "</table>";
$("#searchResults").empty();
$("#searchResults").append(output);
});

JQuery Load using MVC3 #Url.Action does not pass parameters properly

I noticed that doing #Url.Action("myAction", new { param1 = 123, param2 = 456}) provides me with an invalid URL Home/myAction?param1=123&param2=456.
I am attempting to do
$("#myAjaxDiv").load(url);
But only param1 is getting populated in the action method.
When I remove the & and make it just & then it works, but doing a string replace is super hacky.
url = url.replace("&", "&");
Am I missing something here?
EDIT: Per request I'm including some of my sample app. (you can create a new MVC app and just add these quickly and see for yourself)
Controller:
public ActionResult AjaxTest(int? year, int? month)
{
ViewBag.Message = string.Format("Year: {0}, Month: {1}", year.HasValue ? year.ToString() : "no year", month.HasValue ? month.ToString() : "no month");
return PartialView("AjaxTest");
}
AjaxTest View:
#ViewBag.Message
Index View:
<script>
$(function () {
var url="";
$("#noParams").click(function () {
url = "Home/AjaxTest";
$("#ajaxy").load(url)
$("#url").text(url);
});
$("#yearParam").click(function () {
url = "Home/AjaxTest?year=2012";
$("#ajaxy").load(url)
$("#url").text(url);
});
$("#yearAndMonthParam").click(function () {
url = "Home/AjaxTest?year=2012&month=10";
$("#ajaxy").load(url)
$("#url").text(url);
});
$("#generated").click(function () {
url = "#(Url.Action("AjaxTest", new { year=2012, month=10}))";
$("#ajaxy").load(url);
$("#url").text(url);
});
});
</script>
<a id="noParams" href="#">No Params</a> <br />
<a id="yearParam" href="#">Year Param</a> <br />
<a id="yearAndMonthParam" href="#">Year and Month Param</a> <br />
<a id="generated" href="#">Generated</a> <br />
<div id="ajaxy">
</div>
<div>
URL: <span id="url"></span>
</div>
By default every content (which is not IHtmlString) emitted using a # block is automatically HTML encoded by Razor (see this Razor intro article Html Encoding section)
The Url.Action returns just a plain string so thats why the & gets encoded.
Use the Html.Raw if you don't want the encodeing:
url = "#(Html.Raw(Url.Action("AjaxTest", new { year=2012, month=10})))";
You can build the url in this way also.
var url = "#Url.Action("AjaxTest","YourControllerName")?year=2012&month=10";
$("#ajaxy").load(url);

request.getParameter() returns null

Got a homework assignment that is giving me problems.... Its modifying a JSF project with two pages and a bean to fit MVC2 by adding two more pages and a controller servlet and another bean for the two additional pages. the new main page forwards to either the second new page or the old first page. My issue is response.getParameter() always results in null.
<%#page session="false" import="java.util.Iterator"%>
<%#taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%#taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<jsp:useBean id="status" scope="request" class="JSFRegistration.Status" />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>JSP Page</title>
</head>
<body>
<% if (status!=null && !status.isSuccessful()){%>
<font color="red">Processing errors:
<ul><%Iterator errors=status.getExceptions();
while (errors.hasNext()){
Exception e = (Exception) errors.next();%>
<li><%= e.getMessage()%><%}%></ul></font><%}%>
<form action="LoginServlet" method="POST">
<% String username = request.getParameter("username");
if (username==null) username="";%>
<input type="text" name="usernameTF" value="<%=username%>" />
<% String password = request.getParameter("password");
if (password==null) password="";%>
<input type="password" name="passwordTF" value="<%=password%>" />
<input type="submit" value="Login" />
</form>
</body>
</html>
this is basically a direct copy from our book but the fields I need for the new main page. Same for the controller servlet, a direct copy except only contains the fields I need.
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher view = null;
Status status = new Status();
request.setAttribute("status", status);
String username = request.getParameter("username");
String password = request.getParameter("password");
if (username==null || username.length()==0)
status.addException(new Exception("Please enter username"));
if (password==null)
status.addException(new Exception("Please enter password"));
if (!status.isSuccessful()){
view = request.getRequestDispatcher("Login.jsp");
//view.forward(request, response);
}
else
try{
request.setAttribute("username", username);
request.setAttribute("password", password);
view = request.getRequestDispatcher("Registration.jsp");
} catch (Exception e) {
status.addException(new Exception("Error"));
view = request.getRequestDispatcher("Login.jsp");
}
view.forward(request, response);
}
and the Status class, again a direct copy from the book.
public class Status {
private ArrayList exceptions;
public Status(){
exceptions = new ArrayList();
}
public void addException(Exception exception) {
exceptions.add(exception);
}
public boolean isSuccessful(){
return (exceptions.isEmpty());
}
public Iterator getExceptions(){
return exceptions.iterator();
}
regardless of what is typed into the two boxes, stepping through a debug shows the values not getting passed to the parameters. I get the created exceptions printed above the screen for both fields if both have text, if only one has text and when both are empty.
Your request parameter names do not match the input field names. You've assigned the input fields a name of usernameTF and passwordTF. They are then available by exactly those names as request parameter, but you're attempting to get them using the names username and password. So you need either to fix the input field names, or the request parameter names so that they match each other.
By the way, why falling back from a modern MVC framework like JSF to awkward 90's style JSP with mingled business code? Is that really what the homework assignment is asking you? Also the HTML <font> element is deprecated since 1998. Where did you learn about it? Is the quality of the course really good?

Rectify the input at client side using RemoteValidation

Is there any possibility of rectifying the input at client side using Remote Validation?
For example, the user will enter the date as 010101 which means 01-Jan-2001, can Remote Validation reflect/pass the rectified value (010101 into 01-Jan-2001) at/to client side?
I have a scenario where i have JS to format the input into correct date format. Later on i had to use RemoteValidation. My remote validation receives date in ddmmyy format (RemoteValidation gets called before JS), it first converts it into correct date and then perform validation, and then my JS does not get called at all and so 010101 is not get converted into 01-Jan-2001.
Edit
There are two things i would like to get help for
1- Is there anyway a remote validation function can modify the model/data passed to it for validation and then pass it back to the view so that user can see the modified version of the model/data
[Deleted:2- I have JavaScript for a date field which formats the date when focus is lost. It is working fine. When i used Remote validation along with JS, the script does not get called at all.]
Edit
Model
public class master
{
public string sometext { get; set; }
public child mychild { get; set; }
}
public class child
{
public child()
{
thedate = DateTime.MaxValue;
}
[Remote("ValidateDate", "Test", ErrorMessage = "Invalid Date")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:mm/dd/yyyy}", NullDisplayText = "Enter Date")]
public DateTime? thedate { get; set; }
}
View
#model Models.master
#using Web.Framework
#{
Layout = null;
}
<html>
<head>
<title>Test - My ASP.NET MVC Application</title>
<script src="#Url.Scripts("jquery-1.7.1.min.js")" type="text/javascript"></script>
<script src="#Url.Scripts("jquery-ui-1.8.11.js")" type="text/javascript"></script>
<script src="#Url.Scripts("modernizr-2.0.6-development-only.js")" type="text/javascript"></script>
<script src="#Url.Scripts("AjaxLogin.js")" type="text/javascript"></script>
<script src="#Url.Scripts("jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Scripts("jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="#Url.Scripts("jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<script src="#Url.Scripts("MicrosoftAjax.js")" type="text/javascript"></script>
<script src="#Url.Scripts("MicrosoftMvcAjax.js")" type="text/javascript"></script>
<script src="#Url.Scripts("myScripts.js")" type="text/javascript"></script>
</head>
<body>
#using (Html.BeginForm("testSubmit", "Test"))
{
#Html.LabelFor(m => m.sometext)
<br />
#Html.TextBoxFor(m => m.sometext)
<br />
#Html.LabelFor(m => m.mychild.thedate)
<br />
#Html.TextBoxFor(m => m.mychild.thedate, new { onblur = "doDate(this, '');" })
#Html.ValidationMessageFor(m => m.mychild.thedate)
<br />
<input type="submit" value = "Submit me" />
}
</body></html>
Controller
public ActionResult testSubmit(master model)
{
#ViewBag.Message = "OK";
return View("response");
}
public JsonResult ValidateDate(DateTime? thedate)
{
return Json(HttpContext.Request.QueryString["mychild.thedate"].ToString(), JsonRequestBehavior.AllowGet);
}
My remote validator always receives null in thedate, but i can access the value from query string but the value is unformatted i.e. Remote validation gets called before JS which means i have to format the date first in remote function and then validate, once validated then this input is formatted again by JS and both have to be synced.
Now, how can i get the formatted value in Remote function OR pass the formatted value from Remote function to the View ?
Since i didn't get any answer so the answer, so far, is "No".

MVC3 Remote Validation not Fired?

I created a very simple test project to illustrate the problem.
My model class
public class HomeModel
{
[Required(ErrorMessage="Missing property1.")]
public string Property1
{
get;
set;
}
[Remote("ValidateProperty2", "Home", HttpMethod="Get", AdditionalFields = "Property3", ErrorMessage="Property2 wrong!")]
public string Property2
{
get;
set;
}
public string Property3
{
get;
set;
}
}
My controller
public class HomeController : Controller
{
public ActionResult Index()
{
HomeModel model = new HomeModel();
return View(model);
}
[HttpPost]
public ActionResult Index(HomeModel model)
{
return View(model);
}
public ActionResult ValidateProperty2(string property2, string property3)
{
return Json(true, JsonRequestBehavior.AllowGet);
}
}
And my view
#model RemoteValidationTest.Models.HomeModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
</head>
<body>
#using (Ajax.BeginForm(new AjaxOptions
{
HttpMethod = "POST"
}))
{
#Html.TextBoxFor(x => x.Property1) #Html.ValidationMessageFor(x => x.Property1)<br />
#Html.TextBoxFor(x => x.Property2) #Html.ValidationMessageFor(x => x.Property2)<br />
#Html.TextBoxFor(x => x.Property3) #Html.ValidationMessageFor(x => x.Property3)<br />
<input type="submit" />
}
</body>
</html>
And my web.config
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
Nothing really fancy here. I havea model class with 3 properties. The first one is set be required and second one is remote validation, I believed I have create the action method properly. I set break piont to ValidateProperty2 function, it never gets called.
I also used FireBug, the same thing client side does not even try to call the server side.
What is wrong with the code here?
Edit 1:
I think I get something, the remote validation will only fires when the control (e.g text box) has value in side. The empty control will never trigger the validation. In my case I actually try to implmenet a more complicated logic, I need the validation to fire even when the control text is empty (to check other property's value). Is it even possible?
I have a working version here for mvc3:
http://completedevelopment.blogspot.com/2011/08/remote-ajax-validation-in-mvc3.html
d/l it and you can compare files.
The problem is that the validation don't fire automatically when you press the send button for the first time. Here is how you initiate the validation upon page load so that it fires every time it is needed on submit:
"Required" validation attribute not working in asp.net mvc 3 while others work

Resources