I have a simple page with a firstName field and a lastName field both of which are required. When I only enter one field I get the correct error message but I lose the value I have entered. I do have getters and setters for the fields and the page uses the values correctly if I enter them. Everything seems set up in the same way I had it on my previous project and I did not lose data on those pages. I know this question has been asked before but I can't find anything wrong with my code based on those answers so I am hoping someone can see what I am doing wrong.
My jsp code is:
<s:form action = "sign" validate="true" method="post" id="sign" >
<s:hidden name="dateSigned"></s:hidden>
<div class="row">
<div class = "col-md-7 col-xs-12">
<div class="col-md-3 col-sm-3 col-xs-12"><label for="firstName" class="pull-right"><span class="required">*</span><s:text name="firstName"></s:text>:</label></div>
<div class="col-md-3 col-sm-3 col-xs-12"><s:textfield name = "firstName" id = "firstName" value="" maxlength="50" class="form-control" onchange="dirtyFlag();" tabindex="4"/></div>
<div class="col-md-3 col-sm-3 col-xs-12"><label for="lastName" class="pull-right"><span class="required">*</span><s:text name="lastName"></s:text>:</label></div>
<div class="col-md-3 col-sm-3 col-xs-12"><s:textfield name = "lastName" id = "lastName" value="" maxlength="50" class="form-control" onchange="dirtyFlag();" tabindex="5"/></div>
</div>
</div>
<div class="row">
<s:submit method="save" key="button.save" cssClass="submit" onclick="clearDirtyFlag();" tabindex="1"/>
</div>
My struts action is:
<action name="sign" class="gov.mo.dnr.egims.controller.request.RequestorSignatureAction">
<result name="success" type="tiles">reqSign</result>
<result name="input" type="tiles">reqSign</result>
<result name="error" type="tiles">error</result>
<result name="ownerSignature" type="redirectAction">
<param name="actionName">owner</param>
<param name="namespace">/req</param>
<param name="requestId">${requestId}</param>
</result>
</action>
My tiles code is:
<definition name="reqSign" extends="baseLayout">
<put-attribute name="navbar"
value="/WEB-INF/pages/request/nav_secondary.jsp" />
<put-attribute name="content"
value="/WEB-INF/pages/request/RequestorSignature.jsp" />
</definition>
My struts2 result-types and interceptor code is:
<result-types>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" />
</result-types>
<interceptors>
<interceptor name="validUser" class="gov.mo.dnr.egims.controller.interceptors.ValidUser" />
<interceptor-stack name="validUserStack">
<interceptor-ref name="validUser" />
<interceptor-ref name="defaultStack" />
</interceptor-stack>
<interceptor name="userInRole" class="gov.mo.dnr.egims.controller.interceptors.UserInRole">
<param name="rolesList">Administrator,Geologist,Requestor,Reviewer, User</param>
</interceptor>
<interceptor-stack name="userInRoleStack">
<interceptor-ref name="userInRole" />
</interceptor-stack>
</interceptors>
My validation xml is:
<validators>
<field name="firstName">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message key="errors.required" />
</field-validator>
<field-validator type="regex">
<param name="regex">^[ a-zA-Z0-9'\-,.!:##/]*$</param>
<message key="errors.invalidCharacter"/>
</field-validator>
<field-validator type="stringlength">
<param name="maxLength">50</param>
<message key="errors.maxlength"></message>
</field-validator>
</field>
<field name="lastName">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message key="errors.required" />
</field-validator>
<field-validator type="regex">
<param name="regex">^[ a-zA-Z0-9'\-,.!:##/]*$</param>
<message key="errors.invalidCharacter"/>
</field-validator>
<field-validator type="stringlength">
<param name="maxLength">50</param>
<message key="errors.maxlength"></message>
</field-validator>
</field>
Any help would be appreciated, thanks!
Here is the requested dirtyFlag() code (and related code):
//needToConfirm used by confirm exit
var needToConfirm = false;
//default string message to display before leaving a page when data on the page has changed
//these changes were made to allow the message displayed before exiting to be customized
var defaultWarningMessage = "There is unsaved data on this screen. Do you want to exit anyway?";
var dirtyWarningMessage = defaultWarningMessage;
//this line intercepts attempts to leave the page via clicking the X button.
window.onbeforeunload = function ()
{
if (needToConfirm)
{
var outMessage = dirtyWarningMessage;
setDirtyWarningMessage(defaultWarningMessage);
return outMessage;
}
// no changes - return nothing
}
//function to set the string message to display before leaving a page when data on the page has changed
function setDirtyWarningMessage(inMessage)
{
dirtyWarningMessage = inMessage;
}
//function to set dirty flag
function dirtyFlag()
{
//alert ("Dirty flag set");
needToConfirm = true;
}
//function to clear dirty flag
function clearDirtyFlag()
{
//alert ("Dirty flag cleared");
needToConfirm = false;
}
//function to confirm close
function confirmClose()
{
if (needToConfirm)
{
var agree=confirm("Some data on the page is modified. Do you wish to leave the page without saving changes?");
if (agree == true)
{
needToConfirm = false;
window.close();
}
else
{
return false;
}
}
else
{
window.close();
}
}
Guess what ?
<s:textfield name = "firstName"
id = "firstName"
value = ""
maxlength = "50"
class = "form-control"
onchange = "dirtyFlag();"
tabindex = "4"/>
value="" forces the value to always be empty.
Use value="%{firstName}", or
remove it and let name="firstName" do the job (recommended).
Related
This question already has an answer here:
Struts 2 Validation and Input fields repopulation
(1 answer)
Closed 6 years ago.
I was recently working with a login page with Struts2 framework and for validating the fields i used XML Validation feature provided by Struts2. And the fields are validated but the problem is that, if any of the field is not empty after validation the those field values are not repopulated in the corresponding field.The Example code is given.The version of the framework is 2.5.x.
Login.jsp
<s:form method="post" action="authenticate">
<div class="form-group">
<span class="input-icon">
<s:textfield name="strUserName" id="strUserName" cssClass="form-control" placeholder="Username or Email"></s:textfield>
<i class="fa fa-user"></i>
</span>
<span>
<s:fielderror fieldName="strUserName"/>
</span>
</div>
<div class="form-group">
<span class="input-icon">
<s:password name="strPassword" id="strPassword" cssClass="form-control" placeholder="Password"></s:password> <i class="fa fa-lock"></i>
</span>
<span>
<s:fielderror fieldName="strPassword"/>
</span>
</div>
</s:form>
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.action.extension" value=",json"/>
<!-- Set to false before deploying the application -->
<constant name="struts.devMode" value="true" />
<constant name="struts.enable.SlashesInActionNames" value="true"/>
<constant name="struts.mapper.alwaysSelectFullNamespace" value="false"/>
<constant name="struts.configuration.xml.reload" value="false" />
<!-- constant to define global resource bundle -->
<constant name="struts.custom.i18n.resources" value="globalMessages" />
<constant name="struts.ui.theme" value="simple" />
<package name="<package_name>" namespace="/" extends="struts-default">
<action name="authenticate" class="<Action_class_name>" method="<method_name>">
<interceptor-ref name="store">
<param name="operationMode">STORE</param>
</interceptor-ref>
<interceptor-ref name="defaultStack" />
<result type="redirectAction">Successpage</result>
<result name="input" type="redirectAction">login</result>
</action>
<action name="login">
<interceptor-ref name="store">
<param name="operationMode">RETRIEVE</param>
</interceptor-ref>
<result>login.jsp</result>
</action>
</package>
</struts>
Action_name-validation.xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<validator type="requiredstring">
<param name="fieldname">strUserName</param>
<param name="trim">true</param>
<message key="errors.required"></message>
</validator>
<validator type="requiredstring">
<param name="fieldname">strPassword</param>
<param name="trim">true</param>
<message key="errors.required"></message>
</validator>
</validators>
Action_name.java
public class Action_name extends ActionSupport implements ModelDriven<UserModel> {
private UserModel user;
public String method_name() {
if(success){
return SUCCESS;
}else{
return INPUT;
}
}
#Override
public UserModel getModel() {
user = new UserModel();
return user;
}
}
Applicatin - intial run
Application - After Validation
value "xyz" is not repopulated after the validation.
There are two problems:
your login action
<action name="login">
<interceptor-ref name="store">
<param name="operationMode">RETRIEVE</param>
</interceptor-ref>
<result>login.jsp</result>
</action>
has only a single interceptor, the MessageStore one.
It should have instead at least the ModelDriven and the Parameters Interceptors to work correctly. For example
<action name="login">
<interceptor-ref name="store">
<param name="operationMode">RETRIEVE</param>
</interceptor-ref>
<interceptor-ref name="defaultStack" />
<result>login.jsp</result>
</action>
But note that this would lead to infinite recursion due to the MessageStore Interceptor always adding errors and the Workflow Interceptor always returning "input"; to avoid it you should define a secondary defaultStack in your struts.xml with all the intercpetors except the Workflow one, otherwise the MessageStore with RETRIEVE will make it loop or, if you haven't defined an input result for your login action, complaining about a missing input result.
The second error is that you are redirecting, and hence losing the parameters. You're using the MessageStore Interceptor to preserve Action Messages, Action Errors and Field Errors across the redirection, but every other parameter is lost. If you want to preserve a parameter across a redirectAction you must explicitly send it, or store it in session in the source action and retrieving it in the destination action. In your case, it would be better to simply return the JSP in case of input result, instead of redirecting:
<action name="authenticate" class="<Action_class_name>" method="<method_name>">
<interceptor-ref name="store">
<param name="operationMode">STORE</param>
</interceptor-ref>
<interceptor-ref name="defaultStack" />
<result type="redirectAction">Successpage</result>
<result name="input" >login.jsp</result>
</action>
<action name="login">
<interceptor-ref name="defaultStack" />
<result>login.jsp</result>
</action>
Trying Kendo UI JSP editable grid. Grid is working with few problems.
(Version : Kendo UI v2015.3.1111 )
Export: Even with allPages="allPages", its exporting only current
page.
After CREATE, GRID is not updated with server response which has user createDate. Same with Update, grid not updated with update date
even though the updated user object is passed.
Grid shows user added even if it failed in the backend. How to handle error response for create /update and show the failed message ?
Any help greatly appreciated.
Controller create part:
#RequestMapping(value = "/user/create", method = RequestMethod.POST)
public #ResponseBody User create(#RequestBody Map<String, Object> model) {
log.debug("create");
User target = new User();
target.setUserName((String)model.get("UserName"));
target.setFirstName((String)model.get("firstName"));
target.setLastName((String)model.get("lastName"));
target.setOpenDate(getDateFromStr((String)model.get("openDate")));
target.setEditDate(getDateFromStr((String)model.get("editDate")));
User user = userDao.createUser(target);
log.info("user"+user.getUserId()+user.getOpenDate());
return user;
}
JSP PART:
<c:url value="/user/create" var="createUrl" />
<c:url value="/user/read" var="readUrl" />
<c:url value="/user/update" var="updateUrl" />
<c:url value="/user/destroy" var="destroyUrl" />
<c:url value="/user/saveexcel" var="saveExcelUrl" />
<c:url value="/user/savepdf" var="savePdfUrl" />
<kendo:grid name="grid" pageable="true" sortable="true" height="750px" filterable="true">
<kendo:grid-scrollable/>
<kendo:grid-pdf fileName="KendoUIGridExport.pdf" allPages="allPages" proxyURL="${savePdfUrl}"/>
<kendo:grid-excel fileName="KendoUIGridExport.xlsx" allPages="allPages" proxyURL="${saveExcelUrl}" />
<kendo:grid-editable mode="popup" confirmation="Are you sure you want to remove this item?"/>
<kendo:grid-toolbar>
<kendo:grid-toolbarItem name="create"/>
<kendo:grid-toolbarItem name="excel"/>
<kendo:grid-toolbarItem name="pdf"/>
</kendo:grid-toolbar>
<kendo:grid-columns>
<kendo:grid-column title="User Name" field="userName" width="120px"/>
<kendo:grid-column title="First Name" field="firstName" width="120px" />
<kendo:grid-column title="Last Name" field="lastName" width="120px" />
<kendo:grid-column title="Open Date" field="openDate" width="120px" format="{0:MM/dd/yyyy}" />
<kendo:grid-column title="Edit Date" field="editDate" width="120px" format="{0:MM/dd/yyyy}" />
<kendo:grid-column title=" " width="150px">
<kendo:grid-column-command>
<kendo:grid-column-commandItem name="edit" />
<kendo:grid-column-commandItem name="destroy" />
</kendo:grid-column-command>
</kendo:grid-column>
</kendo:grid-columns>
<kendo:dataSource pageSize="10" serverPaging="false" serverSorting="false" serverFiltering="false" serverGrouping="false" >
<kendo:dataSource-transport>
<kendo:dataSource-transport-create url="${createUrl}" type="POST" dataType="json" contentType="application/json"/>
<kendo:dataSource-transport-read url="${readUrl}" type="POST" dataType="json" contentType="application/json"/>
<kendo:dataSource-transport-update url="${updateUrl}" type="POST" dataType="json" contentType="application/json" />
<kendo:dataSource-transport-destroy url="${destroyUrl}" type="POST" dataType="json" contentType="application/json" />
<kendo:dataSource-transport-parameterMap>
<script>
function parameterMap(options,type) {
return JSON.stringify(options);
}
</script>
</kendo:dataSource-transport-parameterMap>
</kendo:dataSource-transport>
<kendo:dataSource-schema>
<kendo:dataSource-schema-model id="userId">
<kendo:dataSource-schema-model-fields>
<kendo:dataSource-schema-model-field name="userName" type="string" >
<kendo:dataSource-schema-model-field-validation required="true" />
</kendo:dataSource-schema-model-field>
<kendo:dataSource-schema-model-field name="firstName" type="string">
<kendo:dataSource-schema-model-field-validation required="true" />
</kendo:dataSource-schema-model-field>
<kendo:dataSource-schema-model-field name="lastName" type="string">
<kendo:dataSource-schema-model-field-validation required="true" />
</kendo:dataSource-schema-model-field>
<kendo:dataSource-schema-model-field name="openDate" type="date" editable="false" />
<kendo:dataSource-schema-model-field name="editDate" type="date" editable="false"/>
</kendo:dataSource-schema-model-fields>
</kendo:dataSource-schema-model>
</kendo:dataSource-schema>
</kendo:dataSource>
</kendo:grid>
Resolved myself: For pdf, allPages="true" works.
Grid refresh: FOR requestEnd event
function onRequestEnd(e) {
if (e.type == "create") {
e.sender.read();
}
else if (e.type == "update") {
e.sender.read();
}
}
Do I need separate Struts action for each form?
Currently, one web page have two forms in jsp. I currently put all validation code in validate() in the Action class. The problem is that it appears the net result is that Form A will then be linked to Form B and vice versa since the validation code is inside the same Action class.
So am I correct that if I want the two forms to be validated independently, then I would require two separate Actions?
Form A:
<font color="red" size="2"><s:actionerror /> <s:fielderror /></font>
<s:form action="NewcreateUser" method="post">
<s:textfield type="text" name="form1filed" key="temp" size="11" label="Mobile_Num" required="true"></s:textfield><br />
<s:submit value="Continue" id="continueSignUp" validate="true"></s:submit>
</s:form>
Form B:
<font color="red" size="2"><s:actionerror /> <s:fielderror /></font>
<s:form action="NewcreateUser" method="post">
<s:textfield type="text" name="form2filed" key="formb" size="11" label="Mobile_Num" required="true"></s:textfield><br />
<s:submit value="Continue" id="continueSignUp" validate="true"></s:submit>
</s:form>
Here You can validate your fields,both form1filed,form2filed with the same Action class
NewcreateUser,And the NewcreateUser-validation.xml file looks like this,
<field name="form1filed">
<field-validator type="required" short-circuit="true">
<message key="form1filed Is Required" />
</field-validator>
</field>
<field name="form2filed">
<field-validator type="required" short-circuit="true">
<message key="form2filed Is Required" />
</field-validator>
</field>
I have this form:
<s:form
action="conexion" validate="true" theme="css_xhtml">
<s:textfield name="username" key="profile.rut" labelposition="left" />
<s:password name="password" key="profile.password" labelposition="left" />
<s:submit id="boton_ingreso" align="left" cssClass="send" value="Entrar" />
</s:form>
This validators:
<validators>
<field name="username">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>*</message>
</field-validator>
<field-validator type="rutValidator">
<param name="trim">true</param>
<message>*</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>*</message>
</field-validator>
</field>
</validators>
And this definition:
<action name="conexion" class="agenda.SecurityAction">
<interceptor-ref name="profiling">
<param name="profilingKey">profilingKey</param>
</interceptor-ref>
<interceptor-ref name="jsonValidationWorkflowStack"/>
<result name="success" type="tiles">/profile.tiles</result>
<result name="error" type="redirectAction">
<param name="actionName">cliente</param>
</result>
<result name="input" type="redirectAction">
<param name="actionName">cliente</param>
</result>
</action>
This works perfectly client side. But when I remove validate="true" from the form in order to test server side, valdation occus and the form loads again, but no error message appears.
Other question regarding the same: I am not using JSON validation, but the normal client side validation. Why it does not work when I remove the definition?
I guess it is because maybe jsonValidationWorkflowStack inherits from other validation interceptor. If it is, perhaps it is convenient to define the other one, instead of jsonValidationWorkflowStack.
Your input result is a redirect and during redirect all request attributes (also messages) are gone, you must use MessageStoreInterceptor to persist them between requests.
See also Struts 2 Validation using Message Store Interceptor
http://struts.apache.org/development/2.x/docs/message-store-interceptor.html
I'm developing with Struts 2 and I would like to validate 2 methods in the same action (which represents a user). The first is the login method which checks the role of the user (admin or normal user) and the second is to edit the user :
public class UserAccountAction extends AppSupport {
public String login() {
if (getUsername().equals("admin") && getPassword().equals("admin")) {
session.put("username", getUsername());
return "adminSuccess";
} else if (getUsername().equals("user") && getPassword().equals("user")) {
session.put("username", getUsername());
return "userSuccess";
} else {
addActionError(getText("login.failedLoginCredential"));
return INPUT;
}
}
public String editProfile {
// ...
}
}
For that, I created 2 xml files : UserAccountAction-login-validation.xml :
<validators>
<field name="login">
<field-validator type="required">
<message key="form.required" />
</field-validator>
</field>
<field name="password">
<field-validator type="required">
<message key="form.required" />
</field-validator>
</field>
</validators>
The UserAccountAction-editProfile-validation.xml is the same with lastname and firstname.
The struts.xml :
<action name="login" method="login" class="com.project.action.UserAccountAction">
<result name="input">/jsp/login.jsp</result>
<result name="userSuccess" type="redirect">home.html</result>
<result name="adminSuccess" type="redirect">admin/home.html</result>
</action>
<action name="edit_account" method="editProfile" class="com.facilityrh.action.UserAccountAction">
<result name="input" type="tiles">userEditProfile</result>
<result name="success" type="redirect">account.html</result>
</action>
And the login.jsp :
<s:if test="hasActionErrors()">
<div class="error"><s:actionerror /></div>
</s:if>
<s:if test="hasActionMessages()">
<div class="message"><s:actionmessage /></div>
</s:if>
<s:form action="login" method="post">
<s:textfield name="login" key="login.login" /><br />
<s:password name="password" key="login.password" /><br />
<s:submit name="submit" key="login.submit" />
</s:form>
For the moment, in the action, the verification is basic but after, I'll use the database to get informations.
The problem is when I submit the form (login or editProfile), the method is not executed because I've no error, I return on the same jsp (without the required messages next to input)
Thank you