How to add back the "loading" Element after removed it from Parent? - gwt

Ok, in war/MyProject.html, I have:
<body>
<div id="loading">
<div id="waitingForLoading"></div>
<BR/>
<img src="../images/loading.gif" />
</div>
...
</body>
in MyProject.java
public class OfflineMatching implements EntryPoint {
#Override
public void onModuleLoad() {
// this code works fine
if(DOM.getElementById("loading")!=null){
DOM.getElementById("loading").removeFromParent();
}
Button myButton=new Button("Enter Main Page");
RootPanel.get().add(myButton);
myButton.addClickHandler(new ClickHandler(){
#Override
public void onClick(ClickEvent event) {
// this code does not work
if(DOM.getElementById("loading")==null){
DOM.appendChild(RootPanel.getBodyElement(), DOM.createElement("loading"));
}
}
});
}
}
So, did i do anything wrong?
Why this code does not work?
// this code does not work
if(DOM.getElementById("loading")==null){
DOM.appendChild(RootPanel.getBodyElement(), DOM.createElement("loading"));
}

DOM.createElement(String tagName) creates a <tagname> element. So, if you pass "loading" to it, it will create a <loading> element.
For a quick workaround, you can use RootPanel.get, and then call setVisible on the widget:
// onModuleLoad:
RootPanel.get("loading").setVisible(false);
// onClick:
RootPanel.get("loading").setVisible(true);
But a better approach would be creating the loading <div> as a widget in GWT and just call setVisible on its instance, without relying on ids.

Related

Wicket 7 Link/Label error when using inheritance

With Wicket 7, I am working on an app that uses a base page as a template for other pages to extend.
On the base page, I want to have a label and a link that changes depending on whether the user is authenticated or not.
Here's my BasePage.html:
<div wicket:id="chromeMenu">foo</div>
<div>
<h2 wicket:id="userGreeting"></h2>
<h2><span wicket:id="loginLabel"></span> </h2>
</div>
<wicket:child/>
and the BasePage.java:
public BasePage() {
super();
add(new ChromeDropDownMenu("chromeMenu", buildMenu()));
add(new Label("pageTitle", new StringResourceModel("page.title", this, null)));
if(BasicAuthenticatedSession.get().isSignedIn()) {
// Do stuff here
} else {
add(new Label("userGreeting", "Hello Visitor"));
add(new Link("loginLink") {
#Override
public void onClick() {
setResponsePage(LoginPage.class);
}
});
add(new Label("loginLabel","Test"));
}
}
HomePage extends BasePage.
HomePage.html
<wicket:extend/>
HomePage.java
public class HomePage extends BasePage {
private static final long serialVersionUID = 1L;
public HomePage() {
super();
setPageTitle(new StringResourceModel("page.title", this, new Model<Serializable>("Admin")));
add(new Label("version", getApplication().getFrameworkSettings().getVersion()));
}
}
HomePage is the class returned by the Wicket application.
When I try to load HomePage, I get the following error:
Last cause: Unable to find component with id 'loginLabel' in [Link [Component id = loginLink]]
Expected: 'loginLink:loginLabel'.
Found with similar names: 'loginLabel'
It points to the <a><span/></a> structure from BasePage.html as the root of the problem.
I've tried a few ways to work around this, but without success. I thought maybe an add(Link).add(Label) might be needed, but that didn't work either.
Any thoughts out there on what I'm missing?
The error message says it all.
Last cause: Unable to find component with id 'loginLabel' in [Link
[Component id = loginLink]]
Expected: 'loginLink:loginLabel'.
Found with similar names: 'loginLabel'
Wicket is expecting the same component hierarchy in your Java code as you've written in the HTML. In BasePage.html you have:
<h2><span wicket:id="loginLabel"></span> </h2>
In the BasePage.java code you need to add loginLabel as a child of loginLink component.
Link loginLink = new Link("loginLink") {
#Override
public void onClick() {
setResponsePage(LoginPage.class);
}
};
add(loginLink);
loginLink.add(new Label("loginLabel", "Test"));
The problem is at
add(new Link("loginLink") {
#Override
public void onClick() {
setResponsePage(LoginPage.class);
}
});
add(new Label("loginLabel","Test"));
The Link should be the parent of the Label:
link = new Link("loginLink") {
#Override
public void onClick() {
setResponsePage(LoginPage.class);
}
};
link.add(new Label("loginLabel","Test"));
add(link);
Few extra notes:
better use BookmarkablePageLink if setResponsePage() is the only thing you need in onClick()
use AbstractLink#setBody(IModel label) instead of Link+Label

