Wicket - hide element on AjaxButton during lazy loading - java

I have a page with AjaxLazyLoadPanel, which contain a long-loading list and submitting AjaxButton.
After the AjaxLazyLoadPanel is ready, when I submit, the another long-loading is executing, and after that I need to refresh whole page. This is where I get myself, the code looks as follows:
AjaxButton button1 = new AjaxButton("submit1") {
#Override
protected void onSubmit(AjaxRequestTarget target, Form form) {
someLongWorkingMethod();
setResponsePage(page); //refreshing page
}
};
add(button1);
And it works perfectly. But what I'm trying to do now - is to disable this button or hide this button (or the whole panel if its necessary) when the method is computing, and when the page refresh with setResponsePage I'd like to have this button back.
I've read many posts/mailing lists about it but nothing helped me, I tried all things that I found and placed it before someLongWorkingMethod():
ajaxLazyLoadPanel.setOutputMarkupId(true);
ajaxLazyLoadPanel.setOutputMarkupPlaceholderTag(true);
ajaxLazyLoadPanel.add(new AttributeAppender("style","display:none;"));
ajaxLazyLoadPanel.setVisible(false);
ajaxLazyLoadPanel.setEnabled(false);
target.add(ajaxLazyLoadPanel);
And the same not for ajaxLazyLoadPanel but for "this" (AjaxButton).
Am I doing something terribly wrong or what? Is this what I'm trying to do even possible? I would really appreciate some help.

In your AjaxButton you could override updateAjaxAttributes() and add an IAjaxCallListener which hides the button via jQuery right after you click the button. When the responsePage is rendered the button appears again. The code for the override looks like this:
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.getAjaxCallListeners().add(new IAjaxCallListener() {
#Override
public CharSequence getBeforeHandler(Component cmpnt) {
return "$(\"#" + cmpnt.getMarkupId() + "\").hide()";
}
#Override
public CharSequence getPrecondition(Component cmpnt) {
return "";
}
#Override
public CharSequence getBeforeSendHandler(Component cmpnt) {
return "";
}
#Override
public CharSequence getAfterHandler(Component cmpnt) {
return "";
}
#Override
public CharSequence getSuccessHandler(Component cmpnt) {
return "";
}
#Override
public CharSequence getFailureHandler(Component cmpnt) {
return "";
}
#Override
public CharSequence getCompleteHandler(Component cmpnt) {
return "";
}
});
}

Thanks to #Robert Niestroj answer (but working only in newest Wicket 6), I found solution for Wicket 1.5, I hope it will help someone.
Its just similar idea, but achieved with overriding getAjaxCallDecorator for AjaxButton, and using pure Javascript
AjaxButton button1 = new AjaxButton("submit1") {
String id = this.getMarkupId();
#Override
protected void onSubmit(AjaxRequestTarget target, Form form) {
...
}
#Override
protected org.apache.wicket.ajax.IAjaxCallDecorator getAjaxCallDecorator() {
return new AjaxCallDecorator() {
#Override
public CharSequence decorateScript(Component component, CharSequence script) {
return "document.getElementById(\'"+id+"\').style.display = 'none';"+script;
}
};
}
};
Important thing to remember is to ensure that you are returning script+[your added script], because otherwise your onsubmit action won't happen.
More info (and also onSucces and onFailure versions) in Wicket 1.5 doc

Related

Why page cannot get bookmarked with History mechanism in GWT/MVP4G.?

