Struts2: Autopopulating fields based on a dropdown value without JavaScript - javascript

I tried searching the site but could not find an answer to my question.
i am developing a java Struts2 web application.
There are 3 form fields on a jsp page as follows:
(Struts2 tags are being used)
<s:form action="action1">
other fields
......
<s:select name="test1" list="{'A','B','C'}"></s:select>
<s:textfield name="test2"></s:textfield>
<s:textfield name="test3"></s:textfield>
.....
other fields
<s:submit value="submit1"><s/submit>
</s:form>
when a value is selected in test1 field, test2 and test3
would needed to be populated from the database based on the
value selected in test1.
as per the process i need to implement, i need to do some calculations based on the input from jsp1(presented above), and present the result on jsp2 which has to have entirely different content from jsp1. My issue is limited to the data entry in jsp1.
what would be the best way of doing this without javascript?
assume that javascript is disabled in the browsers accessing
the application.
thanks,

EDIT
It seems that there's a bit of confusion here, let's try to make it clear:
There are basically three ways of triggering a communication with the server from the browser:
submit HTML
submit JS
AJAX submit
You may or may not care about giving support to users browsing with JavaScript disabled;
if you DO NOT care, then you can proceed as you wish;
if you DO care, then you have two ways in front of you:
make an unique version of the pages, that works both with and without JS (by using ONLY option "1", "submit HTML");
make the pages working in two possible ways, mutually exclusive: while processing the page, you detect if the user has javascript enabled: if yes, you go with JS (submit or AJAX), if not, you fallback to the non JS solution ( "submit HTML" ).
Both this two solutions works with and without JS, but the latter is generally preferred because you can set up a nice, good-looking, user's experience-oriented WebApp for the 99% of the users, by using JavaScript and eventually AJAX, and create a fallback solution for the 1% of the users that, even if the site won't be nice as in the JS version, and even if it won't have ALL the features of the JS version, it would still be usable, and the core functionalities will be available.
As I said in the comment above, there is no need for the fallback version of the WebApp to be as nice, as fast, as good in user experience as the JS version: it should simply... work.
For example, this JSP will work in both cases: it will do a JavaScript Submit after selecting an element from the Select if JS is enabled, and it will do a submit after pressing the Submit button if JS is disabled.
With JS disabled, onchange will be ignored and <noscript> processed.
With JS enabled, onchange will be processed and <noscript> ignored.
<s:form action="myAction">
<s:select onchange="javascript:document.forms[0].submit();"
name="test1" value="test1" list="{'A','B','C'}" />
<s:textfield name="test2" value="test2" />
<noscript>
<span>
Since you have JS disabled,
you need to manually press to the GO button,
but you still can make it work ;)
</span>
<s:submit value="go" />
</noscript>
</s:form>
in your Action
public class MyAction extends ActionSupport{
private String test1="";
private String test2;
/* Getters and Setters */
public String execute(){
if (test1.length()>0)
assignValues();
return SUCCESS;
}
private void assignValues(){
if (test1.equals("A")){
test2 = "A was chosen, do something";
} else if (test1.equals("B")){
test2 = "B was chosen, do something else";
} else if (test1.equals("C")){
test2 = "C was chosen, what's next?";
}
}
}
The other doubts you are expressing in comments suggest that you may want to step back for a moment and read some Struts2 tutorial, to be sure of gaining the maximum from the framework.
If you have other fields in the same Form that you don't want to be affected, just declare a variable in the Action (with the Getter and the Setter), for each one of them: they will be preserved in the reloaded page, because they will be sent (because they're in form) with the submit, they will be injected through the Setter, they will be read back through the Getter and injected in the new page by the matching with their name and the Action variable.
Otherwise you could use AJAX, but I'd start from this.
And no, you can't nest forms.