how to add script to the body (similar functionality like method renderHead(Component component, IHeaderResponse response))

With the following code, I add trackingpixel to some page page.html by overriding the method renderHead(Component component, IHeaderResponse response). This works fine.
page.html looks like this:
<!doctype html>
<html xmlns:wicket="http://wicket.apache.org/">
<head>
..
<wicket:container wicket:id="header"></wicket:container>
</head>
<body>
..
<script wicket:id="scriptHolder" type="text/javascript" > I would like to add my script here
</script>
..
</body>
</html>
TrackingPixel.java:
public abstract class TrackingPixel extends AbstractDefaultAjaxBehavior {
protected TrackingPixel(TrackingPixelType type) {
..
}
#Override
public void renderHead(Component component, IHeaderResponse response) {
response.renderOnDomReadyJavaScript("WebtrekkInstance = {
..
'path' : 'anyPath',
...:...
..
};
");
}
}
renderHead-method adds a trackingpixel to the main page. Right mouse click on the page -> source code shows that the following script is added to the page:
<script type="text/javascript" >
Wicket.Event.add(window, "domready", function(event) {
WebtrekkInstance = {
..
'path' : 'anyPath',
...:...
..
};
..
;});
</script>
Now I would like to add trackingpixel to a popup. My problem is that I can't add a script to the body. The method renderHead(Component component, IHeaderResponse response) doesn't do that, because (I guess) the popup pops up on the same page, so there is only one head and it will not render twice. So I tried to do this with WebMarkupContainer as you can see below.
OurServicePopup.java
/**
* Class to display our service as popup
*/
public class OurServicePopupPage<T> extends WebPage {
public OurServicePopupPage(PageParameters parameters) {
super(parameters);
}
#Override
protected void onInitialize() {
add(new OurServicePixel());
super.onInitialize();
}
}
OurServicePixel.java looks like this:
public class OurServicePopupPixel extends TrackingPixel{
public OurServicePopupPixel() {
}
WebMarkupContainer scriptContainer = new WebMarkupContainer("scriptContainer");
#Override
public void renderHead(Component component, IHeaderResponse response) {
scriptContainer.add(new AttributeAppender("type", Model.of("text/javascript")));
scriptContainer.add(
new AttributeAppender("src","WebtrekkInstance = {
..
'path' : 'anyPath',
...:...
..
};
");
}
add(scriptContainer); //this shows error
}
The problem here is that I cannot add the scriptContainer. add(scriptContainer); will not work, because OurServicePopupPixel is a behaviour and not a page.
Maybe you can simple use a Label component with setEscapeModelStrings(false). But it seems a bit strange.
I didn't full understand what is your javascript doing, but maybe you can try to execute it when the DOM is ready. Using a renderHead like this:
public void renderHead(IHeaderResponse response) {
response.render(OnDomReadyHeaderItem.forScript( ... YOUR SCRIPT HERE ... ));
}
I hope it helps.

Processing a ListView inside a form

Please consider the following signup:
<form wicket:id="form">
<div wicket:id="fooList">
<input wicket:id="fooList.quxField" type="text" size="10"/>
</div>
<button wicket:id="submit"><wicket:message key="submitText"/></button>
</form>
And these two classes (I am assuming setters, getters etc.)
class FooClazz {
String quxField;
}
class BarClazz {
List<FooClazz> fooList;
}
And this form (models are wrapped in CompoundPropertyModel):
class BarForm extends Form<BarClazz> {
public BarForm(String id,final IModel<BarClazz> model){
super(id,model);
add(new ListView<FooClazz>("fooList"){
#Override
protected void populateItem(final ListItem<FooClazz> item){
item.add(new TextField<String>("fooList.quxField"));
}
}
}
}
Now the above code is generating a runtime exception for me:
2011-12-11 16:33:46 ERROR [org.apache.wicket.DefaultExceptionMapper] Unexpected error occurred org.apache.wicket.WicketRuntimeException: The expression 'quxField' is neither an index nor is it a method or field for the list class java.util.ArrayList
I can change the TextField to include a Model like this:
item.add(new TextField<String>("fooList.quxField", new Model<String>(model.getObject().getFooList().getQuxField())));
This resolves the error, but when I submit the form (with an Ajaxbutton) I never get to see the values entered into the form fields.
So how can I keep the TextField models connected to my form model? Am I overlooking the obvious?
(This is of course just a very shortened version of my original code ...)
Need to add: all my models are wrapped in CompoundPropertyModels.
Thanks in advance for any tips how to fix this.
I found it. I need to include a model for the TextField that has implementations for both getObject() and of course setObject(). So I really was missing the obvious.
#Override
protected void populateItem(final ListItem<Taste> item) {
final TextField<String> quxField = new TextField<String>("tastes.quxField", new Model<String>() {
#Override
public String getObject() {
return item.getModel().getObject().getquxField();
}
#Override
public void setObject(final String value) {
item.getModel().getObject().setquxField(value);
}
});
item.add(quxField);
}

why this event (onclick) do not fire?

UI:
<div class="scroll" ui:field="mainContainer">
<ul ui:field="liContainer">
</ul>
</div>
code :
LIElement li = Document.get().createLIElement();
AnchorElement a = Document.get().createAnchorElement();
a.setAttribute("href", "#");
li.appendChild(a);
Image img = new Image(fsd.getImgUrl());
img.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert("Hello, again");
}
});
SpanElement span = Document.get().createSpanElement();
span.setInnerText(fsd.getName());
a.appendChild(img.getElement());
a.appendChild(span);
liContainer.appendChild(li);
Note:
#UiField
UListElement liContainer;
The Image must be added to a parent Widget. By attaching the image's element directly to the DOM, you wind up bypassing GWT`s event dispatch system.

