Wicket modal window not displaying properly - java

I am trying to create a modal window for my application, but unfortunately I am unable to do so.
I have a page that extends WebPage and I have added a panel that extends Panel to it. The page and panel are written separately; that is, in panel.java and page.java. Now, I have added a modal window to the panel with the help of this Wicket Examples example (source). But when the page renders, I am seeing — by inspecting element of that page — that the div with wicket:id of "modal1" has attribute script="display: none". I don't know what to do. Any information will be very helpful to me.
One more thing: are
return new ModalContent1Page(ModalWindowPage.this.getPageReference(), modal1);
and
return new ModalContent1Page(ModalWindowPage.this, modal1);
the same?
Edit:
The problem is solved. Actually when I asked the question I did not have the code then. I was following the tutorial of RoseIndia, but I was unsuccessful and as I am using wicket 1.3.1 the PageReference class is not available there. So I solve it as:
final ModalWindow modalWindow;
add(modalWindow = new ModalWindow("modalVideo"));
modalWindow.setCookieName("modal-video");
modalWindow.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
modalWindow.setResizable(false);
modalWindow.setInitialHeight(215);
modalWindow.setInitialWidth(215);
modalWindow.setHeightUnit("px");
modalWindow.setPageCreator(new ModalWindow.PageCreator() {
public Page createPage() {
return new PlayVideo(ItemViewPanel.this.getPage(), modalWindow, itemId);
}
});
AjaxLink showModalLink;
add(showModalLink = new AjaxLink("showModal") {
#Override
public void onClick(AjaxRequestTarget target) {
modalWindow.show(target);
}
});
Thank you.

To answer your second question: no, those two lines of code are not the same. ModalWindowPage.this is the page itself, so its type is ModalWindowPage. getPageReference(), on the other hand, returns a PageReference, which is not in the same hierarchy.

Related

Wicket: "Component-targetted feedback message was left unrendered" even though the FeedbackPanel is on the page

