wicket download link clear feedback panel - wicket

I have couple of drop downdowns and a download link button. Based on the user selection, i get the file to be downloaded. if the user did not make a selection I show an error on the feedback panel. if the user then makes a selection and clicks on download link it works fine, but the previous feedback message is still visible. How do I clear it.
onclick of the download link, i tried the following, but no use
FeedbackMessages me = Session.get().getFeedbackMessages();
me.clear();

Probably it is
Session.get().cleanupFeedbackMessages()
even it has been changed in Wicket 6.x

I've found this post and I think it is time to share the way for Wicket 6.x and for Wicket 7.x, because Session.get().cleanupFeedbackMessages() was deprecated already.
To do it for Wicket 6.x you have to implement additional filter for the feedback panel. Where to do it, it is your decision to decide.
Create a new FeedbackPanel implementation by extending from the existing FeedBackPanel class
private class MessagesFeedbackPanel extends FeedbackPanel{
private MessageFilter filter = new MessageFilter();
public MessagesFeedbackPanel(String id){
super(id);
setFilter(filter);
}
#Override
protected void onBeforeRender(){
super.onBeforeRender();
// clear old messages
filter.clearMessages();
}
}
Provide a new Filter implementation, by implementing the existing IFeedbackMessageFilter interface
public class MessageFilter implements IFeedbackMessageFilter{
List<FeedbackMessage> messages = new ArrayList<FeedbackMessage>();
public void clearMessages(){
messages.clear();
}
#Override
public boolean accept(FeedbackMessage currentMessage){
for(FeedbackMessage message: messages){
if(message.getMessage().toString().equals(currentMessage.getMessage().toString()))
return false;
}
messages.add(currentMessage);
return true;
}
}

Following code works for me in Wicket 6:
public class MyComponent extends Panel {
...
FeedbackMessages feedback = getFeedbackMessages();
feedback.clear();

Related

upgrade from wicket 1.4.9 to wicket 1.4.22 causes button to not be triggered

We are using 1.4.9 for our current webapp. But we want to upgrade to higher 1.4.x version preferably 1.4.22(latest 1.4). The problem is that the page won't submit if AjaxButton is clicked. This is working in 1.4.9. I put breakpoint on the onSubmit of that button but it is not going there. Any insights on this? Thanks!
Here is the code:
For the button:
public abstract class SXIButton extends AjaxButton {
public SXIButton(String id, Form form) {
super(id, form);
initialize();
add(new SimpleAttributeModifier("validating", "false"));
}
}
In the java:
searchForm.add(new SXIButton("searchButton", searchForm) {
private static final long serialVersionUID = -4366670520053224476L;
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
LOG.info("Searching Users");
target.addComponent(userContainer);
userSearchModel.setUserCurrentUserFilter(getSessionBOUser().getCd());
UserDataProvider udp = new UserDataProvider(userSearchModel,isForSearch);
udp.setSort("cd", true);
userContainer.addOrReplace(getResultPanel(udp));
}
});
add(portlet);
portlet.add(searchForm);
in html
<input type = "submit" wicket:id = "searchButton" wicket:message="value:button.search" />
Without any code it's hard to help you out. I would first check the changelog to see if anything was changed in a later version that might causes you trouble (e.g. this ticket). If you cannot find anything obvious you might want to update first to another version which is not the latest one, to narrow down in which version your code breaks for the first time.
But those are just shots in the dark.

Possible bug with GWT gwtquery .live() method

I'm trying to do the following:
I want to add a specific handler for some links, denoted by a class.
$("a.link_list").live("click", new ListLinkHandler());
I need .live() instead of .bind() because new such links will be generated. (I know jQuery's .live() is deprecated in favor of .on(), but gwt-query doesn't have a .on() yet.)
I defined the handler like this (just as the gwtquery example does):
public class ListLinkHandler extends Function {
#Override
public boolean f(Event e) { [...] }
}
However, the handler method is never called when I click the links.
I can see the event listener in Chrome Dev Tools: http://screencloud.net/v/bV5V. I think it's on the body because it's a .live().
I tried using .bind() and it worked fine. The body event listener changed in a a.link_list and the handler does what it's supposed to do, but (as documented, I didn't test) not for newly created links.
I filed a bug for the .live() method, but maybe I'm doing something wrong.
Also, I have no idea how to do it without gwtquery, GWT doesn't seem to have a method for selecting elements by class, neither to continually add the listener to new elements.
It seems you are doing something wrong, but I need more code to be sure. Could you send the complete onModuleLoad code which demonstrates this wrong behavior?
I have written a quick example using live, and it works either when adding new gwt widgets or dom elements with gquery, in both Chrome and FF
public void onModuleLoad() {
$("a.link_list").live("click", new ListLinkHandler());
// Add a new link via gquery
$("<a class='link_list' href=javascript:alert('href') onClick=alert('onClick')>Click </a>").appendTo(document);
// Add a new link via gwt widgets
Anchor a = new Anchor("click");
a.setStyleName("link_list");
a.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
Window.alert("clickHandler");
}
});
RootPanel.get().add(a);
}
public class ListLinkHandler extends Function {
#Override
public boolean f(Event e) {
Window.alert("live");
return true;
}
}