GWT Button EventListener not fired

I have a <div id="test"><input type="button" value="OK" /></div> html tag.
I used:
((HasClickHandlers)RootPanel.get("test").getWidget(0)).addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert('sss');
}
}
I executed but no action.
Update:
package com.example.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.RootPanel;
public class ExampleWebApp implements EntryPoint {
public void onModuleLoad() {
((HasClickHandlers) RootPanel.get("test").getWidget(0)).addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert("i got it");
}
});
}
}
HTML:
<table>
<tr>
<div id="test">
<input type=button onClick="" value='click here'>
</div>
</tr>
</table>
The GWT Button widget is a button tag and not a input tag. Which means you can't use the GWT Button widget in this case. To make it work you need to create your own widget, which can be based on the widget ButtonBase, but needs to be initialized with an InputElement object instead of a ButtonElement.
The next step to get tag from html is to add something similar to the static wrap method present in most widgets. Here is how it would be used in your example when the input would have been a button tag:
Button.wrap(RootPanel.get("test").getWidget(0).getElement()).addClickHandler(
new ClickHandler() {
#Override public void onClick(ClickEvent event) {
Window.alert('sss');
}
});
In you case you could add a wrap method to your custom input widget. See the Button widget implementation of te wrap method, it's the same, expect of course for the creation of the widget itself.
You can't just take an html button and try to add click handlers to it. You need to create the button using gwt code. Try:
<div id="test"></div>
And then:
Button button = new Button("OK");
RootPanel.get("test").add(button);
button.addClickHandler(new ClickHandler() {...});