I need to send Wicket links (through mail, for example) which references instances in the system.
For example, the mail could contain:
From: ...#...
To: ...#...
Subject: Order Pending
... txt...
Click here to go: http://I.dont.care.the.style.of.the.linkPage.OrderDetailPage?orderId=1001
... txt...
I have two constructor of this OrderDetailPage
public class OrderDetailPage extends BasePage {
public OrderDetailPage(PageParameters parameters){
this(OrderRepository.getById(parameters.getAsInteger("orderId")), null);
}
public OrderDetailPage(Order order, WebPage back) {
super(new CompoundPropertyModel<Order>(order));
//Renders the page for the order received.
//back is the page we came from. Null hides link.
...
}
...
}
I don't know how to send the links, because, I can't create a Bookmarkable Link because it looks for the default constructor... and of course, I don't have one.
What I'm doing for another page is:
final PageParameters pars = new PageParameters();
pars.add("orderId", "1001");
BookmarkablePageLink<Void> link = new BookmarkablePageLink<Void>("alink", OrderDetailPage.class, pars);
link.add(new Label("id", "1001"));
add(link);
Markup:
<li><span wicket:id="id"/></li>
The generated URL is
http://localhost:8080/wicket/bookmarkable/packagePath.OrderDetailPage?orderId=1001
Which is OK, but Still, doesn't call the "parameters" constructor.
FIX:
I fix this, but I know the solution is NOT OK.
public OrderDetailPage() {
this(WicketApplication.orderRepository.get(Integer
.parseInt(RequestCycle.get().getRequest()
.getRequestParameters().getParameterValue("orderId").toString())),
null);
}
EDIT: I read something about "mounting" the URL, could this work? How?
The BookMarkablePageLink has 2 constructors: one for connecting to the default constructor of the linked page, and one with an extra parameter to supply the link with PageParameters, which will call the constructor with the PageParameters.
You create the link like so:
PageParameters pars = new PageParameters();
pars.add("id", 12345);
add(new BookmarkablePageLink("id", MyPage.class, pars);
This also works with the setResponsePage method:
PageParameters pars = new PageParameters();
pars.add("id", 12345);
setResponsePage(MyPage.class, pars);
Related
I was trying to create a link with the username on it (i.e. dynamic data), and couldn't manage to get the StringResourceModel to work with a Link.
My code looked something like:
Properties:
some.key=User name is: {0}
Java:
StringResourceModel model =
new StringResourceModel("some.key", this, null, new Object[] { getUserName() });
add(new Link("someid", model) {
#Override
public void onClick() {
// do something ...
}
});
HTML:
<a wicket:id="someid">some text to replace</a>
However, that didn't work, i.e. the text was never replaced.
I tried a different direction, which did work, and looks something like this:
Java:
StringResourceModel model =
new StringResourceModel("some.key", this, null, new Object[] { getUserName() });
Link link;
add(link = new Link("someid") {
#Override
public void onClick() {
// do something ...
}
});
link.add(new LabeL("anotherid", model));
HTML:
<a wicket:id="someid"><span wicket:id="anotherid">some text to replace</span></a>
(the properties file is the same).
My question is, am I right to assume that the StringResourceModel doesn't work with Links (I call this an assumption since I didn't see anything about this in the JavaDOC) ?
If not, how can the StringResourceModel be used directly with the Link, without the mediator Label ?
The model parameter in the Link constructor isn't meant to be used as a display value. To set the text of the link you need to explicitly add a Label to it:
Link<Void> link = new Link<Void>("link");
link.add(new Label("label", model);
add(link);
and in HTML:
<a wicket:id="link"><span wicket:id="label"></span></a>
The model in the constructor is meant to be used in the onclick method (or similar). For example (from the JavaDoc):
IModel<MyObject> model = ...;
Link<MyObject> link = new Link<MyObject>("link", model) {
public void onClick() {
MyObject obj = getModelObject();
setResponsePage(new MyPage(obj));
}
};
add(link);
In your first example, you aren't telling wicket to replace the text. You just apply a model to the link without telling wicket what to do with it.
To fix this, you'd need to replace your HTML with something along the lines of
<a wicket:id="someid"><wicket:message key="some.key">some text to replace</wicket:message></a>
I don't remember the syntax completely and can't try this right now but it should help you anyway.
I am new to vaadin. I have one Link like
Link link = new Link("", new ExternalResource(redirectURL));
my requirement is, I have to set value when user clicks the link. Can I add listener when user click the link. Or is there alternate ways of setting value if link is clicked.
To capture onClick on a link or a label, I always create a HorizontalLayout and put the component inside it:
HorizontalLayout hor = new HorizontalLayout();
final Link link = new Link("Click on Me!", new ExternalResource("http://www.google.com"));
hor.addComponent(link);
hor.addLayoutClickListener(new LayoutClickListener() {
#Override
public void layoutClick(LayoutClickEvent event) {
// capture the click here and do whatever you'd like to do, e.g.
// if ( event.getClickedComponent() != null ) {
// if(event.getClickedComponent().equals(link)) {}
}
});
I interpreted your question as changing the caption of the link. As far as I know it's not possibly with the Link component. Take a look at the activelink addon: http://vaadin.com/addon/activelink.
This addon behaves like Link and lets you add a LinkActivatedListener to it. The code should look like this:
final ActiveLink link = new ActiveLink("", new ExternalResource(redirectURL));
link.addListener(new LinkActivatedListener() {
#Override
public void linkActivated(LinkActivatedEvent event) {
link.setCaption("newCaption");
}
});
You could use the new BrowserWindowOpener class:
From the API:
Component extension that opens a browser popup window when the
extended component is clicked.
Example:
BrowserWindowOpener browserWindowOpener = new BrowserWindowOpener(new ExternalResource("http://google.com"));
/*
* Apparently, the BrowserWindowOpener method setWindowName uses the HTML5 target
* attribute (no longer deprecated as it was in HTML4).
* So you can use either a frame name, or one of four special attribute values:
* _blank, _self, _parent, _top
*
* browserWindowOpener.setWindowName();
*/
final Button btn = new Button("Click me");
browserWindowOpener.extend(btn);
btn.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
btn.setCaption("clicked");
}
});
More information here.
I dint work on Vaadin yet But I looked into the document. I found that the Link class internally extends AbstractComponent class which has many functions which you can override. like it has addListener function where you need to pass the Component listener as a parameter and can detect the click event and do whatever you want to.
For reference check this
and this too
Hope this will help :)
I'm developing a Wicket application for college and I ran into (a somewhat tricky) problem.
To put some context: I'm making an application that uses a HTML5 player, my solution to this was to give the constructor of the page that contains the player some PageParamameters to make a query and retrieve the sources for the media.
Now my problem is that I'm using a template, so I made a page that puts the Header and the footer automatically, but my player needs the PageParameters to work and I'm trying to make it so it can extend from BasePage, but the constructor from base page also has some parameters so it can dynamically change the text on the header based on the page it is currently on. This makes putting the super() method tricky:
protected BasePage(String tabHeader, String header) {
add(new Label("tab_title", tabHeader));
add(new Header("header", header));
add(new UserPanel("user_panel"));
add(new Footer("footer"));
}
And my player page:
public PlayerPage(PageParameters params) {
String name = params.get("name").toString();
MediaItem item = getItem(name.trim());
add(new Label("tab_title", "MaeGûl - " + name)); //trying to get rid of this
add(new Header("header", item.getName())); //and this
add(new UserPanel("user_panel")); //and this
if (item.getType().equals(ItemTypes.MUSIC)) {
add(new AudioPlayer("player", item.getMediaSources()));
} else if (item.getType().equals(ItemTypes.SERIES)
|| item.getType().equals(ItemTypes.MOVIES))
add(new VideoPlayer("player", item.getMediaSources()));
add(new Footer("footer")); //and this
}
As you may see, if I put the super(tabHeader, header) in my PlayerPage constructor it needs the "name" parameter to update the header and tabHeader of the BasePage, so I'm stupmed...
Any solutions to this?
You may change the BasePage to accept models instead of strings:
protected BasePage(IModel<String> tabHeader, IModel<String> header)
and delegate the retrieval of the values to dedicated models, e.g. derived from AbstractReadOnlyModel:
public PlayerPage(PageParameters params) {
super(new TabHeaderModel(params), new HeaderModel(params));
...
}
There is, of course, a method that can be used by any component to get the PageParameters. It is..
getPage().getPageParameters();
For getPageParameters() to return a non-null value, however, you must have called the Wicket Page constructor with super(params), therefore insisting that your BasePage have a constructor BasePage(PageParameters params).
In fact, after playing around with this for awhile, if you use BookmarkablePageLink and PageParameters for most of your pages, then anything extending Page should only implement the constructor Page(PageParameters params). This doesn't apply if you use session relative pages and a lot of new PlayerPage() type of code.
I need to pull a JavaScript var off a site so I can use it in my code. Following this tutorial, I was able to display the string in an alert message. But what do I have to do to use the string outside of the alert message? Thanks.
EDIT: My code is basically the same as in the tutorial.
Instead of calling AlertDialog, just do something in Java with the value of the "html" parameter, unless I'm completely misunderstanding what you are asking.
String savedHtml = null;
/* An instance of this class will be registered as a JavaScript interface */
class MyJavaScriptInterface
{
#SuppressWarnings("unused")
public void showHTML(String html)
{
savedHtml = html; // this ought to work.
}
}
I'm trying to figure out how to make a dynamically generated csv available to a dygraphs JavaScript.
I'm using a wicket behavior to add the dygraph (JavaScript graph) to my markup like shown in the codesample bellow. Right now I've hardcoded it to use a csv file named "dygraph.csv". I want to change this, and instead make dygraph use the values from String csv, how do I achieve this?
Any help help is greatly appreciated.
public class DygraphBehavior extends AbstractBehavior {
private static final long serialVersionUID = -516501274090062937L;
private static final CompressedResourceReference DYGRAPH_JS = new CompressedResourceReference(DygraphBehavior.class, "dygraph-combined.js");
#Override
public void renderHead(IHeaderResponse response) {
response.renderJavascriptReference(DYGRAPH_JS);
}
#Override
public void onRendered(Component component) {
final String id = component.getId();
Response response = component.getResponse();
response.write(JavascriptUtils.SCRIPT_OPEN_TAG);
response.write("new Dygraph(document.getElementById(\""+id+"\"), \"dygraph.csv\", {rollPeriod: 7, showRoller: true, errorBars: true});");
response.write(JavascriptUtils.SCRIPT_CLOSE_TAG);
}
}
public class Dygraph extends WebPage {
public Dygraph() {
String csv = "Date,ms\n20070101,62\n20070102,62";
add(new ResourceLink<File>("csv", new ByteArrayResource("text/csv", csv.getBytes())));
add(new Label("graphdiv").add(new DygraphBehavior()));
}
}
<div>
<h1>Dygraph:</h1>
<div wicket:id="graphdiv" id="graphdiv" style="width:500px; height:300px;"></div>
<a wicket:id="csv" href="#">dl generated csv</a>
</div>
public class Dygraph extends WebPage {
public Dygraph() {
String csv = "Date,ms\n20070101,62\n20070102,62";
ResourceLink<File> link = new ResourceLink<File>("csv", new ByteArrayResource("text/csv", csv.getBytes()));
add( link );
//this is the url that should be passed to the javascript code
CharSequence url = link.urlFor( IResourceListener.INTERFACE );
add(new Label("graphdiv").add(new DygraphBehavior()));
}
}
There are other solutions based on the scope of your resource, maybe a dynamic shared resource would work better (if your graph parameters can simply be passed as url parameters), but this will work.
The JavaScript needs to see the data in some way after the page has been rendered. So you have two options:
Embed the data in the page (say in a hidden div) and then let JavaScript read the data from there as text.
Create a servlet where the JavaScript can download the data from.
The second option means that your page rendering code has to pass the data somehow to the servlet. You can try to put it into the session but then, it will sit there, occupying RAM. Probably not a problem if it's just a little bit of data and you have only a few users. But if that's not true, option #1 is probably better.