I am trying to implement history mechanism with a GWT app but has problem with page bookmark i.e. in my case, I have created 3 pages where one get invoked from another. Now, the problem is if page3 is bookmarked then while invoking that bookmark it should open page3 instead now it opens Home page.
Why is it so.? What can be the issue.?
I have implemented HistoryConverter as,
#History(type=HistoryConverterType.SIMPLE)
public class MyHistoryConverter implements HistoryConverter<HistoryManagerEventBus> {
public MyHistoryConverter() {
}
#Override
public void convertFromToken(String historyName, String param,HistoryManagerEventBus eventBus) {
eventBus.dispatch(historyName);
}
public String convertToToken(String eventType){
return eventType;
}
public String convertToToken(String eventType,HistoryPageTwoView view){
return view.getClass().getName();
}
public String convertToToken(String eventType,HistoryPageThreeView view){
return view.getClass().getName();
}
#Override
public boolean isCrawlable() {
return false;
}
}
and eventBus as,
#Events(startPresenter = HistoryPageOnePresenter.class,historyOnStart=true)
public interface HistoryManagerEventBus extends EventBusWithLookup {
/**
* Start event will be fired internally
*/
#Start
#Event(handlers = HistoryPageOnePresenter.class,historyConverter=MyHistoryConverter.class)
void start();
#InitHistory
#Event(handlers = HistoryPageOnePresenter.class)
void init();
#Event(handlers = HistoryPageTwoPresenter.class,historyConverter=MyHistoryConverter.class)
void getHistoryPageTwo();
#Event(handlers=HistoryPageThreePresenter.class,historyConverter=MyHistoryConverter.class)
void getHistoryPageThree();
#Event(handlers=HistoryPageOnePresenter.class,historyConverter=MyHistoryConverter.class)
void getHistoryPageOne();
#Event(handlers=HistoryPageOnePresenter.class)
void setHistoryPageTwo(HistoryPageTwoView view);
#Event(handlers=HistoryPageOnePresenter.class)
void setHistoryPageThree(HistoryPageThreeView view);
}
Assuming that:
#Event(handlers = HistoryPageTwoPresenter.class,historyConverter=MyHistoryConverter.class)
void getHistoryPageTwo();
#Event(handlers=HistoryPageThreePresenter.class,historyConverter=MyHistoryConverter.class)
void getHistoryPageThree();
#Event(handlers=HistoryPageOnePresenter.class,historyConverter=MyHistoryConverter.class)
void getHistoryPageOne();
are your navigation events, there is no need to have the following methods inside the MyHistoryConverter class defined:
public String convertToToken(String eventType,HistoryPageTwoView view){
return view.getClass().getName();
}
public String convertToToken(String eventType,HistoryPageThreeView view){
return view.getClass().getName();
}
as they are not called to create history tokens.
If your history converter works, you should see something like that in your URL:
[myURL]#getHistoryPageOne
or
[myURL]#getHistoryPageTwo
or
[myURL]#getHistoryPageThree
If you entering:
[myURL]#getHistoryPageThree
to start your application, the tokens will be handle in the convertFromToken-method.
You can add the #Debug-annotation to your eventBus to verify that the bookmarked event is fired at the start of your application.
So everything looks good, except the fact, that the Start-event should not have a historyConverter-attribute.

How to add properly UiHandler for BlurEvent in GWT?