I'm using apache wicket 1.4.22. I've got an error which indicates that a feedback panel is missing from my page. However, I have added it - so why is the feedback not showing?
Component-targetted feedback message was left unrendered. This could be because you are missing a FeedbackPanel on the page. Message: [FeedbackMessage message = "Problem retrieving transactions for subscription 2971", reporter = 4, level = ERROR]
Here's an extract of the page constructor:
public class SubDetailPage extends AbstractCCPage {
public SubDetailPage(final CCSubscription sub) {
if(sub.getTransactions()==null || sub.getTransactions().isEmpty())
error("Problem retrieving transactions for subscription "+sub.getSubscriptionId());
And here's the super class:
public abstract class AbstractCCPage extends WebPage {
protected final FeedbackPanel feedbackPanel;
public AbstractCCPage() {
feedbackPanel = new FeedbackPanel("info-panel");
feedbackPanel.setOutputMarkupId(true);
add(feedbackPanel);
I've used feedback panels before. They work fine. What am I doing wrong here? I just can't see it.
A little bit of debugging shows that the feedback message was added to the list:
Session.get().getFeedbackMessages();
shows that the message is in there.
And the page rendered does indeed have an (empty) info-panel:
<div id="info_panel45" class="info-panel"> </div>
---edit----
some more debugging: if I put the following line in the AbstractCCPage constructor, it works:
error("hello world");
but if I put the same line in the SubDetailPage constructor, it doesn't - even though both constructors are being called.
The problem might be caused by a redirect to your page:
Wicket redirects to your page instance without actually rendering the page, but the Feedback message is already added.
Try moving the call to #error() to #onBeforeRender().
I found the problem. Right at the end of the AbstractCCPage I had the following entry:
add(new PageView("componentTree", this));
This was to add a breakdown the page structure at debug level so we can see the tree on the page.
Removing this fixed the problem.

Adding JFace wizard pages after addPages() was called?

i am trying to create a jface wizard.
In my wizard i have my "startpage". The options i choose in my "startpage" depending on how many pages will follow. But in my opinion its not possible to do that. Because the addPages() method getting called after the wizard was started. The addPage() method is private. But i need to add my pages there, because when i do it somewhere else, the createControl(Composite parent) don't getting called.
Is there any solution how to solve that problem?
I thought about writing a own method sth. like this:
public void addNewPage() {
Page page = new Page("pagename");
page.createControl(parent);
page.setDescription("");}
...
But it doesn't work.
Do you guys have any solution for my problem?
You could add all your pages in the wizard addPages and then override getNextPage to control which pages is displayed when Next is pressed.
If that is not enough you can always write your own implementation of the IWizard interface.
You can do so by overriding org.eclipse.jface.wizard.Wizard.getNextPage to return a new page if conditions are met (conditionForMorePages in the snippet below):
#Override
public IWizardPage getNextPage() {
IWizardPage nextPage = super.getNextPage(page);
if (nextPage == null) {
if (conditionForMorePages){
// we need an additional page.
IWizardPage nextPage = new MyAdditionalPage();
}
}
return nextPage;
}
If your wizard start with only one page, "back" and "next" buttons do not appear by default. If there is a chance you have more steps coming up dynamically, you want to display the navigation buttons. You can do so by setting the proper flag using the API
public void setForcePreviousAndNextButtons(boolean b)

How to wire up GWT hyperlink click handler?

I am brand new to GWT and am trying to achieve the following:
Here's the code that I've cooked up:
public class MyWebApp implements EntryPoint {
// The main container for everything the user sees (the "view")
private LayoutPanel mainPanel;
// Simple HTML for the header ("MyWebApp") and subsequent <hr/>
private SafeHtml header;
// The three links "Dashboard", "Monitors" and "Help Desk"
private HorizontalPanel navMenu;
// The empty content that gets populated when user clicks one of
// the 3 links.
private Panel menuContent;
#Override
public void onModuleLoad() {
// The initial fragment contains the header, nav menu and empty "content" div.
// Each menu/screen then fills out content div.
initMainPanel();
RootPanel.get().add(mainPanel);
}
private void initMainPanel() {
SafeHtmlBuilder headerBuilder = new SafeHtmlBuilder();
navMenu = new HorizontalPanel();
// Leaving null until user clicks on one of the 3 menus.
// Then the menu will decide what panel gets injected for
// this panel.
menuContent = null;
// Create the simple HTML for the header.
headerBuilder.append("<h1>MyWebApp</h1><hr/>");
// Create the navMenu items.
Hyperlink dashboardLink, monitorsLink, helpDeskLink;
// Homepage is http://www.mywebapp.com
// I want the dashboardLink to inject menuContent and "redirect" user to
// http://www.mywebapp.com/dashboard
dashboardLink = new Hyperlink("???", "???");
// http://www.mywebapp.com/monitors
monitorsLink = new Hyperlink("???", "???");
// http://www.mywebapp.com/help-desk
helpDeskLink = new Hyperlink("???", "???");
navMenu.add(dashboardLink);
navMenu.add(monitorsLink);
navMenu.add(helpDeskLink);
// Add all widgets to the mainPanel.
mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString()));
mainPanel.add(navMenu);
mainPanel.add(menuContent);
// Position and size the widgets (omitted for brevity).
// mainPanel.setWidgetHorizontalPosition(...);
}
private HTML getDashboardMenuContent() {
return new HTML("This is the dashboard.");
}
private HTML getMonitorsMenuContent() {
return new HTML("These are the monitors.");
}
private HTML getHelpDeskMenuContent() {
return new HTML("This is the help desk.");
}
}
Most importantly:
How do I "wire up" the Hyperlinks so that when the user clicks them, I can call the appropriate getXXXMenuContent() method, and then add that to menuContent?
But also:
I feel like I'm doing something wrong here: mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString())); - if so what is it?!? How should I be adding a simple <h1> and <hr/> in a way that's secure (hence the use of the Safe* objects), efficient, and conforming to recommended practices?
Should I be implementing UiBinder here? If so, would I make UiBinders for each menu's content or for the entire mainPanel, or both?
Thanks in advance!
Hyperlink widgets trigger navigation. You don't want to handle clicks on them, you want to handle navigation (that could be triggered by clicking a Hyperlink or using the browser's back/forward buttons, a bookmark or link from elsewhere –including Ctrl+clicking a Hyperlink to open it in a new window/tab–, etc.)
To react to those navigation events, use History.addValueChangeHandler; and to handle the initial navigation on application start, call History.fireCurrentHistoryState() (after you add your handler of course).
More details in: https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsHistory
Would be better to split other questions to... other questions, but here are the answers anyway:
I feel like I'm doing something wrong here: mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString())); - if so what is it?!? How should I be adding a simple <h1> and <hr/> in a way that's secure (hence the use of the Safe* objects), efficient, and conforming to recommended practices?
The HTML widget has a constructor taking a SafeHtml so you don't need to call toString().
If you're only using a constant, you don't need a SafeHtmlBuilder; use SafeHtmlUtils instead. But constants are no more or less secure with or without SafeHtml, SafeHtml just makes it easier to find all occurrences of HTML in your code, to help in doing a security review of your app (BTW, we're doing HTML, so <hr>, not <hr/>; if you really want it to look like XML/XHTML, then use <hr /> but you're only cheating yourself here)
Should I be implementing UiBinder here? If so, would I make UiBinders for each menu's content or for the entire mainPanel, or both?
If you don't feel the need for UiBinder, you don't have to use it. But in this case it won't change anything: you're not handling widget events, but history events.
Something like
dashboardLink.addClickHandler(
new ClickHandler()
{
public void onClick( ClickEvent event )
{
mainPanel.setWidget( getDashboardMenuContent() );
}
} );
You should note that Hyperlink.addClickHandler(...) is deprecated and it is recommended to use Anchor.addClickHandler(...) instead.
As for the other questions: It is a lot more elegant and easier to build UI's with UIBinder, so definitely look into that, but do try to make "it" work first to avoid the added complexity of the .ui.xml setup :-)
Cheers,
I have one simple piece of advice to give you. Use what the framework has to offer.
The HTML widget should be your last escape. There are so many widgets that there is no need for you to write html almost anywhere in your code.
So instead of headerBuilder, you can user the following piece of code
Label header = new Label("MyWebApp");
header.setStyleName("headerStyle",true);
You can set the style properties in an external Css file and add the reference inside the base html file or the gwt.xml file. So that answers your question about mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString()));
In respect to the Hyperlink. If you choose to use hyperlinks, remember that the most effective usage is with the MVP pattern better known as Places and Activities (Lots of information on the web)
If you want something simpler instead the MenuBar and MenuItem classes should do the trick.
Look here for an example on how to use the MenuBar to control your application. There are many other ways but why not use the tools provided?
Also the UIBinder Vs the Designer/Classes methods is extensively discussed on stackoverflow resulting to a matter of choice and programming familiarity/preference.