Thanks to Andrea Ligios, i have the below solution to my issue.
jsp1 was changed as below
<s:form action="action2">
other fields
......
<s:select name="test1" list="{'Select','A','B','C'}"
onchange="javascript:document.forms[0].submit();"></s:select>
<noscript><s:submit value="populate test2 and test3"></s:submit></noscript>
<s:textfield name="test2"></s:textfield>
<s:textfield name="test3"></s:textfield>
.....
other fields
<s:submit value="submit1" action="action1"><s/submit>
</s:form>
struts.xml has following mappings
.....
<action name="action2" class="MyAction" method="populate">
<result name="success">/jsp1.jsp</result>
</action>
<action name="action1" class="MyAction">
<result name="success">/jsp2.jsp</result>
</action>
.....
MyAction has following code
public class MyAction extends ActionSupport{
//all field declarations
//Getters and Setters
public String execute(){
//do processing for jsp2 based on values from jsp1
return SUCCESS;
}
public String populate(){
//populate test2 and test3 from database based on value of test1
return SUCCESS;
}
}

Related

Use form data to update web page

Before I provide a bunch of code I'd like to first find out if what I'm trying to do is even possible.
I've created a web based version of the dice game called PIG using HTML & JavaScript. The user can change some of the game's settings by clicking on a "Settings" button on the main page. This button brings up a modal window containing an HTML form (). I'd like to use the data that the users enters and submits on this form to update various settings on the game's main page.
I chose to use an HTML5 form because was hoping to use the native HTML5 form validation capabilities rather than try and replicate that validation checking logic myself using JavaScript.
So my approach was to use javascript to get the data off the form on submit. I tried two different approaches to get this to work:
1) Using an "onsubmit=function getSettings()" on the tag
2) Using a submit button for the form with an onclick="getSettings()".
With both of these approaches I was able to successfully get all the values from the form on submit and use those values to successfully populate the main game page using the gettSettings() function however when I exit the getSettings() function the webpage values that I updated don't stick...they revert back to the original values regardless of which of these two approaches I use.
I know the values were successfully updated because when I set a break point on the last statement of the getSettings() method I can see that all of the values on the main page have been updated to reflect what was filled in on the form...so I know I'm grabbing all of the data successfully and updating the main page with those values.
I'm puzzled as to why the values that I successfully change on the web page simply revert back to their original value upon exit of the getSettings() function.
Maybe it's just not possible to do what I'm trying to do? And if not does anyone know why given I can see the values are successfully changed before they revert back to their original value. What am I missing?
Again I'm using a Form and collecting the data on submit so that I can leverage the "native" HTML5 form validation capabilities.
Regards.
***** EDIT TO ADD KEY SEGMENTS OF CODE *******
Here is the code HTML Code for the modal form:
<form name="config-settings" onsubmit="getSettings()">
<!-- <form name="config-settings">-->
<span class="errMsg"></span>
<div class="row clearfix">
<div>
<label>Player 1:</label>
</div>
<div>
<input type="text" name="input-name-0" id="input-name-0" maxlength="10" placeholder="Enter name" pattern="^\S+$">
</div>
</div>
<div class="row clearfix">
<div>
<label>Player 2:</label>
</div>
<div>
<input type="text" name="input-name-1" id="input-name-1" maxlength="6" placeholder="Enter name" pattern="^\S+$">
</div>
</div>
<div class="row clearfix">
<div>
<label>Winning Score:</label>
</div>
<div>
<input type="number" name="winning-score" id="winning-score" default="100" placeholder="Enter winning score">
</div>
</div>
<div class="row clearfix">
<div>
<label>Number of Dice:</label>
</div>
<div>
<select name="diceValues" id="dice-value">
<option value=""> - Select - </option>
<option value="dice-1">One Dice</option>
<option value="dice-2">Two Dice</option>
</select>
</div>
</div>
<!-- Below is alt method I used to submit form..yields same results -->
<!-- <input type="submit" value="Submit" onclick="getSettings()">-->
<input type="submit" value="Submit">
</form>
Here are the global variables defined and used in getSettings() method:
// Global variables
var scores, roundScore, activePlayer, gamePlaying, gamesWonCount, playerNames, winningScore, numOfDice, matchScore, msgs;
var player0, player1, score;
var player0Field = document.getElementById('name-0');
var player1Field = document.getElementById('name-1');
var scoreField = document.getElementById('winScore');
Here is the listener for the Settings button on the main web page that brings up the setting modal window containing the settings form:
//*********************************************************
// Open Settings Modal Windows
//*********************************************************
document.querySelector('.btn-settings').addEventListener('click', function () {
// Settings can't be changed if game is actively underway
if (!gamePlaying || roundScore === 0) {
document.querySelector('#modal-settings').style.display = 'block';
} else {
// Make error message visible
msgs.style = 'block';
// Create message to indicate settings successfully updated
msgs.textContent = "Settings can't be updated during game";
msgs.style.backgroundColor = 'pink';
fadeOut(msgs);
}
});
Here is the getSettings() javaScript function (note: there are no local variables defined in this function...they are all defined as global values (first few lines of javaScript app).
function getSettings() {
// Alternative call if I want this function to be called via eventListner
//document.querySelector('.btn-save').addEventListener('click', function () {
console.log("getSettings method called");
player0 = document.forms["config-settings"]["input-name-0"].value;
player1 = document.forms["config-settings"]["input-name-1"].value;
score = document.forms["config-settings"]["winning-score"].value;
// Reset msgs so they will be displayed each time
msgs.style = 'block';
playerNames[0] = player0;
player0Field.innerHTML = playerNames[0];
playerNames[1] = player1;
player1Field.textContent = playerNames[1];
// Set Winning score on UI to value on form
scoreField.textContent = score;
// numOfDice = document.getElementById('dice-value').value;
// Create message to indicate settings successfully updated
msgs.textContent = "Successfully updated settings";
msgs.style.backgroundColor = 'lightgreen';
fadeOut(msgs);
document.querySelector('#modal-settings').style.display = 'none';
}
I don't know exactly what this getSettings() function of yours is supposed to do, but I can try to give you a piece of advice:
Some of the form validation capabilities of HTML5 are not entirely supported on all of the used browsers(some users don't fancy to update their browser). Therefore relying on the "native" validation of HTML5 isn't exactly best practice.
If you want to manipulate the form values in any way before submitting the form I would rather add a listener to the submit button for click events, prevent any other action, make the checks/ manipulation of the form data and then manually submit the form. Anyways, front-end validation isn't entirely safe, so if you're peddling sensitive data it's mandatory that you'll make checks on serverside(if your app uses a server).
To exemplify what I've explained earlier:
document.getElementById("myBtn").addEventListener("click", function(event){
//Stops the form submitting.
event.stopImmediatePropagation();
//Do the checks here.
//Sends the form.
document.getelementById("myForm").sumbit();
);
If you change local variables inside this getSettings() function, the variables will be changed only within the function scope. You might want to read about scope in javascript. (this was just an educated guess).
I hope you find this useful, good luck!
Okay...I finally figured it out! The problem was not a scoping problem but instead and issue with how "onSubmit" works.
The solution involved making two changes:
1) Adding a return statement to the "onsubmit" attribute when calling the "getSettings()" function;
<form name="config-settings" onsubmit="return getSettings()">
2) Returning false at the end of the gettSettings();
return false;
Note: I had previously tried returning true but not false. I was errantly under the impression that returning false value from getSettings() function would disable HTML5 "native" validation and force me to implement all of the error checking myself...which was not what I wanted. It is now my understanding that returning false merely prevents the form from being submitted..but it doesn't disable the HTML5 native validations.
This solution worked perfectly for me because my goal was not to submit the form to the server (as there is no server component here) but merely to use the "native" HTML5 form checking and then update the values on the local web page.
With all of that said I'm still not entirely sure why when I didn't provide the return statement or when I returned true why all of my changes reverted back to their originally value. If anyone can shed some light on why I'd appreciate it.
Cheers

Primefaces ajax not updating panel or panelGrid component in the same form

I am trying to write an application that registers a new user and lets them fill in a user profile after they have created their login details. I need another form to display an exact copy of what the user has entered as a validation, after which the user can accept or edit the entry before persisting the profile form.
The user is successfully created using the following action:
public String makeUser() {
if (nameAvailable = true) {
facade.create(newUser);
} else {
userMessage = "VALIDAION FAILED. Please try again and check that your uder name is not already taken";
}
selUser = newUser;
return "/Main/Users/UserProfile";
}
The user is then directed to a profile form:
<h:form id="proform">
<p:outputPanel id="propan">
<p:panelGrid id="userpro" columns="2">
<p:outputLabel value="Salutation"/>
<p:inputText value="#{userBean.salutation}"/>
<p:outputLabel value="First Name:"/>
<p:inputText value="#{userBean.proFirstName}"/>
<p:outputLabel value="Surame:"/>
<p:inputText value="#{userBean.proSurname}"/>
<p:outputLabel value="Date of Birth:"/>
<p:calendar value="#{userBean.dateofbirth}"/>
</p:panelGrid>
<p:commandLink id="make" value="Create"
action="#{userBean.checkProfile}"
process=":proform:make :proform:userpro"
update="proform:usercheck"/>
// also tried
process="userpro"
update="usercheck"/>
The following checkProfile action is used to create the validation form for the user to check their input (but does not seem to be getting executed) :
public void checkProfile() {
newPro = new Enprofile(salutation, proFirstName, proSurname, dateofbirth, selUser);
salutation = getSalutation();
newPro.setSaltuation(salutation);
proFirstName = getProFirstName();
newPro.setFirstname(proFirstName);
proSurname = getProSurname();
newPro.setSurname(proSurname);
dateofbirth = getDateofbirth();
newPro.setDateofbirth(dateofbirth);
selUser = getSelUser();
newPro.setUser(selUser);
System.out.println("New Profile First Name" + newPro.getFirstname());
setNewPro(newPro);
}
The user check form is:
<p:panelGrid id="usercheck" columns="2">
<p:outputLabel value="#{userBean.newPro.saltuation}"/>
<p:outputLabel value="#{userBean.newPro.firstname}"/>
<p:outputLabel value="#{userBean.newPro.surname}"/>
<p:outputLabel value="#{userBean.newPro.dateofbirth}"/>
<p:commandLink id="accept" value="Accept"
action="#{userBean.makeProfile}"
ajax="false"/>
</p:panelGrid>
</h:form>
When calling the checkProfile action from the profile form (id: proform), the usercheck form remains blank and the console shows no error messages.
Reading the PF documentation and the questions here, I know that the Ajax API consists of three fundamental functions
PrimeFaces.ajax.Request.handle(cfg);
PrimeFaces.ajax.Response
Since the console is totally blank it would suggest that the ajax request is not getting fired in the first place, which leads me to think that I'm doing something wrong in the process part of the checkProfile action?
UPDATE:
In response to BalusC's comment, please note I have gone through all of the points in the following question (marked as duplicate):
commandButton/commandLink/ajax action/listener method not invoked or input value not updated
Specifically I have adjusted looked at point 8
If you're using Ajax, then make sure that the UIInput and UICommand
components of interest are covered by the <f:ajax execute> or e.g.
<p:commandXxx process>, otherwise they won't be executed/processed.
See also Understanding process and update attributes of PrimeFaces.
<p:commandLink id="make" value="Create"
action="#{userBean.checkProfile}"
process=":proform:make :proform:userpro"
update=":proform:usercheck"/>
As above I think I have included the UIInput and UICommand in the process execution, but still no luck. The console does not even print the confirmation value for the newly created instance in the checkProfile method:
System.out.println("New Profile First Name" + newPro.getFirstname());
As for the other points in the question:
1) UICommand and UIINput components are inside an h:form tag
2) Multiple UIForm components do not seem to be nested
3) No input validation error seems to have occured and the
following message tag shows blank:
<p:messages id="msg" for="make"
showDetail="true"
autoUpdate="true"/>
4) Components are not inside any iterating tag
5) No rendered attribute has been explicitly specified for any
Component ** (i assume not explicitly specifying rendered attribute defaults to true??)**
6) No JS errors are recorded for the UIInput actions (or for anything else on the page)
7) There is an h:head in the master template
8) Both UICommand and UIInput components of interest are being
included in the ajax process of the commandLink
9) There is only one form on the page (after the most recent edit)
10) The form does not contain enctype="multipart/form-data
11) I'm using a regular action tag in the commandLink
12) No calls to FacesContext#renderResponse() or
FacesContext#responseComplete() seems to have taken place by any
event listeners
13) No Filter or Servlet in the same request-response chain has
blocked the request fo the FacesServlet
On the final point (13), it may be possible that a request-response chain has disrupted (not blocked) the FacesServlet request. If I set the ajax value to false in the checkProfile action, it produces the following stack:
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:604)
at java.util.ArrayList.get(ArrayList.java:382)
at javax.faces.component.AttachedObjectListHolder.restoreState(AttachedObjectListHolder.java:165)
at javax.faces.component.UIComponentBase.restoreState(UIComponentBase.java:1607)
at com.sun.faces.application.view.FaceletPartialStateManagementStrategy$2.visit(FaceletPartialStateManagementStrategy.java:380)
at com.sun.faces.component.visit.FullVisitContext.invokeVisitCallback(FullVisitContext.java:151)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1689)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at com.sun.faces.application.view.FaceletPartialStateManagementStrategy.restoreView(FaceletPartialStateManagementStrategy.java:367)
This suggests that there is there is a problem with restoring the view state, as there was previously a page rendered when a user was created. Do I need to refresh the View state?
I'm proposing that this question is not duplicate and there maybe more to the error than the 13 points mentioned in the dupe? Thanks