How to hide suggestions in GWT SuggestBox?

I am using GWT 2.4. I have a Suggestbox and I have a requirement to hide the suggestion list under certain cases. The context is as below.
After user selects a suggestion from suggestion list, I am populating two other text box fields, with values corresponding to the selection. For example, suppose the suggestbox contains user-names, and user selects a user-name from suggestions, then other two fields, say user address and email are populated in two other text boxes. These two fields are read only now. Then user clicks on an 'Edit' button. Now the user can edit either user- name ( ie edit in suggestion box), user address and email. It doesn't make sense to show the suggestions again when the user is editing the user-name, since the user has already selected the user and decided to edit it. In a nutshell my SuggesBox should behave as a normal text box. I tried following code, (I know hideSuggestionList() is deprecated) but its not working.
display.getSuggestBox().hideSuggestionList();
Reading the javadoc for hideSuggestionList() it is said that, "Deprecated. use DefaultSuggestionDisplay.hideSuggestions() instead". I don't know how to use DefaultSuggestionDisplay, and I'm using SuggestBox with 'MultiWordSuggestOracle'.
Thanks for helping me out!!
What you can do is simply swap the SuggestionBox with a normal TextBox when the user clicks edit and back when edit is closed. Also because if you would hide the suggestions list, it still queried from the server. By swapping the widget you don't have to care about side effects. SuggestionBox itself uses also a TextBox and thus for the user it's not visible the widget has changed.
If you don't use your own SuggestionDisplay, then this should Just Work™:
((DefaultSuggestionDisplay) suggestBox.getSuggestionDisplay()).hideSuggestions();
Here is the Solution
My Entry Point Class
public class SuggestionEntryPoint implements EntryPoint {
#Override
public void onModuleLoad() {
SuggestBoxWidget suggestBoxWidget = new SuggestBoxWidget();
RootPanel rootPanel = RootPanel.get();
suggestBoxWidget.createOracle();
suggestBoxWidget.createWidgetAndShow(rootPanel);
rootPanel.add(suggestBoxWidget);
DOM.getElementById("loader").removeFromParent();
}
}
And here is my Widget
public class SuggestBoxWidget extends Composite {
private TextBox textSuggestBox = new TextBox();
private SuggestBox suggestBox = null;
DefaultSuggestionDisplay suggestionDisplay = new DefaultSuggestionDisplay();
MultiWordSuggestOracle suggestOracle = new MultiWordSuggestOracle();
private static SuggestBoxWidgetUiBinder uiBinder = GWT
.create(SuggestBoxWidgetUiBinder.class);
interface SuggestBoxWidgetUiBinder extends
UiBinder<Widget, SuggestBoxWidget> {
}
public SuggestBoxWidget() {
initWidget(uiBinder.createAndBindUi(this));
}
public void registerEvents(){
suggestBox.addKeyUpHandler(new KeyUpHandler() {
#Override
public void onKeyUp(KeyUpEvent event) {
if(suggestBox.getText().equalsIgnoreCase("1")){
suggestionDisplay.hideSuggestions();
}
}
});
}
public void createWidgetAndShow(HasWidgets container){
suggestBox = new SuggestBox(suggestOracle,textSuggestBox,suggestionDisplay);
container.clear();
container.add(suggestBox);
registerEvents();
}
public void createOracle(){
for(int i=1;i<=100;i++){
suggestOracle.add(i+"");
}
}
}
Actually you have to create a SuggestBox with 3 Parameters to the Constructor.

GWT TestCase: Simulating clicking a button on my page

