Wicket AjaxSubmitLink onSubmit is not called after applying appendJavascript which changes the DOM of a page. Sample code is:
add(new ListView("list", someArrayList){
#Override
protected void populateItem(final ListItem item) {
add(new AjaxSubmitLink("link") {
#Override
public void onClick(AjaxRequestTarget target) {
target.appendJavascript("swap('"+this.getMarkupId()+"')");
});
})
The JavaScript looks like:
function swap(markupId){
var one = $('.dashed').first().parent();
var two = $('#'+markupId).parent();
var tone = one.clone();
var ttwo = two.clone();
one.replaceWith(ttwo);
two.replaceWith(tone);
}
Any suggestions?
It might be the clone() method causing the problem. According the documentation it does not clone event handlers. Try clone(true);
You could also handle the swap server side and then rerender the list after the swap. That would be the Wicket way to do it.
Related
I have this behavior added to a component(MarkupContainer)
AjaxSelfUpdatingTimerBehavior updateBehavior = new AjaxSelfUpdatingTimerBehavior(Duration.seconds(3))
{
#Override
public void onEvent(Component component, IEvent<?> event) {
// some business logic
}
};
Somewhere , on the same page I have an AjaxLink which redirects to another page(in whom constructor I pass the actual page as a parameter) and on that page I have a "Back" AjaxLink which redirects me back , calling setResponsePage(myFirstPage) .
The problem is that even though , when rendering the page the behavior updates once , it stops updating once at 3 seconds , as was constructed for.No problem faced with the behavior until leaving the page.
Probably not the best solution , but I managed to fix it by removing the behavior onBeforeRender() of the page and adding again . I declared a field on the page private int autoUpdateBehaviorId = -1;
public void addUpdateBehavior(Component c)
{
if(autoUpdateBehaviorId >= 0)
c.remove(c.getBehaviorById(autoUpdateBehaviorId));
AjaxSelfUpdatingTimerBehavior updateBehavior = new AjaxSelfUpdatingTimerBehavior(Duration.seconds(3))
{
#Override
public void onEvent(Component component, IEvent<?> event) {
// bussines logic
}
};
c.add(updateBehavior);
autoUpdateBehaviorId = c.getBehaviorId(updateBehavior);
}
#Override
protected void onBeforeRender() {
super.onBeforeRender();
addUpdateBehavior(myContainer);
}
Not necessarily the solution to your problem; but I have implemented the behavior by overriding onConfigure method of the AjaxSelfUpdatingTimerBehavior as below.
In my case, I had to update label with a count of current records in queue every 10 seconds.
Following is code snippet:
labelToBeUpdated.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(configurableDelay)) {
#Override
public void onConfigure(Component component) {
String inProgressOutOfTotal = "10/100"; //Business logic to get total count and inprogress count
labelToBeUpdated.setDefaultModel(Model.of(inProgressOutOfTotal));
//Set visibility of the component if needed
}
}
labelToBeUpdated.setOutputMarkupId(true);
Just curious; is it that onEvent is waiting on an event on the component in order to refresh? Since onConfigure is called before the rendering cycle has begun, it is working for me.
But as Sven Meier has mentioned, you might still want to work on his advise to get your code with onEvent.
I want to print one panel of page in GWT.
However someone said that you must use iframe because it has print method.
I tried this code but it does not work:
HTML html=new HTML("<iframe id="myframe"></iframe>") ;....
searchButton.setWidth("80px");
searchButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
MyNative.printIframeContent("myframe", "onlineMap");
}
});
map = new SimplePanel();
map.getElement().setId("onlineMap");
map.add(mapView.getMapWidget());
mapView .is an instance of a class that returns a GWT MapWidget and in this manner I want to add GWT map to iframe then use print capability of iframe to print google map
MyNative is a class that use GWT JSNI to call the printPage javascript function
function printPage(idMap,idFrame) {
var myElement = document.getElementById(idMap);
var iframe = document.getElementById(idFrame);
var body = iframe.getElementsByTagName('body');
body.innerHTML = myElement;
iframe.contentWindow.print();
}
but browser can not load body of iframe.
You can try this:
String html = myPanel.getElement().getInnerHTML();
print(html);
public static final native void print(String html) /*-{
top.consoleRef=$wnd.open('','_blank', "");
top.consoleRef.document.write(html);
top.consoleRef.print();
top.consoleRef.document.close()
}-*/;
I'm wondering if what should be done for GWT com.google.gwt.user.client.ui.FileUpload
to upload to server without refresh or forwarding.
I have implemented the Form upload from this Java Doc, however it forwards the browser page to the target server URL.
How can I implement a form upload without forwarding?
Update:
final FormPanel form = new FormPanel();
form.setAction("/upload");
form.setEncoding(FormPanel.ENCODING_MULTIPART);
form.setMethod(FormPanel.METHOD_POST);
VerticalPanel panel = new VerticalPanel();
form.setWidget(panel);
final TextBox tb = new TextBox();
tb.setName("textBoxFormElement");
panel.add(tb);
// Create a FileUpload widget.
FileUpload upload = new FileUpload();
upload.setName("uploadFormElement");
panel.add(upload);
DOM.getElementById("form_panel").appendChild(panel.getElement());
Button submit = new Button("Submit");
panel.add(submit);
DOM.sinkEvents(submit.getElement(), Event.ONCLICK);
DOM.setEventListener(submit.getElement(), new EventListener(){
#Override
public void onBrowserEvent(Event event) {
if (event.getTypeInt() == Event.ONCLICK) {
form.submit();
return;
}
}});
form.addSubmitHandler(new FormPanel.SubmitHandler() {
public void onSubmit(SubmitEvent event) {
if (tb.getText().length() == 0) {
Window.alert("The text box must not be empty");
event.cancel();
}
}
});
form.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {
public void onSubmitComplete(SubmitCompleteEvent event) {
Window.alert(event.getResults());
}
});
IMO you are making things more complex than they are.
I don't understand why, if you are using widgets, you are trying to manage the DOM by hand.
1.- Attach your form panel to the root panel using GWT way, otherwise you are going to break widget hierarchy.
RootPanel.get("form_panel").add(panel);
2.- Try not to use sink-events by hand, and use methods already present in widgets:
submit.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
form.submit();
}
});
FormPanel sets its target to a hidden <iframe> so you will never be redirected to another page.
BTW, I'd rather use gwtupload library which simplifies so much uploading code in GWT, and adds a lot of additional features.
I used before gwt-upload library.
You dont need to rediscover America.
Thanks for moxie group
gwt-upload-project page
I have:
ListView
Button
WebMarkupContainer (Popup content container)
So, when I populate the ListView, I add an AjaxEventBehavior to the buttons. I also override getAjaxCallDecorator(), as I need to call a javascript function from each button. So, in the decorateScript function, I override the WebMarkupContainer markup id by using setMarkupId(), it works. I do the same for the Button, and it works, at least when I call getMarkupId(). But when I go to the generated HTML, it's not there! Why is this happening?
The code is the following (it is inside of the populateItem from ListView):
infoBtn.add(new AjaxEventBehavior("onclick") {
#Override
protected void onEvent(AjaxRequestTarget target) {
}
#Override
protected IAjaxCallDecorator getAjaxCallDecorator() {
return new IAjaxCallDecorator() {
#Override
public CharSequence decorateScript(Component component, CharSequence script) {
StringBuilder jsScript = new StringBuilder();
infoPopoverContent.setMarkupId(infoPopoverContent.getMarkupId(true) + String.valueOf(pos));
infoBtn.setOutputMarkupPlaceholderTag(true);
infoBtn.setMarkupId(infoBtn.getMarkupId() + String.valueOf(pos));
jsScript.append("$('#" + infoBtn.getMarkupId() + "').popover({");
jsScript.append("html:true,");
jsScript.append("placement:'bottom',");
jsScript.append("content:function() {");
jsScript.append("return $('#");
jsScript.append(infoPopoverContent.getMarkupId());
jsScript.append("').html();");
jsScript.append("}");
jsScript.append("});");
logger.debug(jsScript.toString());
pos++;
return jsScript;
}
#Override
public CharSequence decorateOnSuccessScript(Component component,
CharSequence script) {
// TODO Auto-generated method stub
return null;
}
#Override
public CharSequence decorateOnFailureScript(Component component,
CharSequence script) {
// TODO Auto-generated method stub
return null;
}
};
}
});
Make sure you're calling infoBtn.setOutputMarkupId(true), so that Wicket knows it should be outputting the id attribute.
Notice setOutputMarkupPlaceholderTag(true) is also calling setOutputMarkupId(true) behind the scenes. Without knowing much about your code, it looks like you don't really need it. setOutputMarkupPlaceholderTag() will output an emtpy container (<span id="xxx"> in case the component is not visible, just to have a reference to the place the component belgons to, and allowing Wicket for manipulation via DOM in the AJAX response (for example, to make the component visible again).
As a side note, if you don't really need the id attributes to have a specific value, you can simplify your code by not using setMarkupId() and letting Wicket generate ids for you.
Also, it might be simpler to drop the IAjaxCallDecorator and just append the script in onEvent by means of AjaxRequestTarget#appendJavascript() or AjaxRequestTarget#prependJavascript(), depending on your needs.
I have a ContentProvider for a Tree view. There I add some actions that can be performed on an item of the tree. The method looks like this:
private void makeActions() {
action1 = new Action() {
#Override
public void runWithEvent(Event event) {
System.out.println(event);
System.out.println(event.data.getClass());
//How can I find the caller of runWithEvent?
}
};
How can I find the object of the tree that has caused the call of Action#runWithEvent?
Consider using the new Command API instead of the older Action API. In the new API, you can easily access the relevant information in the handler for the command.