I have a page on which I show a list of objects which are loaded from a webservice. This may take a while.
Now I'd like to do it the Ajax way and first show the page and then load the list. While the list is loading a animated should be shown.
Can anybody give me an example how to do that with JSF/ICEFaces? Thanks.
It would be better to use the SessionRenderer. Have a look at my ICEfaces book examples (http://icecube-on-icefusion.googlecode.com/) and search for the progressDialog tag for an example. Or page 244ff in the book.
Ok, solved it myself.
Here's how I'm doing it:
in the Managed Bean's constructor I'm calling a method which creates and starts a new thread. This thread loads the objects. As soon as the objects are there the 'loading' flag of my bean is set to false and
PersistentFacesState.getInstance().renderLater();
is called. 'loading' is initially set to false.
That's the method for loading the objects in async mode:
private void asyncLoading() {
final MyBackingBean bean = this;
final String userName = CallerContextUtil.getCurrentUserCompany();
new Thread() {
#Override
public void run() {
bean.setLoading(true);
PersistentFacesState.getInstance().renderLater();
load(userName );
bean.setLoading(false);
PersistentFacesState.getInstance().renderLater();
}
}.start();
}
On the view I'm showing or hiding an animated loading images on the state of the loading flag.
I don't know if that is the best or even a good solution. Comments are welcome.
It is strongly discouraged to create new threads in a J2EE server. It's server's job to manage threads.
You can ask for the submission of an icefaces form using ajax when your page is loaded, that should do the trick.
i think i have answer for this question, because i have the same trouble about ajax style loading..
after lurking in many sites and icefaces forum, i have this code, without using thread:
first you have to download jquery, and then the code is like this:
<script type="text/javascript" src="js/jquery-1.6.min.js"/>
<script type="text/javascript">
var j = jQuery.noConflict();
j(document).ready(function(){
j(".wrapper-popup-loading").hide();
});
function icesubmitlocal() {
var windowWidth = document.documentElement.clientWidth;
var windowHeight = document.documentElement.clientHeight;
var popupHeight = j(".wrapper-popup-loading").height();
var popupWidth = j(".wrapper-popup-loading").width();
j(".wrapper-popup-loading").css({
"position": "absolute",
"top": windowHeight/2-popupHeight/2,
"left": windowWidth/2-popupWidth/2
}).show();
j(".wrapper-popup-white").show();
}
function icereceivelocal() {
j(".wrapper-popup-loading").hide();
j(".wrapper-popup-white").hide();
}
function init() {
Ice.onSendReceive('document:body',icesubmitlocal,icereceivelocal);
}
</script>
<body onload="init()" id="outputBody1" style="-rave-layout: grid">
the basic idea is simple, every ajax call you just have to show the popup div, and every you receive confirmation from icefaces js, you just have to hide the popup,
the popup panel is like this:
<div class="wrapper-popup-loading"><!-- start wrapper -->
<div class="wrapper-popup-white"><!-- start wrapper -->
<center>
<img src="images/aed-popup.png" alt="" style="margin-top: 5px;"/>
<br />
<img src="images/aed-garuda.gif" alt="" style="margin-top: 5px;"/>
</center>
</div>
</div><!-- end footer -->
then, everytime ajax request on, your popup is show, and if ajax stop, your popup is hide..
hope this help..thanks
Related
I would like to trigger Spring MVC controller method from Thymeleaf view without returning anything from the method and without refreshing the page.
I have the following HTML page:
<!-- 'block item' button code-->
<div class="row">
<form method="get" th:action="#{'/items/block/' + ${item.itemId}}">
<button type="submit" class="btn btn-warning">block item</button>
</form>
</div>
The related controller looks as:
#GetMapping("/items/block/{itemId}")
#ResponseStatus(value = HttpStatus.OK)
public void blockItem(#PathVariable String itemId) {
itemService.blockItem(itemId);
}
The itemService.blockItem(itemId) call just changes the corresponding boolean attribute of the related item object in database.
Currently every time when I trigger this method by pressing block item button I am being redirected to the URL like http://localhost:8080/item/block/7C4A3744375523.
I would like not to do any redirection but just execute the related service method logic. I also need to remove the related item div from the view but this I can do pretty straightforward with JavaScript.
How can I do it? Thanks.
Your button is defined as type submit.
As a consequence, when you click it the form is submitted.
To prevent that default behavior you need several things: the main idea is to define a handler for your form submit event and use Javascript to perform the actual server invocation.
You can do it in different ways, although I think it is preferable to use an event handler to define the desired behavior and separate your HTML code from Javascript as much as possible.
In addition, you seem to be iterating over a list of items.
With those two things in mind consider the following code snippet:
<script>
// We use the DOMContentLoaded event (https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event)
// but please, register the form event as you consider appropriate
document.addEventListener('DOMContentLoaded', () => {
// Register form submit event handler for every form in your page
const forms = document.querySelectorAll('form');
if (forms) {
forms.forEach(f => {
let action = f.action;
f.addEventListener('submit', (event) => {
// prevent default behavior, i.e., form submission
event.preventDefault();
// perform server side request. you can use several options
// see https://developers.google.com/web/updates/2015/03/introduction-to-fetch, for instance
// For example, let's use fetch (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
fetch(action)
.then((response) => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
console.log('Request successfully completed');
})
.catch((error) => {
console.error('There has been a problem while contacting server:', error);
});
});
});
}
});
</script>
In fact, you can get rid of the forms. Please, consider a slightly different approach. First, when iterating over your items, generate the following HTML blocks (you can use a data or any custom attribute to store the current processed item id if you prefer to):
<!-- 'block item' button code-->
<div class="row">
<button type="button" class="btn btn-warning item-button" th:id="${item.itemId}">block item</button>
</div>
Now, in a similar way as described above, register handlers for every item button:
<script th:inline="javascript">
document.addEventListener('DOMContentLoaded', () => {
// Register handlers for every button
const buttons = document.querySelectorAll('.item-button');
if (buttons) {
buttons.forEach(b => {
b.addEventListener('click', (event) => {
let itemId = b.getAttribute('id');
let link = /*[[#{/items/block/}]]*/ 'link';
// Perform server side request
fetch(link + itemId)
.then((response) => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
console.log('Request successfully completed');
})
.catch((error) => {
console.error('There has been a problem while contacting server:', error);
});
});
}
}
});
</script>
It's not a Thymeleaf or Spring MVC that causes redirection but submit button in your form tag. You need to overwrite the behaviour of this button to send the form data through Ajax and handle the response by yourself (basically - ignore it) - e.g. using jQuery it could look like:
<!-- 'block item' button code-->
<div class="row">
<form id="someFormId" method="get" th:action="#{'/items/block/' + ${item.itemId}}">
<button type="submit" class="btn btn-warning">block item</button>
</form>
</div>
//...
$('#someFormId').submit(function(e) {
e.preventDefault();
$.ajax({
type: 'GET',
url: '#{'/items/block/' + ${item.itemId}}',
data: $(this).serialize(),
// here you can define some actions for beforeSend, success, etc...
// for example to just ignore:
success: function(){}
});
})
There are many ideas to solve this issue. Please read e.g.
Prevent redirect after form is submitted
Don't redirect on submitting form
How to submit an HTML form without redirection
The form is being submitted twice:
1. On Page Load
2. When user clicks on Checkout's button
I want to avoid the first submission, it is throwing an error because the token returned is null:
com.stripe.exception.InvalidRequestException: Invalid source object: must be a dictionary or a non-empty string. See API docs at https://stripe.com/docs'; request-id: req_DjRbT4rGULYGnB
Following the documentation I added the following code to my XHTML:
<div>
<form submit="#{studentBean.chargeStudent()}" method="POST">
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="pk_test_xxxxxx"
data-amount="111"
data-name="myApp"
data-description="Example charge"
data-zip-code="true"
data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
data-locale="auto">
</script>
</form>
</div>
Here is my Managed Bean's function:
#Named
#ViewScoped
public class StudentBean implements Serializable {
#EJB
StripeChargeLogic stripeChargeLogic;
public void chargeStudent(){
Map<String,String> requestParams = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
logger.info("charge:" + requestParams.get("stripeToken"));
stripeChargeLogic.chargeStudent(requestParams.get("stripeToken"));
}
}
Can someone please guide me why the form is being submitted twice and how I can prevent the submission during page load Thank you!
You are not doing jsf here, you have plain html, most likely (but mot clear from you post) in an xhtml/facelets file but not JSF.
In your form action you have an EL that, since it all is in no way related to jsf, is called on page load, sort of like what hapens here
The rest of the behaviour is even more 'undefined' because of this. Take a step back and learn the basics of web technology and jsf and then look at your problem again
I'm currently trying to create a toggle that when pressed reloads the page with the opposite of the current boolean value.
<s:url action="mainMenuLabelToggle" var="mainMenuToggle"></s:url>
<a href="${mainMenuToggle}" onclick="<s:set var ="LabelToggle" value
="!#session.LabelToggle" scope="session"/>"> view without labels </a>
<br>
This is the current solution that I've tried, but unfortunately it doesn't work. It seems to run the variable declaration on every page load, rather than onclick, due to the JSP portion being compiled first I think. Are there any other possible solutions? Thanks for the help!
onclick="toggleLabel();"
<script type="text/javascript">
function toggleLabel(){
$.ajax("<s:url action='mainMenuLabelToggle'/>");
document.location.reload(true);
}
</script>
In the action class
boolean labelToggle = session.get("labelToggle");
session.put(!labelToggle);
I am trying to call a method in a Java applet from JS. I am a little bit confused about how to arrange my workflow. I have a jsp (pending.jsp) class which includes a javascript (pending.js). pending.jsp is just a container to hold pending.js. pending.js' purpose is to enable users to cancel report creation.
pending.jsp:
<div id="pending-reports-container" class="pending-reports-container">
<div id="pending-reports">
</div>
</div>
pending.js:
function update_pending_reports(response_data)
{ bla }
function delete_report(report_id)
{ bla }
function request_pending_reports()
{ bla }
function start_pending_reports() {
request_pending_reports();
setInterval("request_pending_reports()", 5000);
}
Because cancelling reports sometimes is not that efficient I want to use Java to cancel requests that goes to the postgres (pending.js does not kill the process that works at postgres). I created my Java class but I don't know where to add it. I know I can make use of tag, but when I tried to add this tag to my jsp file like this:
<div id="pending-reports-container" class="pending-reports-container">
<div id="pending-reports">
<applet id="LS" width=1 height=1 code ="module/LicenseCheckService.class" codebase="."/>
</div>
</div>
I can not reach it from my pending.js with this code:
getJS = document.getElementById("LS");
Is there something wrong with my code or am I wrong at this structure in the first place?
See the Invoking Applet Methods From JavaScript Code Oracle docs.
Nutshell version is that the JavaScript refers to the applet object by the applet ID, and can call methods on it.
appletId.anAppletMethod();
var anAppletClass = appletId.getAnAppletClass();
anAppletClass.methodCalled("with a JavaScript string parameter");
// Etc.
See Dave Newton's answer.
Alternatively, you can also check the HTML field or call a javascript method from Applet. You can construct the interaction to be actively controlled by the applet.
Link here : Java Applet To JS Link
I am trying to create a form for my company's website. I am letting a customer selectively donate to my company upon download of a piece of software. If they check a box, I'd like a "Donate" button to appear with code to go to my third party store (I know how to do this), and if they don't select the checkbox, then I'd like a different button to appear that will link them to the download of the software (I also can do this).
I would prefer to stick to PHP, Javascript, and HTML. I do not have immediate access to anything like asp.net.
Thanks!
Yes. Just toggle the value of button.style.display between 'none' and '' with JavaScript.
<input id="my_check_box" type="checkbox" onclick="handleCheckChange()" onchange="handleCheckChange()" />
<input id="my_donate_button" type="submit" style="display: none" value="Donate now!" />
<script type="text/javascript">
function handleCheckChange() {
var my_donate_button = document.getElementById("my_donate_button");
if (document.getElementById("my_check_box").checked) {
my_donate_button.style.display = '';
} else {
my_donate_button.style.display = 'none';
}
}
// Browsers may pre-check the box if the user re-loads the page,
// so call this to make sure the page is consistent.
handleCheckChange();
</script>
ya u can do it..
create a javascript function named like
function check_button()
{
if(document.getElementById('checkbox_id').value=="checkbox_value")
{
document.getElementById('button_id').style.display="block";
}
else
{
document.getElementById('button_id').style.display="none";
}
}
call this function in checkbox html code