I'm trying to integrate Stripe into my JSF application and am having difficulty navigating away from the "add credit card" page. Everything works, except after the user hits submit, the page does not navigate away.
Below is the addCreditCard.xhtml facelet. Adding the javascript logic as a submit eventListener and triggering the bean update method() using onclick="#{stripeCCBean.update()}" was the only way I could get the javascript to successfully create the token (the createToken method would fail if the javascript was triggered by onclick for some unknown reason) AND get the bean to recognize the hidden fields.
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
template="/WEB-INF/template.xhtml"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">
<head>
<title>Facelet Title</title>
<link rel="stylesheet" type="text/css" href="/css/StripeCCTokenize.css"/>
<script src="https://js.stripe.com/v3/" type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-3.2.0.js" type="text/javascript"></script>
<script src="/js/StripeCCTokenize.js" type="text/javascript"></script>
</head>
<h:body>
<h:form id="addCC" pt:action="/secure/addCreditCard.xhtml" pt:method="POST">
<h:inputHidden id="cardholder-name" value="#{userManagerBean.user.fullName}"/>
We loaded your customer details (name, email and customer ID) from the backend database:
<label>
Hello #{userManagerBean.user.firstName} #{userManagerBean.user.lastName}
</label>
<label>
E-Mail - #{userManagerBean.user.email}
</label>
<label>
Stripe Customer ID - #{userManagerBean.stripeUser.id}
</label>
<h:outputText value="Please enter the requested credit card and billing information below"/>
<span>Address</span>
<h:panelGrid columns="2">
<h:outputText value="Address" />
<h:inputText class="field" id="address1" value="#{stripeCCBean.card.address1}" pt:placeholder="Street address"/>
<h:outputText value="Address"/>
<h:inputText class="field" id="address2" value="#{stripeCCBean.card.address2}" pt:placeholder="Street address"/>
<h:outputText value="City" />
<h:inputText class="field" id="city" value="#{stripeCCBean.card.city}" pt:placeholder="city"/>
<h:outputText value="State" />
<h:inputText class="field" id="state" value="#{stripeCCBean.card.state}" pt:placeholder="state"/>
<h:outputText value="zip" />
<h:inputText class="field" id="address-zip" value="#{stripeCCBean.card.zipcode}" pt:placeholder="zipcode"/>
<h:outputText value="cc"/>
</h:panelGrid>
<div id="card-element" class="field"></div>
<h:commandButton value="Add Credit Card" onclick="#{stripeCCBean.update()}" type="submit" id="addButton"/>
</h:form>
</h:body>
Here is the StripeCCTokenize.js:
var stripe; var card;
$(document).ready(function () {
stripe = Stripe('pk_test_key');
var elements = stripe.elements();
card = elements.create('card', {
hidePostalCode: true,
style: {
base: {
iconColor: '#F99A52',
color: '#32315E',
lineHeight: '48px',
fontWeight: 400,
fontFamily: '"Helvetica Neue", "Helvetica", sans-serif',
fontSize: '15px',
'::placeholder': {
color: '#CFD7DF'
}
}
}
});
card.mount('#card-element');
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('addCC');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
function setOutcome(result) {
if (result.token) {
// Use the token to create a charge or a customer
// https://stripe.com/docs/charges
console.log("Token: " + result.token.id);
stripeTokenHandler(result.token);
}
}
card.on('change', function (event) {
setOutcome(event);
});
document.querySelector('form').addEventListener('submit', function (e) {
e.preventDefault();
var extraDetails = {
address_line1: document.getElementById('addCC:address1').value,
address_line2: document.getElementById('addCC:address2').value,
address_city: document.getElementById('addCC:city').value,
address_state: document.getElementById('addCC:state').value,
address_zip: document.getElementById('addCC:address-zip').value,
name: document.getElementById('addCC:cardholder-name').value
};
console.log(extraDetails);
stripe.createToken(card, extraDetails).then(setOutcome);
});
});
Here is the stripeCCBean class:
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import lombok.Data;
import lombok.ToString;
#Data
#ToString
#RequestScoped
#ManagedBean(name = "stripeCCBean")
public class StripeCCBean implements Serializable {
StripeCard card;
#ManagedProperty(value = "#{stripeServiceBean}")
private StripeServiceBean stripeServiceBean;
#ManagedProperty(value = "#{userManagerBean}")
private UserManagerBean userManagerBean;
#PostConstruct
public void init() {
System.out.println("StripeCCBean.init()");
card = new StripeCard();
card.setName(userManagerBean.getUser().getFullName());
}
public void update() throws IOException {
String token = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("stripeToken");
if (token == null) {
return;
}
System.out.println("StripeCCBean.update()");
System.out.println("Token: " + token);
System.out.println("Card: " + card);
try {
StripeService.addCard(userManagerBean.getStripeUser().getId(), token);
} catch (AuthenticationException | APIConnectionException | CardException | APIException | InvalidRequestException ex) {
ex.printStackTrace();
}
}
}
I tried adding action="#{stripeCCBean.viewAccount()}" to the <h:commandButton .../> and the corresponding method to the StripeCCBean:
public String viewAccount() {
return "AccountView";
}
However the form simply runs the Javascript, calls the stripeCCBean.update() (everything works) and then stays on that page. The customer information fields do not get cleared, however the credit card element does.
I tried adding FacesContext.getCurrentInstance().getExternalContext().redirect("/secure/AccountView.xhtml");
as well as
FacesContext.getCurrentInstance().getExternalContext().dispatch("/secure/AccountView.xhtml"); to the stripeCCBean.update() method and neither works. In fact, they throw an exception.
Can anyone see what I'm doing wrong? If I'm triggering the JS incorrectly or inefficiently, I'm happy to change that as well.
Another one of those "I have no idea why this worked", but I tried adding FacesContext.getCurrentInstance().getExternalContext().redirect("/secure/AccountView.xhtml"); to the end of the stripeCCBean.update() method and now it works.
Still no idea why I have to have the update() method called via the commandButton's onclick though...
Please remove the preventDefault function which prevents the browse default behaviour and you need not use the onclick event.
If you want to navigate by a f:commandButton / f:commandLink, use the action attribute instead of onclick.
<f:commandButton ... action="#{myBean.actionHandler}".../>
If you don't use any ajax mechanism, the bean can be #RequestScoped, other case #ViewScoped
#Named
#RequestScoped
public class MyBean
{
public String actionHandler()
{
...
return "navigationRuleName";
}
...
}
Where navigationRuleName is registered in the faces-config.xml:
<navigation-rule>
<from-view-id>/path/source.xhtml</from-view-id>
<navigation-case>
<from-outcome>navigationRuleName</from-outcome>
<to-view-id>/path/targetPageName.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
Or it can be a page name:
#Named
#RequestScoped
public class MyBean
{
public String actionHandler()
{
...
return "/path/targetPageName.xhtml?faces-redirect=true";
}
...
}
Or the xhtml extension can be omitted.
The '' entity or the faces-redirect=true parameter necessary if you want the location URL of the browser changing to targetPageName.xhtml after the HTTP POST request-response navigation. Redirection do it by another HTTP GET call after the HTTP POST one.
Related
I would like to prevent Server-Side Blazor from firing the OnSubmit event handler (that I can't get rid of for some other reasons) of the EditForm when I hit Enter in the input field. It seems to be an easy task, and I just can't solve it.
I made up the smallest example I could think of:
_Index.razor:
#page "/"
#inject IJSRuntime JSRuntime;
<EditForm Model="Model" OnSubmit="HandleOnSubmit">
<input id="testInput"/>
<button type="submit" value="unneeded submit button"></button>
</EditForm>
#code
{
private CModel Model { get; set; } = new CModel() { ID = "ID", Name = "Name" };
private async Task HandleOnSubmit()
{
await JSRuntime.InvokeAsync<object>("alert", new object[] { "This alert shouldn't be shown!!" });
}
}
the CModel class (although it has no relevance to the question):
public class CModel
{
public string ID { get; set; }
public string Name { get; set; }
}
and the _Host.cshtml:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PreventSubmitOnForm</title>
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
</head>
<body>
<app>
<component type="typeof(App)" render-mode="ServerPrerendered" />
</app>
<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
Reload
<a class="dismiss">đź—™</a>
</div>
<script src="_framework/blazor.server.js"></script>
<script>
document.getElementById("testInput").addEventListener('keypress', function (event) {
if (event.which === 13) {
event.preventDefault();
alert('Form submit prevented');
}
});
</script>
</body>
</html>
In the _Host.cshtml I register a new keypress eventhandler, and as I debug, on page creation it will be really registered. But it never will be triggered on keypress Enter.
And I already have tried to trick the situation with #onkeypress:preventDefault and #onkeypress:stopPropagation but they don't seem to help (as Steve Sanderson declared in his issue comment) when I want to prevent the default behavior only for my input field and in that specific field only for the event: Enter pressed.
In a normal HTML + JS case it works like a charm: https://jsfiddle.net/wmk608gh/1/
So I ended up by the JS Interop solution and added the script
<script>
document.getElementById("testInput").addEventListener('keypress', function (event) {
if (event.which === 13) {
event.preventDefault();
alert('Form submit prevented');
}
});
</script>
to the _Host.cshtml.
But yet it doesn't seem to work. I presume I'm supposed to register my script to another event (instead of keypress), or maybe there is already a best practice I could follow here.
Any help appreciated.
The problem is that you try to add the EventListener at a time where your <input /> element is not rendered yet.
To make this work you can call your JS function after blazor has rendered your page:
In your _Index.razor #code block add:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSRuntime.InvokeVoidAsync("PreventDefault");
}
}
In _Host.cshtml wrap your addEventListener with a function:
<script>
function PreventDefault() {
document.getElementById("testInput").addEventListener('keypress', function (event) {
if (event.which === 13) {
event.preventDefault();
alert('Form submit prevented');
}
});
}
</script>
So I am integrating my angular application into a payment gateway, in certain instances there is an additional security check required by the payment processor. For anyone interested, its a 3D Secure implementation.
I can perform the post request no problem, but the value returned from my provider is simply....
<html>
<head>
<title>Redirecting...</title>
I was hoping it would return full html that I could just render in a modal, no such luck.
So I tried to create an iframe to post into and handle this (like the old school days) but I can't get this to work. My code so far...
Component
export class CheckoutComponent implements OnInit {
#ViewChild('form') postForm: ElementRef;
private MD: any;
private PaReq: any;
private TermUrl: any;
private demoEndpoint: any;
#ViewChild('threedsModal', { static: true }) private threedsModal;
constructor(
private http: HttpClient,
) { }
ngOnInit(): void {
this.demoEndpoint = 'www.example.com/post/'
this.MD = 'foo';
this.PaReq = 'bar';
this.TermUrl = 'www.myexample.com/response';
}
onLoad() {
console.log('onLoad triggered.');
}
// Called from another part of the code when we need to perform the POST
submitForm(){
// values are custom encoded, not needed to show for example
const myParams = new HttpParams({encoder: new HttpUrlEncodingCodec()})
.set('MD', this.MD)
.set('PaReq', this.PaReq)
.set('TermUrl', this.TermUrl);
this.http.post(this.demoEndpoint, myParams, {responseType: 'text'}).subscribe(x => console.log(x));
return true;
}
}
Then in my template:
<iframe class="custom-frame" #frame width="400" height="400" id="frame" name="frame"
frameborder="0" [src]="demoEndpoint | safeResourceUrl" (load)="onLoad()"></iframe>
<form target="frame" action="demoEndpoint| safeResourceUrl" #form method="POST">
<input type="hidden" name="MD" value={{MD}} id="MD" />
<input type="hidden" name="PaReq" value={{PaReq}} id="PaReq" />
<input type="hidden" name="TermUrl" value={{TermUrl}} id="TermUrl" />
</form>
But this iframe simply renders "Unable to determine the request"
If I perform the POST request manually in postman, in renders the correct HTML, but the response from my httpPOST in console just shows Re-directing.
So my question, how can I achieve this in an iframe and render the correct response?
EDIT: This question helped me somewhat
So for the help of anyone in the future, this was fairly easy with the help of this answer
// create a form for the post request
const form = window.document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', 'http://post.example.com');
// use _self to redirect in same tab, _blank to open in new tab
// form.setAttribute('target', '_blank');
form.setAttribute('target', 'threedframe');
// Add all the data to be posted as Hidden elements
form.appendChild(this.createHiddenElement('MD', 'foo'));
form.appendChild(this.createHiddenElement('PaReq', 'bar'));
form.appendChild(this.createHiddenElement('TermUrl','https://dump.example.com'));
console.log(form);
window.document.body.appendChild(form);
form.submit();
// create the form
private createHiddenElement(name: string, value: string): HTMLInputElement {
const hiddenField = document.createElement('input');
hiddenField.setAttribute('name', name);
hiddenField.setAttribute('value', value);
hiddenField.setAttribute('type', 'hidden');
return hiddenField;
}
Then setup an iframe in my template:
<iframe class="custom-frame" id="three-d-frame" width="430" height="450" frameborder="0" name="threedframe">
I am surprised to see that the event valueChange does not trigger when the value of an inputText is changed by a javascript method.
However, it triggers when I manually change the value of the inputText.
You can test the code below to sense this, and maybe you can give a solution to make the event to trigger when a javascript function changes the value of a component.
The xhtml page:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
>
<body>
<script type="text/javascript">
function testValueChange() {
console.log("testValueChange called");
var inputHCodes = document.getElementById('form:inptHCodes');
inputHCodes.value = "new value";
}
</script>
<h:form>
<p:commandButton type="button" value="BUTTON" onclick="testValueChange();"/>
<h:inputText id="inptHCodes" value="#{questionnaireExtendedKeyAttribute.selectedInputCodes}">
<p:ajax event="valueChange" listener="#{questionnaireExtendedKeyAttribute.testValueChangeListener}"/>
</h:inputText>
</h:form>
</body>
</html>
The listener in backing bean:
public void testValueChangeListener(AjaxBehaviorEvent abe) {
UIInput uiinput = (UIInput) abe.getSource();
String id = uiinput.getId();
selectedInputCodes = uiinput.getValue().toString();
logger.debug("### value : " + selectedInputCodes + " and id is: " + id);
}
I am trying to create an interactive chat web application using Java EE 7, in particular using JSF 2.2 with ajax.
The idea is that there is always one slow pending asynchronous ajax request waiting
on the server for each individual client. Once a new message arrives to the server,
all waiting requests are returned so that the messages are rendered in all clients.
On completion of the requests, new waiting requests are sent by the clients.
If no message arrives within 30 seconds, the request is returned so that a new one
can be submitted before the old one times out.
I could make it work like this:
index.xhtml:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>async jsf app</title>
<h:outputScript library="js" name="resendscript.js" />
</h:head>
<h:body>
async jsf app
<h:form id="jsfappform">
say something:
<h:inputText id="newmsg" value="#{jsfAsync.newMessage}" />
<h:commandButton id="sendbut" value="say" action="#{jsfAsync.say}" />
<br /><br />
Messages:
<br /><br />
<h:outputText id="msgs" value="#{jsfAsync.msgs}" escape="false">
<h:outputScript>resendRequest()</h:outputScript>
</h:outputText>
<h:commandButton id="reloadbut" value="" action="#{jsfAsync.resend}" style="visibility: hidden">
<f:ajax execute="#this" render="msgs" onevent="handleAjax" onerror="handleError" />
</h:commandButton>
<h:commandButton id="clearbut" value="clear" action="#{jsfAsync.clear}" />
<h:outputScript>resendRequest()</h:outputScript>
</h:form>
</h:body>
</html>
resendscript.js:
function handleAjax(data)
{
var status = data.status;
switch(status)
{
case "success": resendRequest();
break;
}
}
function handleError(data) { }
function resendRequest()
{
document.getElementById("jsfappform:reloadbut").click();
}
backing bean JsfAsync.java:
package jsfasync;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ApplicationScoped;
#ManagedBean
#ApplicationScoped
public class JsfAsync
{
private final List<String> messages;
private final Object wakeup;
public JsfAsync()
{
wakeup = new Object();
messages = new ArrayList<String>();
}
public void setNewMessage(String msg)
{
synchronized(messages) { messages.add(msg); }
}
public void say()
{
synchronized(wakeup) { wakeup.notifyAll(); }
}
public void resend()
{
try {
synchronized(wakeup) { wakeup.wait(30000); }
} catch (Exception e) { }
}
public void clear()
{
synchronized(messages) { messages.clear(); }
say();
}
public String getNewMessage() { return ""; }
public String getMsgs()
{
StringBuilder msgs = new StringBuilder();
synchronized(messages)
{
for (String m : messages)
{
msgs.append(m);
msgs.append("<br />");
}
return msgs.toString();
}
}
}
I would like to replace the body of the resendRequest() javascript function with the ajax request API as follows:
jsf.ajax.request('jsfappform:reloadbut', null,
{'javax.faces.behavior.event': 'action',
'execute': 'jsfappform:reloadbut',
'render': 'jsfappform:msgs',
'onevent': 'handleAjax',
'onerror': 'handleError'});
Unfortunately, I can't get it work this way. The call can perform the ajax request, but it seems the onevent option was ignored, and the event handler was not called when this request completed. Do you, perhaps, have any hints how to make it work in this way?
For hints, check the generated HTML source of <h:commandButton id="reloadbut">. You'll see that JSF has generated it as 'onevent': handleAjax. Indeed, as function reference instead of as a string.
Fix it accordingly:
jsf.ajax.request('jsfappform:reloadbut', null,
{'javax.faces.behavior.event': 'action',
'execute': 'jsfappform:reloadbut',
'render': 'jsfappform:msgs',
'onevent': handleAjax,
'onerror': handleError});
I’m having trouble getting JSON results working with Struts 2.2.1.1.
Does anyone have a simple working example that returns a JSON result to a JSP using Struts 2.2.1.1 and is ready to run in Eclipse as a dynamic web project?
Please include the struts.xml, action class and JSP code. Also, note dependencies. Thank you.
Here’s how to create a simple JSON example using the Struts 2 jQuery plugin.
Go to Struts2 jQuery Plugin Showcase
Navigate to Ajax Forms > Buttonset / Checkboxes
Review the code for Buttonset that was populated from AJAX JSON Result. This is code I selected to create a simple example.
Create dynamic web project in Eclipse
Create a Java package and name it test.
Download the Struts 2 jQuery plugin showcase source (struts2-jquery-showcase-x.x.x-sources.jar) and extract the JAR file.
Import Echo.java, JsonSample.java, and ListValue.java into the test package and move the code into the package with quick fix.
Change the class annotation in Echo.java and JsonSample.java to #ParentPackage(value = "test")
In addition to the standard Struts 2 libraries, ensure that the struts2-json-plugin-x.x.x.jar, struts2-jquery-plugin-x.x.x.jar, and struts2-convention-plugin-x.x.x.jar files are in your classpath.
Create a struts.xml file and add the following XML:
<struts>
<constant name="struts.devMode" value="true" />
<constant name="struts.convention.action.packages" value="test" />
<package name="test" extends="json-default” namespace="/">
</package>
</struts>
Create an index.jsp file and insert the following code:
<s:form id="form2" action="echo" theme="xhtml">
<s:url id="remoteurl" action="jsonsample" />
<sj:checkboxlist href="%{remoteurl}" id=“remoteCheckboxlist” name="echo" list="languageList" label="Language" />
<sj:submit targets="formResult" value="AJAX Submit" indicator=“indicator” button="true"/>
</s:form>
Run the example.
Must see : struts2-x.x.x-all.zip /apps/struts2-showcase-2.2.1.war
Struts 2 and JSON example
Struts 2 autocompleter + JSON example
It is very simple to get Json work with struts2.
For this,
you need to add struts-json plugin*(jsonplugin-0.32.jar)* to classpath.
Your struts.xml file should extends json-default
<package name="base" namespace="/" extends="json-default">
Your action result be like this.
<result type="json"><param name="root">jsonData</param></result>
Inside action class, declare json as
private LinkedHashMap<K, V> jsonData new LinkedHashMap<k, V>();
and then add the result list to json like
jsonData.put("result", anyList or object);
Thats all we have to do. Then we can access the result using javascript.
Try this, will help you in Struts 2.0.14 with jsonplugin-0.32.jar.
struts.xml:
<struts>
<package name="example" extends="json-default">
<action name="HelloWorld" class="example.HelloWorld" >
<result type="json" />
</action>
<action name="HelloWorld1" class="example.HelloWorld" >
<result name="success" >example/HelloWorld.jsp</result>
</action>
</package>
</struts>
action class Helloworld.java:
package prabhakar;
import glb.DB;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Prabhakar
*/
public class HelloWorld {
private List<StateMaster> stateList= new ArrayList<StateMaster>();
private List<RegnMaster> regnList= new ArrayList<StateMaster>();
private Integer stateId;
public Integer getStateId()
{
return this.stateId;
}
public void setStateId(Integer stateId)
{
this.stateId=stateId;
}
public List<StateMaster> getStateList() {
return stateList;
}
public void setStateList(List<StateMaster> stateList) {
this.stateList = stateList;
}
public void setRegnList(List<RegnMaster> regnList) {
this.regnList = regnList;
}
public List<RegnMaster> getRegnList() {
return regnList;
}
public String execute() throws Exception {
stateList=DB.getStateData()//
if(stateId !=null)
{
regnList=DB.getRegnByStateId(stateId);
}
//setMessage(getText(MESSAGE));
return "success";
}
/**
* Provide default valuie for Message property.
*/
}
You can directly call HelloWorld.action to view the JSON data or else you can bind the JSON data to a form element below.
JSP page HelloWorld.jsp:
/*
Prabhakar
*/
<%# page contentType="text/html; charset=UTF-8" %>
<%# taglib prefix="s" uri="/struts-tags" %>
<script>
<%#include file="../js/jquery-1.7.1.min.js"%>
</script>
<html>
<!-- JavaScript Plugins -->
<script>
function getLoad(){
var stateId = $('#state').val();
$.getJSON('HelloWorld.action', {'stateId': stateId},
function(data) {
var divisionList = (data.regnList);
var options = $("#regn");
options.find('option')
.remove()
.end();
options.append($("<option />").val("-1").text("--Select--"));
$.each(divisionList, function() {
options.append($("<option />").val(this.regnId).text(this.regnName));
});
}
);}
</script>
<!-- jQuery-UI Dependent Scripts -->
<body>
State List <s:select name="stateId" list="stateList" id="state" listKey="stateId" onchange="getLoad()" listValue="stateName" headerKey="0" headerValue="--select--" />
Regn List <s:select name="regnId" list="regnList" listKey="regnId" id="regn" listValue="regnName" headerKey="0" headerValue="--select--" />
</body>
</html>
Happy coding :)