client-side form validation after clicking SUBMIT

I have 2 php files "source.php" and "target.php". In the source.php part I have,
<form method="POST" id="form1" action="target.php">
...
<input type="submit" name="submit" value="Submit"/>
</form>
When I click on submit it goes to the "target.php" (even if I have errors in the form), but I want that, only after all form fields are validated it will go to the target page, else it shows some kind of warning message and stays on the same page. Please help! Maybe this is a stupid question for some but I am a beginner. (I know how to do all the field validations and its working fine).
Duplicate of duplicate questions.Please search throughly before you post next time.
Generally javascripts are used for validation.But there are cases when javascripts become inefficient,for example when you need to validate country and its states.Its not practical to send the entire list of countries and states to the client. In such scenarios AJAX is used.By using AJAX the client sends the data to server immediatly after the user enters it.then it fetch only the required data.Its a simultaneous two way communication between client and server.for example if the user enters country name as INDIA,using AJAX states of INDIA are loaded for validation,thus saving bandwidth.
JavaScript and AJAX are not easy to learn,you must research try and correct different codes.Just google "JavaScript form validation"...
This is from w3Schools...
Required Fields
The function below checks if a field has been left empty. If the field is blank, an alert box alerts a message, the function returns false, and the form will not be submitted:
function validateForm()
{
var x=document.forms["myForm"]["fname"].value;
if (x==null || x=="")
{
alert("First name must be filled out");
return false;
}
}
The function above could be called when a form is submitted:
Example
<form name="myForm" action="demo_form.asp" onsubmit="return validateForm()" method="post">
First name: <input type="text" name="fname">
<input type="submit" value="Submit">
</form>
here is more basic examples http://www.w3schools.com/js/js_form_validation.asp
Good Luck
You can use AJAX to validate your form. JavaScript is not recommended for form validation.
A simple tutorial for AJAX Validation is available here
But be aware, even if you are validating your form before submission to target.php, always make sure that you check the data in target.php too. This is because JavaScript can be changed (thanks to the modern DOM interpreters) in the browser. It can be made so that the form is submitted without AJAX verification. So you should check it twice, before and after submission.
Also make sure to escape the data, as user input can never be trusted.
You should also user strip_tags($string) to prevent use from inserting php code.
JavaScript is most likely the easiest way to do this (read the other posts).
However, if you don't want to use JavaScript you could always check if all forms are set using isset() or something similar and then passing on the $_POST variables in the URL and grabbing those using $_GET. Of course make sure there isn't any sensitive information in the URL. In addition: you could always work with global variables.
Another way to do this without JavaScript is submit to a database after several checks (like escaping the strings etc.), perhaps even encrypt, but I don't suggest this since this is the long way around.

