StringResourceModel only works for label - java

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.

Related

How can i get GWT HTML selected text?

i needed an Widget to display text properly, containing HTML elements. Therefore i used the GWT HTML-Widget like that.
HTML text= new HTML(new SafeHtml() {
#Override
public String asString() {
return "<b>TestText</b>";
}
});
Now i would like to select text displayed by that widget, and somehow get the String.
I would like to right click the marked text, and do something with that String
It's also no problem if your ideas making use of other gwt widgets, i am not too focused on that HTML one.
I also have access to Sencha GXT libarys.
Any ideas would be appreciated.
I'm assuming you want the user to select text and then retrieve the selected text on right click. Am I right? I don't recall any way of retrieving selected text in GWT, so I would use pure javascript for that. There is already a thread explaining how to do that with javascript, so you can grab that code and wrap it in a JSNI method:
public class MyClass implements IsWidget {
private final HTML text;
public MyClass() {
text = new HTML(SafeHtmlUtils.fromTrustedString("<b>Some text</b>"));
text.addDomHandler(new ContextMenuHandler() {
#Override
public void onContextMenu(ContextMenuEvent event) {
String test = getSelection();
Window.alert(test);
}
}, ContextMenuEvent.getType());
}
private native String getSelection() /*-{
var text = "";
if ($wnd.getSelection) {
text = $wnd.getSelection().toString();
} else if ($doc.selection && $doc.selection.type != "Control") {
text = $doc.selection.createRange().text;
}
return text;
}-*/;
#Override
public Widget asWidget() {
return text;
}
}
You can use sth like this:
final Label label = new Label("Some text");
label.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
label.getElement().getStyle().setBackgroundColor("#ff0"); //sth. like select
String txt = label.getText(); //get the String
Window.alert(txt); //do sth. with text
}
});
But it works on left click. If you have to use right click, you can use native JS code using eg. jQuery click.
And do not use b tag. It is deprecated in HTML5.
I've actually found a GWT-Libary that can get the selected text.
Watch this https://code.google.com/p/gwt-selection/
After installing the libary i just had to
String currentSelection = Selection.getBrowserRange().getText();
Thank you for answering though - you helped me a lot

Call javascript function from wicket 6, Link's "onclick ()"

I have the following java and html code:
this.leakageModel = new PropertyListView<Leakage> ( "leakage", new ArrayList<Leakage> ()) {
private static final long serialVersionUID = 1L;
#Override
protected void populateItem (final ListItem<Leakage> item) {
Link<String> brandLink = new Link<String> ("brandLink") {
private static final long serialVersionUID = -480222850475280108L;
#Override
public void onClick () {
//change another model in the page to update
//another table when the link is clicked
}
};
brandLink.add (new Label ("brand"));
item.add (brandLink);
} };
add (this.leakageModel);
html file:
<tr wicket:id="leakage" class="testClass">
<td class="testClass">
<a wicket:id="brandLink" href="#">
<span wicket:id="brand"></span>
</a>
</td>
</tr>
What I want to do is to be able to call a javascript function from inside the onClick() method.
The model update that I currently do inside the onClick method works well and updates another table on the page.
However everything I have tried to call a javascript function or change the css style has failed.
For instance:
Adding a css class:
add (new AttributeAppender("class", new Model("anotherclass"), " "));
Using an AjaxLink type instead, and a number of other things I have tried to no avail.
On a related note, my original intention is to hide all rows in the table except the one I have clicked. Maybe I can do this just from the Java code and have no need for Javascript at all, but updating the css as above doesn't work.
Any suggestions as to what am I doing wrong?
On a related note, my original intention is to hide all rows in the
table except the one I have clicked.
Instead of answering your question, I will try to provide a solution to your problem :).
It makes perfect sense to hide the table row via javascript. I would suggest doing it with Jquery as described in Hiding all but first table row with jQuery:
$("#myTbl tr:not(nth-child(3))").hide();
Now, you have to execute the above javascript snippet each time a user clicks your Wicket link. For this, you can for example create your own link class like this:
public class JavascriptLink extends Label{
public JavascriptLink(String id, String label) {
super(id, label);
add(new AttributeAppender("onclick", "...your javascript here..."));
}
}
I leave it to you to combine the jquery with the JavascriptLink to meet your requirements. It should work going in this direction.

How to reference a page with parameters Wicket

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);

Wicket: make a generated csv available to a dygraphs JavaScript

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.

Wicket checkbox that automatically submits its changed value to domain object

What's the cleanest way I can make a checkbox automatically submit the form it belongs to in Wicket? I don't want to include a submit button at all. The checkbox is backed by a boolean field in a domain object ("Account" in this case).
Simplified example with irrelevant parts omitted:
EntityModel<Account> accModel = new EntityModel<Account>(Account.class, id);
PropertyModel<Boolean> model = new PropertyModel<Boolean>(accModel, "enabled");
CheckBox checkBox = new CheckBox("cb", model);
Form form = new Form("form");
form.add(checkBox);
add(form);
HTML:
<form wicket:id="form" id="form" action="">
<input wicket:id="cb" type="checkbox" />
</form>
Edit: To clarify, my goal is just to change the domain object's field (-> value in database too) when the checkbox is toggled. Any (clean, easy) way to achieve that would be fine. (I'm not sure if you actually need the form for this.)
Just overriding wantOnSelectionChangedNotifications() for the checkbox—even without overriding onSelectionChanged()—seems to do what I want.
This way you don't need the form on Java side, so the above code would become:
EntityModel<Account> accModel = new EntityModel<Account>(Account.class, id);
add(new CheckBox("cb", new PropertyModel<Boolean>(accModel, "enabled")){
protected boolean wantOnSelectionChangedNotifications() {
return true;
}
});
Feel free to add better solutions, or a better explanation of what's going on with this approach!
Edit: On closer inspection, I guess the method's Javadoc makes it reasonably clear why this does what I wanted (emphasis mine):
If true, a
roundtrip will be generated with each
selection change, resulting in the
model being updated (of just this
component) and onSelectionChanged
being called.
While this may work, you are far better off using AjaxCheckBox. An anonymous subclass can be wired to receive events immediately as well as make changes to the UI outside the checkbox itself.
final WebMarkupContainer wmc = new WebMarkupContainer("wmc");
final EntityModel<Account> accModel = new EntityModel<Account>(Account.class, id);
wmc.setVisible(false);
wmc.setOutputMarkupPlaceholderTag(true);
form.add(new AjaxCheckBox("cb", new PropertyModel<Boolean>(accModel, "enabled")) {
#Override
protected void onUpdate(AjaxRequestTarget target) {
wmc.setVisible(accModel.isEnabled());
target.addComponent(wmc);
// .. more code to write the entity
}
});
In this contrived example, the WebMarkupContainer would be made visible in sync with the value of the checkbox.

Categories