Normally if we have some textField in GWT we can add a BlurHandler by the following code:
textField.addBlurHandler(new BlurHandler() {
#Override
public void onBlur(BlurEvent event) {
//what we need
}
});
But if we use UiBinder and our textField is annotated by #UiField and it is mentioned in our ui.xml file we can add BlurHandler by this code as well:
#UiHandler("textField")
protected void createBlurHandler(BlurEvent event) {
}
I guess I am right here because it works like this. So, the question is, can we actually define BlurHandler inside ui.xml file?
For example, it is possible to add inputMaxLength and some other attributes there, does GWT has some possibility like onChange method or are these ways that I described the only possibilities?
I would like to have something like this:
<g:TextBox ui:field="textField" onBlur="methodName" />
Is it possible?
I am pretty sure what you are asking is not possible. The problem is that you wouldn't be able to use reflection to figure out which method you want to call. However you can extends the TextBox class and use that inside your template. The extended class could have it's own properties that can be set in the template. An example is as follows where I set the default test on my own DefaultTextBox.
public class DefaultTextBox extends TextBox {
/**
* The text color used when the box is disabled and empty.
*/
private static final String TEXTBOX_DISABLED_COLOR = "#AAAAAA";
private final String defaultText;
public #UiConstructor
DefaultTextBox(final String defaultText) {
this.defaultText = defaultText;
resetDefaultText();
// Add focus and blur handlers.
addFocusHandler(new FocusHandler() {
#Override
public void onFocus(FocusEvent event) {
getElement().getStyle().clearColor();
getElement().getStyle().clearFontStyle();
if (defaultText.equals(getText())) {
setText("");
}
}
});
addBlurHandler(new BlurHandler() {
#Override
public void onBlur(BlurEvent event) {
if ("".equals(getText())) {
resetDefaultText();
}
}
});
}
public String getDefaultText() {
return defaultText;
}
#Override
public void setText(String text) {
if (text == null) {
super.setText(getDefaultText());
} else {
getElement().getStyle().clearColor();
getElement().getStyle().clearFontStyle();
super.setText(text);
}
}
public String getText() {
return super.getText();
}
/**
* This is override so that the editor framework will not get the default
* value but the actual null value when the default text is in the box.
*/
#Override
public String getValue() {
try {
return getValueOrThrow();
} catch (ParseException e) {
return null;
}
}
#Override
public void setValue(String value) {
setText(value);
}
/**
* This is overridden from the parent class because this is
* how the editor gets the value.
*/
public String getValueOrThrow() throws ParseException {
if (defaultText.equals(super.getValueOrThrow())) {
return null;
}
return super.getValueOrThrow();
}
/**
* Reset the text box to the default text.
*/
public void resetDefaultText() {
setText(defaultText);
getElement().getStyle().setColor(TEXTBOX_DISABLED_COLOR);
getElement().getStyle().setFontStyle(FontStyle.ITALIC);
}
}
Then in the template you can set properties like this.
<w:DefaultTextBox defaultText="name" ui:field="nameTextBox" />
This will also work with setters, you can set properties without having to use the #UiConstructor but in my case I wanted to make sure that there was no empty constructor for this class.

GWT: SafeHtmlRenderer

I'm trying to resolve a deprecation warning The constructor TextInputCell(SafeHtmlRenderer) is deprecated raised in the latest version of GWT (2.6):
Column<InterimReport, String> contextColumn = new Column<InterimReport, String>(
new TextInputCell(new SafeHtmlRenderer<String>() {
#Override
public void render(String result, SafeHtmlBuilder builder) {
builder.appendHtmlConstant(result);
}
#Override
public SafeHtml render(String result) {
return SafeHtmlUtils.fromTrustedString(result);
}
}
)
)
{
#Override
public String getValue(InterimReport ir) {
return ir.get("context");
}
};
The TextInputCell holds a URL (see String result) to some page on the internet. I don't know what to use in its place. I found this HyperlinkCell class but can't work out whether:
this is a good approach (should I be doing something with com.google.gwt.user.client.ui.Anchor instead?)
or
if it's the right approach, how to actually implement it
Given your current SafeHtmlRenderer, which works around a previous bug of TextInputCell's default behavior, you can just switch to the default constructor: new TextInputCell().

Disable modify\delete JTextArea content (but not insert)

I have JTextArea component and I need to disable modify\delete current content in component by users. Users may only add\insert some text at the end, but setText method must work as usual.
tnx
I need to disable modify\delete current content in component by users.
textArea.setEditable( false );
Users may only add\insert some text at the end, but setText method must work as usual.
You should have an "Add Text" button that will take text from a separate text field and then append the text to the Document using the append(...) method of the JTextArea.
Could you post an example of what you already have?
To clarify, if you want users to be unable to certain things, you may need to re-insert the original text manually. I'm unsure of the editor used by a JTextArea, but you could try overriding that.
Horrific code I'm coming up with on the spot incoming, you can probably do this much easier:
private static String mand = "mandatory.";
private static JTextArea test = new JTextArea(mand);
public static String getMand() {
return mand;
}
public static JTextArea getTest() {
return test;
}
public static void setMand(String mand2) {
mand = mand2;
}
public static void setTest(JTextArea test2) {
test = test2;
}
getTest().addKeyListener(new KeyListener() {
#Override
public void keyPressed(KeyEvent arg0) {
// do nothing
}
#Override
public void keyReleased(KeyEvent arg0) {
// do nothing
}
#Override
public void keyTyped(KeyEvent arg0) {
if(getTest().getText().startsWith(getMand())) {
System.out.println("good, text still present");
setMand(test.getText());
} else {
getTest().setText(getMand());
}
}
});
WARNING :: if the user makes any mistakes in adding information to the JTextArea, the code will not allow the user to fix these mistakes.
Tested successfully under JDK (/JRE) 7.