Can i use JS to replace a GET-parameter with a Post in a link?

I'm working with an old ASP WebForms page in which there is a link which opens in a new windo using javascript. This link includes a GET-parameter, like this:
<href="javascript:window.open(http://myurl.com?MyId=123).focus()">
Search for object
</a>
What I would like to do is replace this GET-parameter with a Post-variable in order to avoid the value of MyId being stored in the browser-history. Possibly something like:
<input type="hidden" id="MyId" name="MyId" value="123">
<a href="submitSearchCriteria()">
Search for object
</a>
Note: Since this is a webforms page, the whole contents of the page is within a pair of <form>...</form> tags which post back to the page itself, and I don`t want to mess with these. The page I would like to link to is another page.
My question: Is there some fairly simple, clean and safe way to pass along a Post-variable from within a link like this? I would prefer to do this without including any third-party java script libraries if possible (I want to minimize the necessary changes to an aging system).
Any ideas?
Add your MyId in your form:
<input type="hidden" id="MyId" name="MyId" value="123">
Then your hyperlink:
Search for object
Then use javascript to change your form action:
function submit(){
[Your Form].action = "[Your Action]";
[Your Form].submit();
}
The form submits but as the page refreshes, the form action goes back to what it was before. But this could depend to where you point back your new action. You could add something to handle the response. This is the easiest solution if you ask me. But for the cleanest, you should try reading about AJAX.

Spring MVC - Set an actionURL parameter with Javascript

Is it possible to dynamically set a Spring MVC portlet:actionURL portlet:param using javascript? I have tried with the following code, but the id value always comes across as null to the controller. I have verified that setting the portlet:param manually passes the value correctly:
<portlet:param name="id" value="2" />
I have also verified the value in the javascript is being set correctly and is not null.
(Note: I've changed the variable names, etc. from the original code to simplify it and obfuscate it since it is my employer's code.)
JSP:
<portlet:actionURL var="modifyURL">
<portlet:param name="do" value="modify" />
<portlet:param name="id" value="${model.id}" />
</portlet:actionURL>
...
<form:form action="${modifyURL}" id="modifyForm" modelAttribute="model">
<form:hidden path="id" id="id" />
</form:form>
Javascript called when the update URL is clicked:
function update() {
document.forms[0]["id"].value = selectedId;
document.forms[0].submit();
}
Controller:
#RequestMapping(params = {"do=modify"})
public void modify(#ModelAttribute("model") Model model,
#RequestParam(value = "id", required=true) Long id,
ActionRequest request, ActionResponse response,
SessionStatus sessionStatus, ModelMap modelMap) {
....
A co-worker figured it out. It looks like you just have to add the parameter to the action within the javascript and not include it in the actionURL or form.
JSP:
<portlet:actionURL var="modifyURL">
<portlet:param name="do" value="modify" />
</portlet:actionURL>
...
<form:form action="${modifyURL}" id="modifyForm" modelAttribute="model" method="POST">
</form:form>
Javascript called when the update URL is clicked:
function update() {
$("modifyForm").action = '${modifyURL}&id='+selectedId;
$("modifyForm").submit();
}
I came across this almost 3 years later, still i found it easier to add a hidden form field and when the action is clicked than to set this value to the hidden field
something like
<input type="submit" id="btn_terminate_cmpn"
value="Terminar campaƱa" onclick="setAction('terminate');">
and the javascript code
function setAction(action){
$("#actionToDo").val(action);
}
The URL generated by the portlet tag is on the server side. Javascript doesn't see the portlet tag. It only sees the actual URL. What your coworker is suggesting would work but it's not a good approach. Here he's just adding the dynamic parameter as a query string parameter which makes it visible to all the portlets on your target portal page. A better solution is to keep a hidden element (text box or something) and set the dynamic value to this hidden element in your onSubmit Javascript hander function.

Categories

Resources