How to both start a file download and close a (jQuery) dialog in Wicket?

In a Wicket app, I have a modal dialog that contains a simple form and a button. User enters values (report parameters), and then clicks the button which starts the download of a report file (typically a PDF). (All form values are required, and Wicket's validation mechanism is used to make sure user entered them before the download can start.)
Maybe this is better explained with a picture:
I'm using here a jQuery UI Dialog (instead of Wicket's ModalWindow which felt a lot clumsier and uglier from user's perspective).
Everything is pretty much working, except closing the dialog when/after clicking the download button.
Current version (irrelevant bits omitted):
public class ReportDownloadLink extends Link {
public ReportDownloadLink(String id, ReportDto report) {
super(id);
this.report = report;
}
#Override
public void onClick() {
IResourceStream resourceStream = new AbstractResourceStreamWriter() {
#Override
public void write(OutputStream output) {
try {
reportService.generateReport(output, report);
} catch (ReportGenerationException e) {
// ...
}
}
#Override
public String getContentType() {
// ...
}
};
ResourceStreamRequestTarget target =
new ResourceStreamRequestTarget(resourceStream, report.getFileName());
getRequestCycle().setRequestTarget(target);
}
The dialog is a Wicket Panel (which makes use of ReportDownloadLink above), which we put in a certain div, and then when a report is selected in a list, the dialog is opened from an AjaxLink's onClick() quite simply like this:
target.appendJavascript(String.format("showReportExportDialog('%s')", ... ));
Which calls this JS function:
function showReportExportDialog(dialogTitle) {
$("#reportExportPanelContainer").dialog(
{modal:true, draggable:true, width: 320, height: 330, title: dialogTitle}
);
}
Some options:
Make ReportDownloadLink extend something else than Link, perhaps, and/or find an appropriate method to override which would allow me to execute the tiny bit of JavaScript needed to close the jQuery Dialog.
Investigate jQuery + Wicket libraries (such as jqwicket or wiquery) that supposedly make these two work better together.
Latest thing I tried was overriding method getOnClickScript() in ReportDownloadLink which seemed promising (according to the Javadocs, it returns "Any onClick JavaScript that should be used"):
#Override
protected CharSequence getOnClickScript(CharSequence url) {
return "closeDownloadDialog()";
}
Thing is, this causes onClick() not to be called at all, i.e., the download doesn't start.
Could I perhaps override some more "ajaxy" class from Wicket (than Link) to combine these things: first init the download, then call the JS for closing the dialog?
Any recommendations or experiences from similar cases? Note that I want to keep using the jQuery dialog here, even though it makes things like these more complicated. Using a DownloadLink (see related question) is fine too in case that makes things easier.
NB: if you recommend JQWicket or wiQuery, please provide an example of how to do this.
Maybe you can try to bind the close modal code to the button "click" event using only JQuery, in your modal panel page, add something similar to ${"#mySubmit").click(myCloseModalFunction). It should keep Wicket default's behavior and add modal closing in the mix.
The other way is to override the getOnClickScript(...) method but the javascript has to return true in order for the browser to call the continue link evaluation and load the corresponding href. If you return false, the evaluation stops. I would suggest something like
#Override
protected CharSequence getOnClickScript(CharSequence url) {
return "closeDownloadDialog();return true;";
}
Hope it helps...
See https://cwiki.apache.org/WICKET/ajax-update-and-file-download-in-one-blow.html for inspiration.

How to use GWT fileupload?

I have some queries when trying to implement a fileupload widget in my application. After many tries, it just doesn't seem to work.
Hence, I tried getting working solutions to see if I can understand anything from there.
http://code.google.com/p/faculty-gwt/source/checkout
However, I tried uploading a file using this and it seems that I am getting error messages too. and what is that textbox and listbox suppose to do? It is meant for showing an example of validating an input before submitting?
Can someone guide me along to solve this? Thanks.
Never tried to use the link you provided, but this is what i did to use a a GWT FileUpload widget:
I built a File Upload widget using the uibinder:
<g:FormPanel ui:field="docForm">
<g:FlowPanel ui:field="inputPane">
/*other displayed info*/
<g:FileUpload ui:field="DocPath"/>
/*other displayed info*/
</g:FlowPanel>
</g:FormPanel>
(Per the GWT api, FileUpload widgets can only be used from a FormPanel)
Make sure you set these in the FormPanel, otherwise you'll probably have issues:
yourFormPanel.setEncoding(FormPanel.ENCODING_MULTIPART);
yourFormPanel.setMethod(FormPanel.METHOD_POST);
That widget is dropped into my container page, then added to the display panel:
private FileUploadWidget createNewUploader(){
FileUploadWidget uploader = new FileUploadWidget(/*my constructor params*/);
uploader.addChangeHandler(new ChangeHandler() {
#Override
public void onChange(ChangeEvent event) {
DocPanel.add(createNewUploader());
}
});
return uploader;
}
My OnChange event is so that I have a new, blank uploader available when i use the current one.
and when I'm ready to submit:
private void processUpload(FileUploadWidget upload, int id) {
upload.setId(id);
//Don't bother to submit an empty one.
if (upload.IsFileSelected())
upload.Submit();
}

Categories