I'm using GWT 2.4 with JUnit 4.8.1. When writing my class that extends GWTTestCase, I want to simulate clicking on a button on the page. Currently, in my onModuleLoad method, this button is only a local field ...
public void onModuleLoad() {
final Button submitButton = Button.wrap(Document.get().getElementById(SUBMIT_BUTTON_ID));
...
// Add a handler to send the name to the server
GetHtmlHandler handler = new GetHtmlHandler();
submitButton.addClickHandler(handler);
How do I simulate clicking on this button from the GWTTestCase? Do I have to expose this button as a public member accessor is there a more elegant way to access it? Here is what I have in my test case so far ...
public class GetHtmlTest extends GWTTestCase {
// Entry point class of the GWT application being tested.
private Productplus_gwt productPlusModule;
#Override
public String getModuleName() {
return "com.myco.clearing.productplus.Productplus_gwt";
}
#Before
public void prepareTests() {
productPlusModule = new Productplus_gwt();
productPlusModule.onModuleLoad();
} // setUp
#Test
public void testSuccessEvent() {
// TODO: Simulate clicking on button
} // testSuccessEvent
}
Thanks, - Dave
It can be as easy as buttonElement.click() (or ButtonElement.as(buttonWidget.getElement()).click(), or ButtonElement.as(Document.get().getElementById(SUBMIT_BUTTON_ID)).click())
But remember that a GWTTestCase doesn't run in your own HTML host page, but an empty one, so you'll first have to insert your button within the page before simulating your module's load.
gwt-test-utils seems to be the perfect framework to answer your need. Instead of inheriting from GWTTestCase, extend the gwt-test-utils GwtTest class and implement your click test with the Browser class, like shown in the getting starting guide :
#Test
public void checkClickOnSendMoreThan4chars() {
// Arrange
Browser.fillText(app.nameField, "World");
// Act
Browser.click(app.sendButton);
// Assert
assertTrue(app.dialogBox.isShowing());
assertEquals("", app.errorLabel.getText());
assertEquals("Hello, World!", app.serverResponseLabel.getHTML());
assertEquals("Remote Procedure Call", app.dialogBox.getText());
}
If you want to keep your button private, you'd be able to retrieve it by introspection. But my advice is to make you view's widgets package protected and to write your unit test in the same package so it could access them. It's more convinent and refactoring-friendly.
gwt-test-utils provide introspection convinence. For example, to retrieve the "dialogBox" field which could have been private, you could have do this :
DialogBox dialogBox = GwtReflectionUtils.getPrivateFieldValue(app, "dialogBox");
But note that using GwtReflectionUtils is not mandatory. gwt-test-utils allows you to use ANY java classes in GWT client side tests, without restriction :)
You can do it like this:
YourComposite view = new YourComposite();
RootPanel.get().add(view);
view.getSubmitButton.getElement().<ButtonElement>cast().click();

How do you rebuild the GWT History stack?

I have a larger application that I'm working with but the GWT History documentation has a simple example that demonstrates the problem. The example is copied for convenience:
public class HistoryTest implements EntryPoint, ValueChangeHandler
{
private Label lbl = new Label();
public void onModuleLoad()
{
Hyperlink link0 = new Hyperlink("link to foo", "foo");
Hyperlink link1 = new Hyperlink("link to bar", "bar");
Hyperlink link2 = new Hyperlink("link to baz", "baz");
String initToken = History.getToken();
if (initToken.length() == 0)
{
History.newItem("baz");
}
// Add widgets to the root panel.
VerticalPanel panel = new VerticalPanel();
panel.add(lbl);
panel.add(link0);
panel.add(link1);
panel.add(link2);
RootPanel.get().add(panel);
History.addValueChangeHandler(this); // Add history listener
History.fireCurrentHistoryState();
}
#Override
public void onValueChange(ValueChangeEvent event)
{
lbl.setText("The current history token is: " + event.getValue());
}
}
The problem is that if you refresh the application, the history stack gets blown away. How do you preserve the history so that if the user refreshes the page, the back button is still useful?
I have just tested it with Firefox and Chrome for my application and page refresh does not clear the history. Which browser do you use? Do you have the
<iframe src="javascript:''" id='__gwt_historyFrame' style='position:absolute;width:0;height:0;border:0'></iframe>
in your HTML?
GWT has catered for this problem by providing the History object. By making a call to it's static method History.newItem("your token"), you will be able to pass a token into your query string.
However you need to be aware that any time there is a history change in a gwt application, the onValueChange(ValueChangeEvent event){} event is fired, and in the method you can call the appropriate pages. Below is a list of steps which i use to solve this problem.
Add a click listener to the object that needs too call a new page. In handling the event add a token to the history.(History.newItem("new_token").
Implement the ValueChangeHandler in the class that implements your EntryPoint.
Add onValueChangeHandler(this) listener to the class that implements the EntryPoint. Ensure that the line is add in the onModuleLoad() method (it is important it is added in this method) of the class that implements the EntryPoint(pretty obvious ha!)
Finally implement onValueChange(ValueChangeEvent event){ //call a new page } method.
That's it