Apache wicket: how to update model after validation error

I have form with dateTimeField, and ListView.
ListView looks like that:
final ListView<String> countryView = new ListView<String>("country", model.<List<String>>bind("country")) {
#Override
protected void populateItem(final ListItem<String> item) {
final String country = item.getModelObject();
item.add(new ValidationDisplayableLabel("country", country, new String[] { modelPath }));
item.add(new AjaxLink("deleteLink") {
#Override
public void onClick(AjaxRequestTarget target) {
model.getObject().getCountry().remove(country);
if (issPeriod) {
addButton.setVisible(true);
countryTextField.setVisible(true);
findButton.setVisible(true);
}
if (target != null)
target.addComponent(rowPanel);
}
});
}
};
countryTextField = new ValidationDisplayableTextField("countryCodeInput", model.bind("oneCountry"), "job.country.value");
**countryView.setReuseItems(true);**
rowPanel.add(countryView);
rowPanel.add(countryTextField);
addButton.setOutputMarkupPlaceholderTag(true);
rowPanel.add(addButton);
And the addButton looks like that:
AjaxSubmitLink addButton = new AjaxSubmitLink(LinkNames.addCountry.toString()) {
#Override
public void onSubmit(AjaxRequestTarget target, Form form) {
if (model.getObject().getOneCountry() != null)
addCountry();
if (target != null)
target.addComponent(rowPanel);
target.addComponent(form.getPage().get("feedbackPanel"));
}
#Override
protected void onError(AjaxRequestTarget target, Form<?> form)
{
onSubmit(target, form);
}
};
The thing is, that when I fail my dateTimeField (e.g. set hours to 100), enter country code in countryTextField, and press on addButton, it displays validation message in feedback panel, that hour range is incorrect, but don't add the country. This is because my model isn't updated. Maybe there is a way to update it manually? So validation message will be displayed, but the country listView still could be updated?
Submit of the whole form is on other button, so logically it is normal to add a country even if there is a validation error in dateTimeField.
Thanks!
P.S. i've read a lot of posts about similar problem, but most of them were solved with .setReuseItems(true), but it doesn't work in my case.
P.P.S Apache wicket 1.4.17
As an update to this answer, in Wicket 6, you can accomplish this by overriding onError() in the Form:
#Override
protected void onError() {
super.onError();
this.updateFormComponentModels();
}
I faced a similar problem in my project, the workaround I found was to use a special Visitor. It will update the model even though the submitted input is invalid.
public class VisitorUpdateModelWithoutValidation implements FormComponent.IVisitor {
public Object formComponent(IFormVisitorParticipant formComponent) {
if (formComponent instanceof FormComponent) {
final FormComponent<?> formComponent1 = (FormComponent<?>) formComponent;
boolean required = formComponent1.isRequired();
if (required) {
formComponent1.setRequired(false);
}
formComponent1.modelChanging();
formComponent1.validate();
formComponent1.updateModel();
formComponent1.modelChanged();
if (required) {
formComponent1.setRequired(true);
}
}
return Component.IVisitor.CONTINUE_TRAVERSAL;
}
}
Simply use it in the onSubmit method of your behavior : getForm().visitFormComponents(new VisitorUpdateModelWithoutValidation());
You can issue a field.clearInput() on the fields you are updating before you target the update(s).

Categories

Resources